Skip to content

Commit c838df3

Browse files
committed
Fixed incorrect data offset for 'WriteSingleRegister'-function in 'SendMessage'-window
1 parent 118c487 commit c838df3

28 files changed

+495
-233
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.5) # 2.2 - case insensitive syntax
22

3-
project(ModbusTools VERSION 0.3.2 LANGUAGES CXX)
3+
project(ModbusTools VERSION 0.3.3 LANGUAGES CXX)
44

55
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
66
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")

README.md

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
## Overview
44

5-
ModbusTools are cross-platform (Windows, Linux) Modbus simulator tools (client and server) with GUI to work with standard Modbus Protocol. Modbus Tools are a free, open-source tools with a simple user interface written in C++/Qt. It implements TCP, RTU and ASCII versions of Modbus Protocol.
5+
ModbusTools are cross-platform (Windows, Linux) Modbus simulator tools (client and server) with GUI
6+
to work with standard Modbus Protocol.
7+
Modbus Tools are a free, open-source tools with a simple user interface written in C++/Qt.
8+
It implements TCP, RTU and ASCII versions of Modbus Protocol.
69

710
Software implements such Modbus functions as:
811
* `1 ` (`0x01`) - `READ_COILS`
@@ -24,25 +27,37 @@ https://github.com/serhmarch/ModbusLib
2427

2528
## Release
2629

27-
All compiled binaries are located in latest release:
30+
All compiled binaries are located in the latest release:
2831

2932
https://github.com/serhmarch/ModbusTools/releases
3033

3134
## About Modbus Client
3235

33-
The client implements access to a remote Modbus device. However, the client can work not only with one device, but with several devices that can be connected to a single network, which is especially useful when working with RTU and ASCII protocols, when access to all Modbus servers is realized through a single serial port. However, it can also be useful when using the TCP version of the protocol, for example, if you use the TCP->RTU bridge.
36+
The client implements access to a remote Modbus device.
37+
However, the client can work not only with one device, but with several devices that can be connected to
38+
a single network, which is especially useful when working with RTU and ASCII protocols,
39+
when access to all Modbus servers is realized through a single serial port.
40+
However, it can also be useful when using the TCP version of the protocol, for example,
41+
if you use the TCP->RTU bridge.
3442

3543
![](./doc/images/client_view.png)
3644

37-
All work is done within a single project. The main entities in the project are Port, Device and DataViewItem. Port contains network settings for both TCP/IP and serial ports. Device contains settings for a single device (such as Modbus Unit Address, etc.). The DataViewItem contains a single data unit to be read from the remote device and has many formats to represent the current data.
45+
All work is done within a single project. The main entities in the project are Port, Device and DataViewItem.
46+
Port contains network settings for both TCP/IP and serial ports.
47+
Device contains settings for a single device (such as Modbus Unit Address, etc.).
48+
The DataViewItem contains a single data unit to be read from the remote device and
49+
has many formats to represent the current data.
3850

3951
### Send Message window
4052

41-
The client has the ability to process one separate Modbus function with full configuration of the parameters of this function, view/edit read/write data with the format specified, view Modbus packets of this function:
53+
The client has the ability to process one separate Modbus function with full configuration of the parameters
54+
of this function, view/edit read/write data with the format specified, view Modbus packets of this function:
4255

4356
![](./doc/images/client_sendmessage_window.png)
4457

45-
This window can be opened using menu `Tools->Send Message`. It works in parallel with regular Modbus application messages and can be seen in LogView as regular Modbus message as well.
58+
This window can be opened using menu `Tools->Send Message`.
59+
It works in parallel with regular Modbus application messages and
60+
can be seen in LogView as regular Modbus message as well.
4661

4762
### Scanner window (since v0.3)
4863

@@ -62,15 +77,27 @@ button `To Project` add selected devices, `All To Project` - all devices will be
6277

6378
## About Modbus Server
6479

65-
The server implements Modbus server device and works like Modbus simulator. However, the server can not only simulate single device, but can simulate several devices that can be connected to a single network, which is especially useful when working with RTU and ASCII protocols, when access to all Modbus servers is realized through a single serial port. However, it can also be useful to simulate Modbus network using the TCP version of the protocol, for example, if you use the TCP->RTU bridge, Modbus server can replace this bridge with remote devices for testing purposes.
80+
The server implements Modbus server device and works like Modbus simulator.
81+
However, the server can not only simulate single device, but can simulate several devices that can be connected
82+
to a single network, which is especially useful when working with RTU and ASCII protocols,
83+
when access to all Modbus servers is realized through a single serial port.
84+
However, it can also be useful to simulate Modbus network using the TCP version of the protocol,
85+
for example, if you use the TCP->RTU bridge, Modbus server can replace this bridge with remote devices
86+
for testing purposes.
6687

