Skip to content

Commit 4f51481

Browse files
more consistent naming for modbus participants (Server,Client)
1 parent 3d80fd0 commit 4f51481

File tree

6 files changed

+85
-66
lines changed

6 files changed

+85
-66
lines changed

README.md

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,46 @@ As an alternative to the ```git submodule``` commands, the ```--recursive``` opt
1616

1717
## Use
1818
```
19-
Modbus_TCP_client_shm [OPTION...]
19+
modbus-tcp-client-shm [OPTION...]
2020
21-
-i, --ip arg ip to listen for incoming connections (default: 0.0.0.0)
22-
-p, --port arg port to listen for incoming connections (default: 502)
23-
-n, --name-prefix arg shared memory name prefix (default: modbus_)
24-
--do-registers arg number of digital output registers (default: 65536)
25-
--di-registers arg number of digital input registers (default: 65536)
26-
--ao-registers arg number of analog output registers (default: 65536)
27-
--ai-registers arg number of analog input registers (default: 65536)
28-
-m, --monitor output all incoming and outgoing packets to stdout
29-
-r, --reconnect do not terminate if Master disconnects.
30-
-h, --help print usage
21+
-i, --ip arg ip to listen for incoming connections (default: 0.0.0.0)
22+
-p, --port arg port to listen for incoming connections (default: 502)
23+
-n, --name-prefix arg shared memory name prefix (default: modbus_)
24+
--do-registers arg number of digital output registers (default: 65536)
25+
--di-registers arg number of digital input registers (default: 65536)
26+
--ao-registers arg number of analog output registers (default: 65536)
27+
--ai-registers arg number of analog input registers (default: 65536)
28+
-m, --monitor output all incoming and outgoing packets to stdout
29+
-r, --reconnect do not terminate if the Modbus Server disconnects.
30+
--byte-timeout arg timeout interval in seconds between two consecutive bytes of the same message. In most
31+
cases it is sufficient to set the response timeout. Fractional values are possible.
32+
--response-timeout arg set the timeout interval in seconds used to wait for a response. When a byte timeout is
33+
set, if the elapsed time for the first byte of response is longer than the given timeout,
34+
a timeout is detected. When byte timeout is disabled, the full confirmation response must
35+
be received before expiration of the response timeout. Fractional values are possible.
36+
-t, --tcp-timeout arg tcp timeout in seconds. Set to 0 to use the system defaults (not recommended). (default:
37+
5)
38+
--force Force the use of the shared memory even if it already exists. Do not use this option per
39+
default! It should only be used if the shared memory of an improperly terminated instance
40+
continues to exist as an orphan and is no longer used.
41+
-s, --separate arg Use a separate shared memory for requests with the specified client id. The the client id
42+
(as hex value) is appended to the shared memory prefix (e.g. modbus_fc_DO). You can
43+
specify multiple client ids by separating them with ','. Use --separate-all to generate
44+
separate shared memories for all possible client ids.
45+
--separate-all like --separate, but for all client ids (creates 1028 shared memory files! check/set
46+
'ulimit -n' before using this option.)
47+
-h, --help print usage
48+
--version print version information
49+
--license show licences
3150
3251
3352
The modbus registers are mapped to shared memory objects:
34-
type | name | master-access | shm name
35-
-----|---------------------------|-----------------|----------------
36-
DO | Discrete Output Coils | read-write | <name-prefix>DO
37-
DI | Discrete Input Coils | read-only | <name-prefix>DI
38-
AO | Discrete Output Registers | read-write | <name-prefix>AO
39-
AI | Discrete Input Registers | read-only | <name-prefix>AI
53+
type | name | mb-server-access | shm name
54+
-----|---------------------------|------------------|----------------
55+
DO | Discrete Output Coils | read-write | <name-prefix>DO
56+
DI | Discrete Input Coils | read-only | <name-prefix>DI
57+
AO | Discrete Output Registers | read-write | <name-prefix>AO
58+
AI | Discrete Input Registers | read-only | <name-prefix>AI
4059
```
4160

