33 * This program is free software. You can redistribute it and/or modify it under the terms of the GPLv3 License.
44 */
55
6+ #include " Modbus_TCP_Client_poll.hpp"
7+ #include " Print_Time.hpp"
8+ #include " generated/version_info.hpp"
9+ #include " license.hpp"
10+ #include " modbus_shm.hpp"
11+
612#include < atomic>
713#include < condition_variable>
814#include < csignal>
3339# pragma GCC diagnostic pop
3440#endif
3541
36- #include " Modbus_TCP_Client_poll.hpp"
37- #include " Print_Time.hpp"
38- #include " license.hpp"
39- #include " modbus_shm.hpp"
40-
41-
4242// ! Maximum number of registers per type
4343static constexpr size_t MODBUS_MAX_REGS = 0x10000 ;
4444
@@ -111,74 +111,82 @@ int main(int argc, char **argv) {
111111#endif
112112
113113 // all command line arguments
114- options.add_options ()(
114+ options.add_options (" network " )(
115115 " i,host" , " host to listen for incoming connections" , cxxopts::value<std::string>()->default_value (" any" ));
116- options.add_options ()(" p,service" ,
117- " service or port to listen for incoming connections" ,
118- cxxopts::value<std::string>()->default_value (" 502" ));
119- options.add_options ()(
116+ options.add_options (" network " )(" p,service" ,
117+ " service or port to listen for incoming connections" ,
118+ cxxopts::value<std::string>()->default_value (" 502" ));
119+ options.add_options (" shared memory " )(
120120 " n,name-prefix" , " shared memory name prefix" , cxxopts::value<std::string>()->default_value (" modbus_" ));
121- options.add_options ()(" do-registers" ,
122- " number of digital output registers" ,
123- cxxopts::value<std::size_t >()->default_value (" 65536" ));
124- options.add_options ()(
121+ options.add_options (" modbus " )(" do-registers" ,
122+ " number of digital output registers" ,
123+ cxxopts::value<std::size_t >()->default_value (" 65536" ));
124+ options.add_options (" modbus " )(
125125 " di-registers" , " number of digital input registers" , cxxopts::value<std::size_t >()->default_value (" 65536" ));
126- options.add_options ()(
126+ options.add_options (" modbus " )(
127127 " ao-registers" , " number of analog output registers" , cxxopts::value<std::size_t >()->default_value (" 65536" ));
128- options.add_options ()(
128+ options.add_options (" modbus " )(
129129 " ai-registers" , " number of analog input registers" , cxxopts::value<std::size_t >()->default_value (" 65536" ));
130- options.add_options ()(" m,monitor" , " output all incoming and outgoing packets to stdout" );
131- options.add_options ()(" c,connections" ,
132- " number of allowed simultaneous Modbus Server connections." ,
133- cxxopts::value<std::size_t >()->default_value (" 1" ));
134- options.add_options ()(" r,reconnect" , " do not terminate if no Modbus Server is connected anymore." );
135- options.add_options ()(" byte-timeout" ,
136- " timeout interval in seconds between two consecutive bytes of the same message. "
137- " In most cases it is sufficient to set the response timeout. "
138- " Fractional values are possible." ,
139- cxxopts::value<double >());
140- options.add_options ()(" response-timeout" ,
141- " set the timeout interval in seconds used to wait for a response. "
142- " When a byte timeout is set, if the elapsed time for the first byte of response is longer "
143- " than the given timeout, a timeout is detected. "
144- " When byte timeout is disabled, the full confirmation response must be received before "
145- " expiration of the response timeout. "
146- " Fractional values are possible." ,
147- cxxopts::value<double >());
130+ options.add_options (" modbus" )(" m,monitor" , " output all incoming and outgoing packets to stdout" );
131+ options.add_options (" network" )(" c,connections" ,
132+ " number of allowed simultaneous Modbus Server connections." ,
133+ cxxopts::value<std::size_t >()->default_value (" 1" ));
134+ options.add_options (" network" )(" r,reconnect" , " do not terminate if no Modbus Server is connected anymore." );
135+ options.add_options (" modbus" )(" byte-timeout" ,
136+ " timeout interval in seconds between two consecutive bytes of the same message. "
137+ " In most cases it is sufficient to set the response timeout. "
138+ " Fractional values are possible." ,
139+ cxxopts::value<double >());
140+ options.add_options (" modbus" )(
141+ " response-timeout" ,
142+ " set the timeout interval in seconds used to wait for a response. "
143+ " When a byte timeout is set, if the elapsed time for the first byte of response is longer "
144+ " than the given timeout, a timeout is detected. "
145+ " When byte timeout is disabled, the full confirmation response must be received before "
146+ " expiration of the response timeout. "
147+ " Fractional values are possible." ,
148+ cxxopts::value<double >());
148149#ifdef OS_LINUX
149- options.add_options ()(" t,tcp-timeout" ,
150- " tcp timeout in seconds. Set to 0 to use the system defaults (not recommended)." ,
151- cxxopts::value<std::size_t >()->default_value (" 5" ));
150+ options.add_options (" network " )(" t,tcp-timeout" ,
151+ " tcp timeout in seconds. Set to 0 to use the system defaults (not recommended)." ,
152+ cxxopts::value<std::size_t >()->default_value (" 5" ));
152153#endif
153- options.add_options ()(" force" ,
154- " Force the use of the shared memory even if it already exists. "
155- " Do not use this option per default! "
156- " It should only be used if the shared memory of an improperly terminated instance continues "
157- " to exist as an orphan and is no longer used." );
158- options.add_options ()(" s,separate" ,
159- " Use a separate shared memory for requests with the specified client id. "
160- " The client id (as hex value) is appended to the shared memory prefix (e.g. modbus_fc_DO)"
161- " . You can specify multiple client ids by separating them with ','. "
162- " Use --separate-all to generate separate shared memories for all possible client ids." ,
163- cxxopts::value<std::vector<std::uint8_t >>());
164- options.add_options ()(" separate-all" ,
165- " like --separate, but for all client ids (creates 1028 shared memory files! "
166- " check/set 'ulimit -n' before using this option.)" );
167- options.add_options ()(" semaphore" ,
168- " protect the shared memory with a named semaphore against simultaneous access" ,
169- cxxopts::value<std::string>());
170- options.add_options ()(" semaphore-force" ,
171- " Force the use of the semaphore even if it already exists. "
172- " Do not use this option per default! "
173- " It should only be used if the semaphore of an improperly terminated instance continues "
174- " to exist as an orphan and is no longer used." );
175- options.add_options ()(" b,permissions" ,
176- " permission bits that are applied when creating a shared memory." ,
177- cxxopts::value<std::string>()->default_value (" 0640" ));
178- options.add_options ()(" h,help" , " print usage" );
179- options.add_options ()(" version" , " print version information" );
180- options.add_options ()(" license" , " show licences (short)" );
181- options.add_options ()(" license-full" , " show licences (full license text)" );
154+ options.add_options (" shared memory" )(
155+ " force" ,
156+ " Force the use of the shared memory even if it already exists. "
157+ " Do not use this option per default! "
158+ " It should only be used if the shared memory of an improperly terminated instance continues "
159+ " to exist as an orphan and is no longer used." );
160+ options.add_options (" shared memory" )(
161+ " s,separate" ,
162+ " Use a separate shared memory for requests with the specified client id. "
163+ " The client id (as hex value) is appended to the shared memory prefix (e.g. modbus_fc_DO)"
164+ " . You can specify multiple client ids by separating them with ','. "
165+ " Use --separate-all to generate separate shared memories for all possible client ids." ,
166+ cxxopts::value<std::vector<std::uint8_t >>());
167+ options.add_options (" shared memory" )(" separate-all" ,
168+ " like --separate, but for all client ids (creates 1028 shared memory files! "
169+ " check/set 'ulimit -n' before using this option.)" );
170+ options.add_options (" shared memory" )(" semaphore" ,
171+ " protect the shared memory with a named semaphore against simultaneous access" ,
172+ cxxopts::value<std::string>());
173+ options.add_options (" shared memory" )(
174+ " semaphore-force" ,
175+ " Force the use of the semaphore even if it already exists. "
176+ " Do not use this option per default! "
177+ " It should only be used if the semaphore of an improperly terminated instance continues "
178+ " to exist as an orphan and is no longer used." );
179+ options.add_options (" shared memory" )(" b,permissions" ,
180+ " permission bits that are applied when creating a shared memory." ,
181+ cxxopts::value<std::string>()->default_value (" 0640" ));
182+ options.add_options (" other" )(" h,help" , " print usage" );
183+ options.add_options (" version information" )(" version" , " print version and exit" );
184+ options.add_options (" version information" )(" longversion" ,
185+ " print version (including compiler and system info) and exit" );
186+ options.add_options (" version information" )(" shortversion" , " print version (only version string) and exit" );
187+ options.add_options (" version information" )(" git-hash" , " print git hash" );
188+ options.add_options (" other" )(" license" , " show licences (short)" );
189+ options.add_options (" other" )(" license-full" , " show licences (full license text)" );
182190
183191 // parse arguments
184192 cxxopts::ParseResult args;
@@ -210,8 +218,8 @@ int main(int argc, char **argv) {
210218 return EX_OK;
211219 }
212220
213- // print usage
214- if (args.count (" version " )) {
221+ // print version
222+ if (args.count (" longversion " )) {
215223 std::cout << PROJECT_NAME << ' ' << PROJECT_VERSION << " (compiled with " << COMPILER_INFO << " on "
216224 << SYSTEM_INFO << ' )'
217225#ifndef OS_LINUX
@@ -221,6 +229,33 @@ int main(int argc, char **argv) {
221229 return EX_OK;
222230 }
223231
232+ if (args.count (" shortversion" )) {
233+ std::cout << PROJECT_VERSION << ' \n ' ;
234+ return EX_OK;
235+ }
236+
237+ if (args.count (" version" )) {
238+ std::cout << PROJECT_NAME << ' ' << PROJECT_VERSION << ' \n ' ;
239+ return EX_OK;
240+ }
241+
242+ if (args.count (" longversion" )) {
243+ std::cout << PROJECT_NAME << ' ' << PROJECT_VERSION << ' \n ' ;
244+ std::cout << " compiled with " << COMPILER_INFO << ' \n ' ;
245+ std::cout << " on system " << SYSTEM_INFO
246+ #ifndef OS_LINUX
247+ << " -nonlinux"
248+ #endif
249+ << ' \n ' ;
250+ std::cout << " from git commit " << RCS_HASH << ' \n ' ;
251+ return EX_OK;
252+ }
253+
254+ if (args.count (" git-hash" )) {
255+ std::cout << RCS_HASH << ' \n ' ;
256+ return EX_OK;
257+ }
258+
224259 // print licenses
225260 if (args.count (" license" )) {
226261 print_licenses (std::cout, false );
0 commit comments