6788
![](./doc/images/server_view.png)
6889

69-
All work is performing within a single project. The main entities in the project are Port, Device, DataViewItem and Action. Port contains network settings for both TCP/IP and serial ports. Device contains settings for a single device (such as Modbus Unit Address, memory size etc). The DataViewItem contains a single data unit to be read/write from the device and has many formats to represent the current data. Action provides simulation capabilities (automatic change of device memory values).
90+
All work is performing within a single project.
91+
The main entities in the project are Port, Device, DataViewItem and Action.
92+
Port contains network settings for both TCP/IP and serial ports.
93+
Device contains settings for a single device (such as Modbus Unit Address, memory size etc).
94+
The DataViewItem contains a single data unit to be read/write from the device and has many formats to
95+
represent the current data. Action provides simulation capabilities (automatic change of device memory values).
7096

7197
### Server Actions window
7298

73-
The server has the ability to simulate data (actions, automaticaly change values) with predefined action types (`Actions` tab near `LogView`, menu `View->Actions` window and menu `Actions`):
99+
The server has the ability to simulate/change data (actions, automaticaly change values) with predefined
100+
action types (`Actions` tab near `LogView`, menu `View->Actions` window and menu `Actions`):
74101
* `Increment` - changing value by adding or subtracting (if incrementValue < 0) incrementValue
75102
* `Sine` - sine function with parameters of period, shift, amplitude
76103
* `Random` - randomly changing values with specified range

bugfix.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,7 @@ typedef QAtomicInt RefCount_t;
4242
# 0.3.2
4343

4444
* Fixed a bug when changing the log settings does not affect the LogView of client/server
45+
46+
# 0.3.3
47+
48+
* Fixed incorrect data offset for 'WriteSingleRegister'-function in 'SendMessage'-window

changelog.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,10 @@
5858

5959
* Load previously saved project when starting the `client`/`server`
6060
* Mdi Windows are saved/restored their geometry (when saving/opening project) for `client`/`server`
61-
* Fixed bug
61+
* Fixed bugs
62+
63+
# 0.3.3
64+
65+
* Improve client's Scanner Window
66+
* Allow user right to enter port name if it's absent in list of ports in ComboBox
67+
* Fixed bugs
-12.1 KB
Loading

src/client/gui/dialogs/client_dialogdataviewitem.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ void mbClientDialogDataViewItem::setCachedSettings(const MBSETTINGS &settings)
104104
void mbClientDialogDataViewItem::fillFormInner(const MBSETTINGS &settings)
105105
{
106106
const mbClientDataViewItem::Strings &sItem = mbClientDataViewItem::Strings::instance();
107-
const QString &prefix = Strings().cachePrefix;
108107
int period = settings.value(sItem.period).toInt();
109108
ui->spPeriod->setValue(period);
110109
}

src/client/gui/dialogs/client_dialogdevice.cpp

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ mbClientDialogDevice::mbClientDialogDevice(QWidget *parent) :
108108
QStringList ports = Modbus::availableSerialPortList();
109109
Q_FOREACH(const QString &port, ports)
110110
cmb->addItem(port);
111+
cmb->setEditable(true); // Note: Allow user right to enter port name if it's absent in list
111112

112113
// Baud Rate
113114
cmb = ui->cmbBaudRate;
@@ -223,11 +224,11 @@ void mbClientDialogDevice::setCachedSettings(const MBSETTINGS &m)
223224
it = m.find(prefix+ss.parity ); if (it != end) ui->cmbParity ->setCurrentText(it.value().toString());
224225
it = m.find(prefix+ss.stopBits ); if (it != end) ui->cmbStopBits ->setCurrentText(it.value().toString());
225226
it = m.find(prefix+ss.flowControl ); if (it != end) ui->cmbFlowControl ->setCurrentText(it.value().toString());
226-
it = m.find(prefix+ss.timeoutFirstByte); if (it != end) ui->spTimeoutFB ->setValue (it.value().toInt());
227-
it = m.find(prefix+ss.timeoutInterByte); if (it != end) ui->spTimeoutIB ->setValue (it.value().toInt());
227+
it = m.find(prefix+ss.timeoutFirstByte); if (it != end) ui->spTimeoutFB ->setValue (it.value().toInt ());
228+
it = m.find(prefix+ss.timeoutInterByte); if (it != end) ui->spTimeoutIB ->setValue (it.value().toInt ());
228229
it = m.find(prefix+ss.host ); if (it != end) ui->lnHost ->setText (it.value().toString());
229-
it = m.find(prefix+ss.port ); if (it != end) ui->spPort ->setValue (it.value().toInt());
230-
it = m.find(prefix+ss.timeout ); if (it != end) ui->spTimeout ->setValue (it.value().toInt());
230+
it = m.find(prefix+ss.port ); if (it != end) ui->spPort ->setValue (it.value().toInt ());
231+
it = m.find(prefix+ss.timeout ); if (it != end) ui->spTimeout ->setValue (it.value().toInt ());
231232