4261
### Use privileged ports

docs/index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@ One for each register type:
1313
- Discrete Input Registers (AI)
1414

1515
All registers are initialized with 0 at the beginning.
16-
The Modbus master reads and writes directly the values from these shared memories.
16+
The Modbus server reads and writes directly the values from these shared memories.
1717

1818
The actual functionality of the client is realized by applications that read data from or write data to the shared memory.
1919

2020

2121
## Use the Application
2222
The application can be started completely without command line arguments.
2323
In this case the client listens for connections on all IPs on port 502 (the default modbus port).
24-
The application terminates if the master disconnects.
24+
The application terminates if the Modbus server disconnects.
2525

2626
The arguments ```--port``` and ```--ip``` can be used to specify port and ip to listen to.
2727

2828
By using the command line argument ```--monitor``` all incoming and outgoing packets are printed on stdout.
29-
This option should be used carefully, as it generates large amounts of output depending on the masters polling cycle and the number of used registers.
29+
This option should be used carefully, as it generates large amounts of output depending on the Modbus servers polling cycle and the number of used registers.
3030

31-
The ```--reconnect``` option can be used to specify that the application is not terminated when the master disconnects, but waits for a new connection.
31+
The ```--reconnect``` option can be used to specify that the application is not terminated when the Modbus Server disconnects, but waits for a new connection.
3232

3333
The client creates four shared memories and names them ```modbus_DO```, ```modbus_DI```, ```modbus_AO``` and ```modbus_AI``` by default.
3434
The prefix modbus_ can be changed via the argument ```--name-prefix```.

src/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33

44
target_sources(${Target} PRIVATE main.cpp)
55
target_sources(${Target} PRIVATE modbus_shm.cpp)
6-
target_sources(${Target} PRIVATE Modbus_TCP_Slave.cpp)
6+
target_sources(${Target} PRIVATE Modbus_TCP_Client.cpp)
77
target_sources(${Target} PRIVATE license.cpp)
88

99

1010
# ---------------------------------------- header files (*.jpp, *.h, ...) ----------------------------------------------
1111
# ======================================================================================================================
1212
target_sources(${Target} PRIVATE modbus_shm.hpp)
13-
target_sources(${Target} PRIVATE Modbus_TCP_Slave.hpp)
13+
target_sources(${Target} PRIVATE Modbus_TCP_Client.hpp)
1414
target_sources(${Target} PRIVATE license.hpp)
1515

1616

src/Modbus_TCP_Slave.cpp renamed to src/Modbus_TCP_Client.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* This program is free software. You can redistribute it and/or modify it under the terms of the MIT License.
44
*/
55

6-
#include "Modbus_TCP_Slave.hpp"
6+
#include "Modbus_TCP_Client.hpp"
77

