Skip to content

Commit d7a0efc

Browse files
committed
Merge remote-tracking branch 'origin/dev'
2 parents 431e167 + 18b7dad commit d7a0efc

61 files changed

Lines changed: 6360 additions & 664 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Open ModSim
22
Open ModSim is a free implimentation of modbus slave (server) utility for modbus-tcp and modbus-rtu protocols.
33

4-
![image](https://github.com/sanny32/OpenModSim/assets/13627951/43d1b90d-b56b-400d-8dca-2903e23e56a9)
4+
![image](https://github.com/sanny32/OpenModSim/assets/13627951/3912005f-df9b-41b4-b6f5-33ebc76a908c)
55

6-
![image](https://github.com/sanny32/OpenModSim/assets/13627951/e805d429-7657-4355-869b-7559f11ea3d9)
76

7+
![image](https://github.com/sanny32/OpenModSim/assets/13627951/b40eca28-7a34-46dc-9a50-9b16dc1becf1)
88

99

1010
## Features
@@ -38,7 +38,18 @@ Registers
3838
Random - simulate register randomly
3939
Increment - simulate register from Low Limit to High Limit with a given Step
4040
Decrement - simulate register from High Limit to Low Limit with a given Step
41-
41+
42+
Modbus Logging
43+
44+
![image](https://github.com/sanny32/OpenModSim/assets/13627951/1ebf4973-44a5-4464-aada-26aa751f65da)
45+
46+
47+
## Extended Featues
48+
49+
Modbus Message Parser
50+
51+
![image](https://github.com/sanny32/OpenModScan/assets/13627951/86a82340-015e-4ee9-a483-b5ab83527cc1)
52+
4253
## Scripting
4354
From version 1.2.0 Open ModSim supports scripting. Qt runtime implements the [ECMAScript Language Specification](http://www.ecma-international.org/publications/standards/Ecma-262.htm) standard, so Javascript is used to write code.
4455

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
#include <QRegularExpressionValidator>
2+
#include <QMimeData>
3+
#include "formatutils.h"
4+
#include "bytelisttextedit.h"
5+
6+
///
7+
/// \brief ByteListTextEdit::ByteListTextEdit
8+
/// \param parent
9+
///
10+
ByteListTextEdit::ByteListTextEdit(QWidget* parent)
11+
:QPlainTextEdit(parent)
12+
,_separator(' ')
13+
,_validator(nullptr)
14+
{
15+
setInputMode(DecMode);
16+
connect(this, &QPlainTextEdit::textChanged, this, &ByteListTextEdit::on_textChanged);
17+
}
18+
19+
///
20+
/// \brief ByteListTextEdit::ByteListTextEdit
21+
/// \param mode
22+
/// \param parent
23+
///
24+
ByteListTextEdit::ByteListTextEdit(InputMode mode, QWidget *parent)
25+
:QPlainTextEdit(parent)
26+
,_separator(' ')
27+
,_validator(nullptr)
28+
{
29+
setInputMode(mode);
30+
connect(this, &QPlainTextEdit::textChanged, this, &ByteListTextEdit::on_textChanged);
31+
}
32+
33+
///
34+
/// \brief ByteListTextEdit::value
35+
/// \return
36+
///
37+
QByteArray ByteListTextEdit::value() const
38+
{
39+
return _value;
40+
}
41+
42+
///
43+
/// \brief ByteListTextEdit::setValue
44+
/// \param value
45+
///
46+
void ByteListTextEdit::setValue(const QByteArray& value)
47+
{
48+
switch(_inputMode)
49+
{
50+
case DecMode:
51+
{
52+
const auto text = formatByteArray(DataDisplayMode::Decimal, value);
53+
if(text != toPlainText())
54+
setPlainText(formatByteArray(DataDisplayMode::Decimal, value));
55+
}
56+
break;
57+
58+
case HexMode:
59+
{
60+
const auto text = formatByteArray(DataDisplayMode::Hex, value);
61+
if(text != toPlainText())
62+
setPlainText(formatByteArray(DataDisplayMode::Hex, value));
63+
}
64+
break;
65+
}
66+
67+
if(value != _value)
68+
{
69+
_value = value;
70+
emit valueChanged(_value);
71+
}
72+
}
73+
74+
///
75+
/// \brief ByteListTextEdit::inputMode
76+
/// \return
77+
///
78+
ByteListTextEdit::InputMode ByteListTextEdit::inputMode() const
79+
{
80+
return _inputMode;
81+
}
82+
83+
///
84+
/// \brief ByteListTextEdit::setInputMode
85+
/// \param mode
86+
///
87+
void ByteListTextEdit::setInputMode(InputMode mode)
88+
{
89+
_inputMode = mode;
90+
91+
if(_validator)
92+
{
93+
delete _validator;
94+
_validator = nullptr;
95+
}
96+
97+
const auto sep = (_separator == ' ')? "\\s" : QString(_separator);
98+
switch(_inputMode)
99+
{
100+
case DecMode:
101+
_validator =new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[" + sep + "]{0,1})*"), this);
102+
break;
103+
104+
case HexMode:
105+
_validator = new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[" + sep + "]{0,1})*"), this);
106+
break;
107+
}
108+
109+
setValue(_value);
110+
}
111+
112+
///
113+
/// \brief ByteListTextEdit::text
114+
/// \return
115+
///
116+
QString ByteListTextEdit::text() const
117+
{
118+
return toPlainText();
119+
}
120+
121+
///
122+
/// \brief ByteListTextEdit::setText
123+
/// \param text
124+
///
125+
void ByteListTextEdit::setText(const QString& text)
126+
{
127+
setPlainText(text);
128+
updateValue();
129+
}
130+
131+
///
132+
/// \brief ByteListTextEdit::focusOutEvent
133+
/// \param event
134+
///
135+
void ByteListTextEdit::focusOutEvent(QFocusEvent* e)
136+
{
137+
updateValue();
138+
QPlainTextEdit::focusOutEvent(e);
139+
}
140+
141+
///
142+
/// \brief ByteListTextEdit::keyPressEvent
143+
/// \param e
144+
///
145+
void ByteListTextEdit::keyPressEvent(QKeyEvent *e)
146+
{
147+
if(!_validator)
148+
{
149+
QPlainTextEdit::keyPressEvent(e);
150+
return;
151+
}
152+
153+
if(e->key() == Qt::Key_Enter ||
154+
e->key() == Qt::Key_Return)
155+
{
156+
return;
157+
}
158+
159+
int pos = 0;
160+
auto text = toPlainText() + e->text();
161+
const auto state = _validator->validate(text, pos);
162+
163+
if(state == QValidator::Acceptable ||
164+
e->key() == Qt::Key_Backspace ||
165+
e->key() == Qt::Key_Delete ||
166+
e->key() == Qt::Key_Space ||
167+
e->matches(QKeySequence::Cut) ||
168+
e->matches(QKeySequence::Copy) ||
169+
e->matches(QKeySequence::Paste) ||
170+
e->matches(QKeySequence::Undo) ||
171+
e->matches(QKeySequence::Redo) ||
172+
e->matches(QKeySequence::SelectAll))
173+
{
174+
QPlainTextEdit::keyPressEvent(e);
175+
}
176+
}
177+
178+
///
179+
/// \brief ByteListTextEdit::canInsertFromMimeData
180+
/// \param source
181+
/// \return
182+
///
183+
bool ByteListTextEdit::canInsertFromMimeData(const QMimeData* source) const
184+
{
185+
int pos = 0;
186+
auto text = source->text().trimmed();
187+
const auto state = _validator->validate(text, pos);
188+
189+
return state == QValidator::Acceptable;
190+
}
191+
192+
///
193+
/// \brief ByteListTextEdit::insertFromMimeData
194+
/// \param source
195+
///
196+
void ByteListTextEdit::insertFromMimeData(const QMimeData* source)
197+
{
198+
int pos = 0;
199+
auto text = source->text().trimmed();
200+
const auto state = _validator->validate(text, pos);
201+
202+
if(state == QValidator::Acceptable)
203+
{
204+
QPlainTextEdit::insertFromMimeData(source);
205+
updateValue();
206+
}
207+
}
208+
209+
///
210+
/// \brief ByteListTextEdit::on_textChanged
211+
///
212+
void ByteListTextEdit::on_textChanged()
213+
{
214+
QByteArray value;
215+
switch(_inputMode)
216+
{
217+
case DecMode:
218+
{
219+
for(auto&& s : text().split(_separator))
220+
{
221+
bool ok;
222+
const quint8 v = s.trimmed().toUInt(&ok);
223+
if(ok) value.push_back(v);
224+
}
225+
}
226+
break;
227+
228+
case HexMode:
229+
{
230+
for(auto&& s : text().split(_separator))
231+
{
232+
bool ok;
233+
const quint8 v = s.trimmed().toUInt(&ok, 16);
234+
if(ok) value.push_back(v);
235+
}
236+
}
237+
break;
238+
}
239+
240+
if(value != _value)
241+
{
242+
_value = value;
243+
emit valueChanged(_value);
244+
}
245+
}
246+
247+
///
248+
/// \brief ByteListTextEdit::updateValue
249+
///
250+
void ByteListTextEdit::updateValue()
251+
{
252+
QByteArray value;
253+
switch(_inputMode)
254+
{
255+
case DecMode:
256+
{
257+
for(auto&& s : text().split(_separator))
258+
{
259+
bool ok;
260+
const quint8 v = s.trimmed().toUInt(&ok);
261+
if(ok) value.push_back(v);
262+
}
263+
264+
if(!value.isEmpty()) setValue(value);
265+
else setValue(_value);
266+
}
267+
break;
268+
269+
case HexMode:
270+
{
271+
for(auto&& s : text().split(_separator))
272+
{
273+
bool ok;
274+
const quint8 v = s.trimmed().toUInt(&ok, 16);
275+
if(ok) value.push_back(v);
276+
}
277+
278+
if(!value.isEmpty()) setValue(value);
279+
else setValue(_value);
280+
}
281+
break;
282+
}
283+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#ifndef BYTELISTTEXTEDIT_H
2+
#define BYTELISTTEXTEDIT_H
3+
4+
#include <QValidator>
5+
#include <QPlainTextEdit>
6+
7+
///
8+
/// \brief The ByteListTextEdit class
9+
///
10+
class ByteListTextEdit : public QPlainTextEdit
11+
{
12+
Q_OBJECT
13+
14+
public:
15+
enum InputMode
16+
{
17+
DecMode = 0,
18+
HexMode
19+
};
20+
21+
explicit ByteListTextEdit(QWidget* parent = nullptr);
22+
explicit ByteListTextEdit(InputMode mode, QWidget *parent = nullptr);
23+
24+
QByteArray value() const;
25+
void setValue(const QByteArray& value);
26+
27+
InputMode inputMode() const;
28+
void setInputMode(InputMode mode);
29+
30+
QString text() const;
31+
void setText(const QString& text);
32+
33+
bool isEmpty() const {
34+
return text().isEmpty();
35+
}
36+
37+
signals:
38+
void valueChanged(const QByteArray& value);
39+
40+
protected:
41+
void focusOutEvent(QFocusEvent* e) override;
42+
void keyPressEvent(QKeyEvent* e) override;
43+
bool canInsertFromMimeData(const QMimeData* source) const override;
44+
void insertFromMimeData(const QMimeData* source) override;
45+
46+
private slots:
47+
void on_textChanged();
48+
49+
private:
50+
void updateValue();
51+
52+
private:
53+
InputMode _inputMode;
54+
QByteArray _value;
55+
QChar _separator;
56+
QValidator* _validator;
57+
};
58+
59+
#endif // BYTELISTTEXTEDIT_H

0 commit comments

Comments
 (0)