232233
QString portName = ui->lnPortName->text();
233234
if (!portName.isEmpty())
@@ -246,20 +247,19 @@ void mbClientDialogDevice::fillForm(const MBSETTINGS &m)
246247
const mbClientDevice::Strings &ms = mbClientDevice::Strings::instance();
247248

248249
auto it = m.find(Strings::instance().createDeviceForPort);
249-
if (it != m.end())
250+
auto end = m.end();
251+
252+
if (it != end)
250253
{
251254
ui->cmbPort->setEnabled(false);
252-
QString portName = it.value().toString();
253-
setPortName(portName);
255+
setPortName(it.value().toString());
254256
}
255257
else
256258
{
257-
ui->spUnit->setValue(m.value(ms.unit).toInt());
258259
mbCoreDialogDevice::fillForm(m);
259-
//----------------------- PORT -----------------------
260260
ui->cmbPort->setEnabled(true);
261-
QString portName = m.value(ms.portName).toString();
262-
setPortName(portName);
261+
it = m.find(ms.unit ); if (it != end) ui->spUnit->setValue (it.value().toInt ());
262+
it = m.find(ms.portName); if (it != end) this-> setPortName(it.value().toString());
263263
}
264264
}
265265

@@ -312,19 +312,22 @@ void mbClientDialogDevice::fillPortForm(const MBSETTINGS &m)
312312
mbClientPort::Strings ms = mbClientPort::Strings();
313313
Modbus::Strings ss = Modbus::Strings::instance();
314314

315-
ui->lnPortName ->setText (m.value(ms.name ).toString());
316-
ui->cmbPortType ->setCurrentText(m.value(ms.type ).toString());
317-
ui->cmbSerialPortName->setCurrentText(m.value(ss.serialPortName ).toString());
318-
ui->cmbBaudRate ->setCurrentText(m.value(ss.baudRate ).toString());
319-
ui->cmbDataBits ->setCurrentText(m.value(ss.dataBits ).toString());
320-
ui->cmbParity ->setCurrentText(m.value(ss.parity ).toString());
321-
ui->cmbStopBits ->setCurrentText(m.value(ss.stopBits ).toString());
322-
ui->cmbFlowControl ->setCurrentText(m.value(ss.flowControl ).toString());
323-
ui->spTimeoutFB ->setValue (m.value(ss.timeoutFirstByte).toInt());
324-
ui->spTimeoutIB ->setValue (m.value(ss.timeoutInterByte).toInt());
325-
ui->lnHost ->setText (m.value(ss.host ).toString());
326-
ui->spPort ->setValue (m.value(ss.port ).toInt());
327-
ui->spTimeout ->setValue (m.value(ss.timeout ).toInt());
315+
MBSETTINGS::const_iterator it;
316+
MBSETTINGS::const_iterator end = m.end();
317+
318+
it = m.find(ms.name ); if (it != end) ui->lnPortName ->setText (it.value().toString());
319+
it = m.find(ms.type ); if (it != end) ui->cmbPortType ->setCurrentText(it.value().toString());
320+
it = m.find(ss.serialPortName ); if (it != end) ui->cmbSerialPortName->setCurrentText(it.value().toString());
321+
it = m.find(ss.baudRate ); if (it != end) ui->cmbBaudRate ->setCurrentText(it.value().toString());
322+
it = m.find(ss.dataBits ); if (it != end) ui->cmbDataBits ->setCurrentText(it.value().toString());
323+
it = m.find(ss.parity ); if (it != end) ui->cmbParity ->setCurrentText(it.value().toString());
324+
it = m.find(ss.stopBits ); if (it != end) ui->cmbStopBits ->setCurrentText(it.value().toString());
325+
it = m.find(ss.flowControl ); if (it != end) ui->cmbFlowControl ->setCurrentText(it.value().toString());
326+
it = m.find(ss.timeoutFirstByte); if (it != end) ui->spTimeoutFB ->setValue (it.value().toInt ());
327+
it = m.find(ss.timeoutInterByte); if (it != end) ui->spTimeoutIB ->setValue (it.value().toInt ());
328+
it = m.find(ss.host ); if (it != end) ui->lnHost ->setText (it.value().toString());
329+
it = m.find(ss.port ); if (it != end) ui->spPort ->setValue (it.value().toInt ());
330+
it = m.find(ss.timeout ); if (it != end) ui->spTimeout ->setValue (it.value().toInt ());
328331
}
329332

330333
void mbClientDialogDevice::fillPortData(MBSETTINGS &m) const

src/client/gui/dialogs/client_dialogport.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,37 +70,38 @@ mbClientDialogPort::~mbClientDialogPort()
7070