88
#include <algorithm>
99
#include <arpa/inet.h>
@@ -23,7 +23,7 @@ namespace TCP {
2323

2424
static constexpr int MAX_REGS = 0x10000;
2525

26-
Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t *mapping, std::size_t tcp_timeout) {
26+
Client::Client(const std::string &ip, unsigned short port, modbus_mapping_t *mapping, std::size_t tcp_timeout) {
2727
// create modbus object
2828
modbus = modbus_new_tcp(ip.c_str(), static_cast<int>(port));
2929
if (modbus == nullptr) {
@@ -62,7 +62,7 @@ Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t *mappi
6262
#endif
6363
}
6464

65-
Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t **mappings, std::size_t tcp_timeout) {
65+
Client::Client(const std::string &ip, unsigned short port, modbus_mapping_t **mappings, std::size_t tcp_timeout) {
6666
// create modbus object
6767
modbus = modbus_new_tcp(ip.c_str(), static_cast<int>(port));
6868
if (modbus == nullptr) {
@@ -98,7 +98,7 @@ Slave::Slave(const std::string &ip, unsigned short port, modbus_mapping_t **mapp
9898
#endif
9999
}
100100

101-
void Slave::listen() {
101+
void Client::listen() {
102102
// create tcp socket
103103
socket = modbus_tcp_listen(modbus, 1);
104104
if (socket == -1) {
@@ -116,7 +116,7 @@ void Slave::listen() {
116116
}
117117

118118
#ifdef OS_LINUX
119-
void Slave::set_tcp_timeout(std::size_t tcp_timeout) {
119+
void Client::set_tcp_timeout(std::size_t tcp_timeout) {
120120
// set user timeout (~= timeout for tcp connection)
121121
unsigned user_timeout = static_cast<unsigned>(tcp_timeout) * 1000;
122122
int tmp = setsockopt(socket, IPPROTO_TCP, TCP_USER_TIMEOUT, &user_timeout, sizeof(tcp_timeout));
@@ -148,7 +148,7 @@ void Slave::set_tcp_timeout(std::size_t tcp_timeout) {
148148
#endif
149149

150150

151-
Slave::~Slave() {
151+
Client::~Client() {
152152
if (modbus != nullptr) {
153153
modbus_close(modbus);
154154
modbus_free(modbus);
@@ -157,14 +157,14 @@ Slave::~Slave() {
157157
if (socket != -1) { close(socket); }
158158
}
159159

160-
void Slave::set_debug(bool debug) {
160+
void Client::set_debug(bool debug) {
161161
if (modbus_set_debug(modbus, debug)) {
162162
const std::string error_msg = modbus_strerror(errno);
163163
throw std::runtime_error("failed to enable modbus debugging mode: " + error_msg);
164164
}
165165
}
166166

167-
std::string Slave::connect_client() {
167+
std::string Client::connect_client() {
168168
int tmp = modbus_tcp_accept(modbus, &socket);
169169
if (tmp < 0) {
170170
const std::string error_msg = modbus_strerror(errno);
@@ -189,7 +189,7 @@ std::string Slave::connect_client() {
189189
return sstr.str();
190190
}
191191

192-
bool Slave::handle_request() {
192+
bool Client::handle_request() {
193193
// receive modbus request
194194
uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
195195
int rc = modbus_receive(modbus, query);
@@ -232,7 +232,7 @@ static inline timeout_t double_to_timeout_t(double timeout) {
232232
return ret;
233233
}
234234

235-
void Slave::set_byte_timeout(double timeout) {
235+
void Client::set_byte_timeout(double timeout) {
236236
const auto T = double_to_timeout_t(timeout);
237237
auto ret = modbus_set_byte_timeout(modbus, T.sec, T.usec);
238238

@@ -242,7 +242,7 @@ void Slave::set_byte_timeout(double timeout) {
242242
}
243243
}
244244

245-
void Slave::set_response_timeout(double timeout) {
245+
void Client::set_response_timeout(double timeout) {
246246
const auto T = double_to_timeout_t(timeout);
247247
auto ret = modbus_set_response_timeout(modbus, T.sec, T.usec);
248248

@@ -252,7 +252,7 @@ void Slave::set_response_timeout(double timeout) {
252252
}
253253
}
254254

255-
double Slave::get_byte_timeout() {
255+
double Client::get_byte_timeout() {
256256
timeout_t timeout {};
257257

258258
auto ret = modbus_get_byte_timeout(modbus, &timeout.sec, &timeout.usec);
@@ -265,7 +265,7 @@ double Slave::get_byte_timeout() {
265265
return static_cast<double>(timeout.sec) + (static_cast<double>(timeout.usec) / (1000.0 * 1000.0));
266266
}
267267

268-
double Slave::get_response_timeout() {
268+
double Client::get_response_timeout() {
269269
timeout_t timeout {};
270270

271271
auto ret = modbus_get_response_timeout(modbus, &timeout.sec, &timeout.usec);

src/Modbus_TCP_Slave.hpp renamed to src/Modbus_TCP_Client.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace TCP {
1414

1515
constexpr std::size_t MAX_CLIENT_IDS = 256;
1616

17-
//! Modbus TCP slave
18-
class Slave {
17+
//! Modbus TCP client
18+
class Client {
1919
private:
2020
modbus_t *modbus; //!< modbus object (see libmodbus library)
2121
modbus_mapping_t
@@ -24,36 +24,36 @@ class Slave {
2424
int socket = -1; //!< socket of the modbus connection
2525

2626
public:
27-
/*! \brief create modbus slave (TCP server)
27+
/*! \brief create modbus client (TCP server)
2828
*
2929
* @param ip ip to listen for incoming connections (default 0.0.0.0 (any))
3030
* @param port port to listen for incoming connections (default 502)
3131
* @param mapping modbus mapping object for all client ids
3232
* nullptr: an mapping object with maximum size is generated
3333
* @param tcp_timeout tcp timeout (currently only available on linux systems)
3434
*/
35-
explicit Slave(const std::string &ip = "0.0.0.0",
35+
explicit Client(const std::string &ip = "0.0.0.0",
3636
short unsigned int port = 502,
3737
modbus_mapping_t *mapping = nullptr,
3838
std::size_t tcp_timeout = 5);
3939

4040
/**
41-
* @brief create modbus slave (TCP server) with dedicated mappings per client id
41+
* @brief create modbus client (TCP server) with dedicated mappings per client id
4242
*
4343
* @param ip ip to listen for incoming connections
4444
* @param port port to listen for incoming connections
4545
* @param mappings modbus mappings (one for each possible id)
4646
* @param tcp_timeout tcp timeout (currently only available on linux systems)
4747
*/
48-
Slave(const std::string &ip,
48+
Client(const std::string &ip,
4949
short unsigned int port,
5050
modbus_mapping_t *mappings[MAX_CLIENT_IDS],
5151
std::size_t tcp_timeout = 5);
5252

53-
/*! \brief destroy the modbus slave
53+
/*! \brief destroy the modbus client
5454
*
5555
*/
56-
~Slave();
56+
~Client();
5757

5858
/*! \brief enable/disable debugging output
5959
*
@@ -67,7 +67,7 @@ class Slave {
6767
*/
6868
std::string connect_client();
6969

70-
/*! \brief wait for request from Master and generate reply
70+
/*! \brief wait for request from Modbus Server and generate reply
7171
*
7272
* @return true: connection closed
7373
*/

src/main.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# pragma GCC diagnostic pop
2929
#endif
3030

31-
#include "Modbus_TCP_Slave.hpp"
31+
#include "Modbus_TCP_Client.hpp"
3232
#include "license.hpp"
3333
#include "modbus_shm.hpp"
3434

@@ -123,7 +123,7 @@ int main(int argc, char **argv) {
123123
("m,monitor",
124124
"output all incoming and outgoing packets to stdout")
125125
("r,reconnect",
126-
"do not terminate if the Modbus master disconnects.")
126+
"do not terminate if the Modbus Server disconnects.")
127127
("byte-timeout",
128128
"timeout interval in seconds between two consecutive bytes of the same message. "
129129
"In most cases it is sufficient to set the response timeout. "
@@ -179,12 +179,12 @@ int main(int argc, char **argv) {
179179
std::cout << options.help() << std::endl;
180180
std::cout << std::endl;
181181
std::cout << "The modbus registers are mapped to shared memory objects:" << std::endl;
182-
std::cout << " type | name | master-access | shm name" << std::endl;
183-
std::cout << " -----|---------------------------|-----------------|----------------" << std::endl;
184-
std::cout << " DO | Discrete Output Coils | read-write | <name-prefix>DO" << std::endl;
185-
std::cout << " DI | Discrete Input Coils | read-only | <name-prefix>DI" << std::endl;
186-
std::cout << " AO | Discrete Output Registers | read-write | <name-prefix>AO" << std::endl;
187-
std::cout << " AI | Discrete Input Registers | read-only | <name-prefix>AI" << std::endl;
182+
std::cout << " type | name | mb-server-access | shm name" << std::endl;
183+
std::cout << " -----|---------------------------|------------------|----------------" << std::endl;
184+
std::cout << " DO | Discrete Output Coils | read-write | <name-prefix>DO" << std::endl;
185+
std::cout << " DI | Discrete Input Coils | read-only | <name-prefix>DI" << std::endl;
186+
std::cout << " AO | Discrete Output Registers | read-write | <name-prefix>AO" << std::endl;
187+
std::cout << " AI | Discrete Input Registers | read-only | <name-prefix>AI" << std::endl;
188188
std::cout << std::endl;
189189
std::cout << "This application uses the following libraries:" << std::endl;
190190
std::cout << " - cxxopts by jarro2783 (https://github.com/jarro2783/cxxopts)" << std::endl;
@@ -308,29 +308,29 @@ int main(int argc, char **argv) {
308308
}
309309

310310

311-
// create slave
312-
std::unique_ptr<Modbus::TCP::Slave> slave;
311+
// create modbus client
312+
std::unique_ptr<Modbus::TCP::Client> client;
313313
try {
314-
slave = std::make_unique<Modbus::TCP::Slave>(args["ip"].as<std::string>(),
314+
client = std::make_unique<Modbus::TCP::Client>(args["ip"].as<std::string>(),
315315
args["port"].as<uint16_t>(),
316316
mb_mappings.data(),
317317
#ifdef OS_LINUX
318318
args["tcp-timeout"].as<std::size_t>());
319319
#else
320320
0);
321321
#endif
322-
slave->set_debug(args.count("monitor"));
322+
client->set_debug(args.count("monitor"));
323323
} catch (const std::runtime_error &e) {
324324
std::cerr << e.what() << std::endl;
325325
return EX_SOFTWARE;
326326
}
327-
socket = slave->get_socket();
327+
socket = client->get_socket();
328328

329329
// set timeouts if required
330330
try {
331-
if (args.count("response-timeout")) { slave->set_response_timeout(args["response-timeout"].as<double>()); }
331+
if (args.count("response-timeout")) { client->set_response_timeout(args["response-timeout"].as<double>()); }
332332

333-
if (args.count("byte-timeout")) { slave->set_byte_timeout(args["byte-timeout"].as<double>()); }
333+
if (args.count("byte-timeout")) { client->set_byte_timeout(args["byte-timeout"].as<double>()); }
334334
} catch (const std::runtime_error &e) {
335335
std::cerr << e.what() << std::endl;
336336
return EX_SOFTWARE;
@@ -339,10 +339,10 @@ int main(int argc, char **argv) {
339339
// connection loop
340340
do {
341341
// connect client
342-
std::cerr << "Waiting for Master to establish a connection..." << std::endl;
343-
std::string client;
342+
std::cerr << "Waiting for Modbus Server to establish a connection..." << std::endl;
343+
std::string client_name;
344344
try {
345-
client = slave->connect_client();
345+
client_name = client->connect_client();
346346
} catch (const std::runtime_error &e) {
347347
if (!terminate) {
348348
std::cerr << e.what() << std::endl;
@@ -351,21 +351,21 @@ int main(int argc, char **argv) {
351351
break;
352352
}
353353

354-
std::cerr << "Master (" << client << ") established connection." << std::endl;
354+
std::cerr << "Modbus Server (" << client_name << ") established connection." << std::endl;
355355

356356
// ========== MAIN LOOP ========== (handle requests)
357357
bool connection_closed = false;
358358
while (!terminate && !connection_closed) {
359359
try {
360-
connection_closed = slave->handle_request();
360+
connection_closed = client->handle_request();
361361
} catch (const std::runtime_error &e) {
362362
// clang-tidy (LLVM 12.0.1) warning "Condition is always true" is not correct
363363
if (!terminate) std::cerr << e.what() << std::endl;
364364
break;
365365
}
366366
}
367367

368-
if (connection_closed) std::cerr << "Master closed connection." << std::endl;
368+
if (connection_closed) std::cerr << "Modbus Server closed connection." << std::endl;
369369
} while (args.count("reconnect"));
370370

371371
std::cerr << "Terminating..." << std::endl;

0 commit comments

Comments
 (0)