7171
MBSETTINGS mbClientDialogPort::cachedSettings() const
7272
{
73-
Modbus::Strings ss = Modbus::Strings::instance();
73+
Modbus::Strings vs = Modbus::Strings::instance();
7474
const QString &prefix = Strings().cachePrefix;
7575
MBSETTINGS m = mbCoreDialogPort::cachedSettings();
76-
m[prefix+ss.host] = ui->lnHost->text();
76+
m[prefix+vs.host] = ui->lnHost->text();
7777
return m;
7878
}
7979

8080
void mbClientDialogPort::setCachedSettings(const MBSETTINGS &m)
8181
{
8282
mbCoreDialogPort::setCachedSettings(m);
8383

84-
Modbus::Strings ss = Modbus::Strings::instance();
84+
Modbus::Strings vs = Modbus::Strings::instance();
8585
const QString &prefix = Strings().cachePrefix;
8686
MBSETTINGS::const_iterator it;
8787
MBSETTINGS::const_iterator end = m.end();
8888
//bool ok;
8989

90-
it = m.find(prefix+ss.host); if (it != end) ui->lnHost->setText(it.value().toString());
91-
90+
it = m.find(prefix+vs.host); if (it != end) ui->lnHost->setText(it.value().toString());
9291
}
9392

9493
void mbClientDialogPort::fillFormInner(const MBSETTINGS &settings)
9594
{
96-
Modbus::Strings ss = Modbus::Strings::instance();
95+
Modbus::Strings vs = Modbus::Strings::instance();
96+
MBSETTINGS::const_iterator it;
97+
MBSETTINGS::const_iterator end = settings.end();
9798

98-
ui->lnHost->setText(settings.value(ss.host).toString());
99+
it = settings.find(vs.host); if (it != end) ui->lnHost->setText(it.value().toString());
99100
}
100101

101102
void mbClientDialogPort::fillDataInner(MBSETTINGS &settings) const
102103
{
103-
Modbus::Strings ss = Modbus::Strings::instance();
104+
Modbus::Strings vs = Modbus::Strings::instance();
104105

105-
settings[ss.host] = ui->lnHost->text();
106+
settings[vs.host] = ui->lnHost->text();
106107
}

src/client/gui/scanner/client_scanner.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ void mbClientScanner::clear()
425425
QWriteLocker _(&m_lock);
426426
m_deviceInfoList.clear();
427427
setStatDevice(QString());
428+
setStatFound (0);
428429
setStatCountTx(0);
429430
setStatCountRx(0);
430431
setStatPercent(0);
@@ -454,6 +455,15 @@ void mbClientScanner::setStatDevice(const QString &device)
454455
}
455456
}
456457

458+
void mbClientScanner::setStatFound(quint32 count)
459+
{
460+
if (m_stat.found != count)
461+
{
462+
m_stat.found = count;
463+
Q_EMIT statFoundChanged(count);
464+
}
465+
}
466+
457467
void mbClientScanner::setStatCountTx(quint32 count)
458468
{
459469
if (m_stat.countTx != count)

src/client/gui/scanner/client_scanner.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class mbClientScanner : public QObject
128128
QString deviceInfoStr(int i) const;
129129
void deviceAdd(const Modbus::Settings &settings);
130130
inline QString statDevice () const { return m_stat.device ; }
131+
inline quint32 statFound () const { return m_stat.found ; }
131132
inline quint32 statCountTx() const { return m_stat.countTx; }
132133
inline quint32 statCountRx() const { return m_stat.countRx; }
133134
inline quint32 statPercent() const { return m_stat.percent; }
@@ -138,6 +139,7 @@ class mbClientScanner : public QObject
138139
void startScanning(const Modbus::Settings &settings);
139140
void stopScanning();
140141
void setStatDevice(const QString &device);
142+
void setStatFound (quint32 count);
141143
void setStatCountTx(quint32 count);
142144
void setStatCountRx(quint32 count);
143145
void setStatPercent(quint32 percent);
@@ -147,6 +149,7 @@ class mbClientScanner : public QObject
147149
void cleared();
148150
void stateChanged(bool run);
149151
void statDeviceChanged(const QString &name);
152+
void statFoundChanged (quint32 count);
150153
void statCountTxChanged(quint32 count);
151154
void statCountRxChanged(quint32 count);
152155
void statPercentChanged(quint32 percent);
@@ -173,13 +176,14 @@ private Q_SLOTS:
173176
{
174177
Statistics()
175178
{
176-
179+
found = 0;
177180
countTx = 0;
178181
countRx = 0;
179182
percent = 0;
180183
}
181184

182-
QString device;
185+
QString device ;
186+
quint32 found ;
183187
quint32 countTx;
184188
quint32 countRx;
185189
quint32 percent;

0 commit comments

Comments
 (0)