rodbus (C++ API) 1.3.1
Loading...
Searching...
No Matches
rodbus.hpp
Go to the documentation of this file.
1// This library is provided under the terms of a non-commercial license.
2//
3// Please refer to the source repository for details:
4//
5// https://github.com/stepfunc/rodbus/blob/master/LICENSE.txt
6//
7// Please contact Step Function I/O if you are interested in commercial license:
8//
9// info@stepfunc.io
10#pragma once
11
12#include <cstdint>
13#include <stdexcept>
14#include <chrono>
15#include <memory>
16#include <vector>
17
37
39namespace rodbus {
40
42constexpr uint64_t rodbus_version_major = 1;
44constexpr uint64_t rodbus_version_minor = 3;
46constexpr uint64_t rodbus_version_patch = 1;
48constexpr char const* rodbus_version_string = "1.3.1";
49
50
52enum class ParamError {
54 ok = 0,
56 no_support = 1,
70 invalid_range = 8,
74 invalid_index = 10,
78 invalid_unit_id = 12,
88 bad_tls_config = 17,
90 shutdown = 18,
92 invalid_utf8 = 19,
93};
94
98const char* to_string(ParamError value);
99
101class ParamException : public std::logic_error {
102public:
107};
108
110enum class Nothing {
112 nothing = 0,
113};
114
118const char* to_string(Nothing value);
119
123enum class AppDecodeLevel {
125 nothing = 0,
127 function_code = 1,
129 data_headers = 2,
131 data_values = 3,
132};
133
137const char* to_string(AppDecodeLevel value);
138
146 nothing = 0,
148 header = 1,
150 payload = 2,
151};
152
156const char* to_string(FrameDecodeLevel value);
157
159enum class PhysDecodeLevel {
161 nothing = 0,
163 length = 1,
165 data = 2,
166};
167
171const char* to_string(PhysDecodeLevel value);
172
173struct DecodeLevel;
174
177 friend class CppDecodeLevelFriend;
178
179 DecodeLevel() = delete;
180
187
188
198
199
206};
207
208struct BitValue;
209
211struct BitValue {
212 friend class CppBitValueFriend;
213
214 BitValue() = delete;
215
220 BitValue(uint16_t index, bool value);
221
222
224 uint16_t index;
226 bool value;
227};
228
229struct RegisterValue;
230
233 friend class CppRegisterValueFriend;
234
235 RegisterValue() = delete;
236
241 RegisterValue(uint16_t index, uint16_t value);
242
243
245 uint16_t index;
247 uint16_t value;
248};
249
250class Runtime;
251
252struct RuntimeConfig;
253
256 friend class CppRuntimeConfigFriend;
257
258private:
263
264public:
265
273
274
279};
280
282class Runtime {
283 friend class CppRuntimeFriend;
284 // pointer to the underlying C type
285 void* self;
286 // constructor only accessible internally
287 Runtime(void* self): self(self) {}
288 // non-copyable
289 Runtime(const Runtime&) = delete;
290 Runtime& operator=(const Runtime&) = delete;
291 // no move assignment
292 Runtime& operator=(Runtime&& other) = delete;
293
294public:
298 Runtime(Runtime&& other) noexcept : self(other.self) { other.self = nullptr; }
299
306 Runtime(const RuntimeConfig& config);
307
312
320 void set_shutdown_timeout(std::chrono::steady_clock::duration timeout);
321};
322
326enum class RequestError {
328 ok = 0,
330 shutdown = 1,
332 no_connection = 2,
336 bad_request = 4,
338 bad_response = 5,
340 io_error = 6,
342 bad_framing = 7,
344 internal_error = 8,
346 bad_argument = 9,
367};
368
372const char* to_string(RequestError value);
373
375class RequestException : public std::logic_error {
376public:
381};
382
383struct AddressRange;
384
387 friend class CppAddressRangeFriend;
388
389 AddressRange() = delete;
390
395 AddressRange(uint16_t start, uint16_t count);
396
397
399 uint16_t start;
401 uint16_t count;
402};
403
404struct RequestParam;
405
408 friend class CppRequestParamFriend;
409
410 RequestParam() = delete;
411
416 RequestParam(uint8_t unit_id, std::chrono::steady_clock::duration timeout);
417
418
420 uint8_t unit_id;
422 std::chrono::steady_clock::duration timeout;
423};
424
425class BitValueIterator;
426
438class BitValueIterator final {
439
440 friend class CppBitValueIteratorFriend;
441
442 // underlying opaque c type
443 void* iter;
444 // pointer to the last retrieved c value
445 void* current;
446
447 // internal constructor
448 BitValueIterator(void* iter) : iter(iter), current(nullptr) {}
449
450 BitValueIterator() = delete; // no default construction
451 BitValueIterator(const BitValueIterator&) = delete; // no copies
452 BitValueIterator& operator=(const BitValueIterator&) = delete; // no self-assignment
453 BitValueIterator& operator=(BitValueIterator&&) = delete; // no move self-assignment
454
455public:
456
459
462 bool next();
463
468};
469
471
484
485 friend class CppRegisterValueIteratorFriend;
486
487 // underlying opaque c type
488 void* iter;
489 // pointer to the last retrieved c value
490 void* current;
491
492 // internal constructor
493 RegisterValueIterator(void* iter) : iter(iter), current(nullptr) {}
494
495 RegisterValueIterator() = delete; // no default construction
496 RegisterValueIterator(const RegisterValueIterator&) = delete; // no copies
497 RegisterValueIterator& operator=(const RegisterValueIterator&) = delete; // no self-assignment
498 RegisterValueIterator& operator=(RegisterValueIterator&&) = delete; // no move self-assignment
499
500public:
501
504
507 bool next();
508
513};
514
516enum class ModbusException {
526 acknowledge = 5,
536 unknown = 255,
537};
538
542const char* to_string(ModbusException value);
543
545enum class DataBits {
547 five = 0,
549 six = 1,
551 seven = 2,
553 eight = 3,
554};
555
559const char* to_string(DataBits value);
560
562enum class FlowControl {
564 none = 0,
566 software = 1,
568 hardware = 2,
569};
570
574const char* to_string(FlowControl value);
575
577enum class Parity {
579 none = 0,
581 odd = 1,
583 even = 2,
584};
585
589const char* to_string(Parity value);
590
592enum class StopBits {
594 one = 0,
596 two = 1,
597};
598
602const char* to_string(StopBits value);
603
604struct SerialPortSettings;
605
608 friend class CppSerialPortSettingsFriend;
609
610private:
619
620public:
621
633
634
636 uint32_t baud_rate;
645};
646
648enum class MinTlsVersion {
650 v12 = 0,
652 v13 = 1,
653};
654
658const char* to_string(MinTlsVersion value);
659
663enum class CertificateMode {
669 authority_based = 0,
673 self_signed = 1,
674};
675
679const char* to_string(CertificateMode value);
680
681struct RetryStrategy;
682
687 friend class CppRetryStrategyFriend;
688
689private:
694 RetryStrategy(std::chrono::steady_clock::duration min_delay, std::chrono::steady_clock::duration max_delay);
695
696public:
697
706
707
709 std::chrono::steady_clock::duration min_delay;
711 std::chrono::steady_clock::duration max_delay;
712};
713
717enum class LogLevel {
719 error = 0,
721 warn = 1,
723 info = 2,
725 debug = 3,
727 trace = 4,
728};
729
733const char* to_string(LogLevel value);
734
735struct LoggingConfig;
736
738enum class LogOutputFormat {
740 text = 0,
742 json = 1,
743};
744
748const char* to_string(LogOutputFormat value);
749
751enum class TimeFormat {
753 none = 0,
755 rfc_3339 = 1,
757 system = 2,
758};
759
763const char* to_string(TimeFormat value);
764
767 friend class CppLoggingConfigFriend;
768
769private:
778
779public:
780
792
793
804};
805
809class Logger {
810public:
811 virtual ~Logger() = default;
812
817 virtual void on_message(LogLevel level, const char* message) = 0;
818
819};
820
822namespace functional {
823
826template <class T>
827class LoggerLambda final : public Logger
828{
829 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
830
831 T lambda;
832
833public:
836 LoggerLambda(const T& lambda) : lambda(lambda) {}
837
839 void on_message(LogLevel level, const char* message) override
840 {
841 lambda(level, message);
842 }
843};
844
849template <class T>
850std::unique_ptr<Logger> logger(const T& lambda)
851{
852 return std::make_unique<LoggerLambda<T>>(lambda); ;
853}
854
855} // end namespace functional
856
858class Logging {
859 Logging() = delete;
860public:
870 static void configure(const LoggingConfig& config, std::unique_ptr<Logger> logger);
871};
872
873class ClientChannel;
874
875struct TlsClientConfig;
876
879 friend class CppTlsClientConfigFriend;
880
881private:
892 TlsClientConfig(const std::string& dns_name, const std::string& peer_cert_path, const std::string& local_cert_path, const std::string& private_key_path, const std::string& password, MinTlsVersion min_tls_version, CertificateMode certificate_mode, bool allow_server_name_wildcard);
893
894public:
895 TlsClientConfig() = delete;
896
910 TlsClientConfig(const std::string& dns_name, const std::string& peer_cert_path, const std::string& local_cert_path, const std::string& private_key_path, const std::string& password);
911
912
914 std::string dns_name;
916 std::string peer_cert_path;
918 std::string local_cert_path;
920 std::string private_key_path;
926 std::string password;
933};
934
938enum class ClientState {
940 disabled = 0,
942 connecting = 1,
944 connected = 2,
950 shutdown = 5,
951};
952
956const char* to_string(ClientState value);
957
962public:
963 virtual ~ClientStateListener() = default;
964
968 virtual void on_change(ClientState state) = 0;
969
970};
971
972namespace functional {
973
976template <class T>
978{
979 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
980
981 T lambda;
982
983public:
986 ClientStateListenerLambda(const T& lambda) : lambda(lambda) {}
987
989 void on_change(ClientState state) override
990 {
991 lambda(state);
992 }
993};
994
999template <class T>
1000std::unique_ptr<ClientStateListener> client_state_listener(const T& lambda)
1001{
1002 return std::make_unique<ClientStateListenerLambda<T>>(lambda); ;
1003}
1004
1005} // end namespace functional
1006
1010enum class PortState {
1012 disabled = 0,
1014 wait = 1,
1016 open = 2,
1018 shutdown = 3,
1019};
1020
1024const char* to_string(PortState value);
1025
1030public:
1031 virtual ~PortStateListener() = default;
1032
1036 virtual void on_change(PortState state) = 0;
1037
1038};
1039
1040namespace functional {
1041
1044template <class T>
1046{
1047 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
1048
1049 T lambda;
1050
1051public:
1054 PortStateListenerLambda(const T& lambda) : lambda(lambda) {}
1055
1057 void on_change(PortState state) override
1058 {
1059 lambda(state);
1060 }
1061};
1062
1067template <class T>
1068std::unique_ptr<PortStateListener> port_state_listener(const T& lambda)
1069{
1070 return std::make_unique<PortStateListenerLambda<T>>(lambda); ;
1071}
1072
1073} // end namespace functional
1074
1079public:
1080 virtual ~BitReadCallback() = default;
1081
1085 virtual void on_complete(BitValueIterator& result) = 0;
1086
1090 virtual void on_failure(RequestError error) = 0;
1091
1092};
1093
1098public:
1099 virtual ~RegisterReadCallback() = default;
1100
1104 virtual void on_complete(RegisterValueIterator& result) = 0;
1105
1109 virtual void on_failure(RequestError error) = 0;
1110
1111};
1112
1117public:
1118 virtual ~WriteCallback() = default;
1119
1123 virtual void on_complete(Nothing result) = 0;
1124
1128 virtual void on_failure(RequestError error) = 0;
1129
1130};
1131
1136 friend class CppClientChannelFriend;
1137 // pointer to the underlying C type
1138 void* self;
1139 // constructor only accessible internally
1140 ClientChannel(void* self): self(self) {}
1141 // non-copyable
1142 ClientChannel(const ClientChannel&) = delete;
1143 ClientChannel& operator=(const ClientChannel&) = delete;
1144 // no move assignment
1145 ClientChannel& operator=(ClientChannel&& other) = delete;
1146
1147public:
1151 ClientChannel(ClientChannel&& other) noexcept : self(other.self) { other.self = nullptr; }
1152
1155
1161 void enable();
1162
1168 void disable();
1169
1174 void set_decode_level(const DecodeLevel& level);
1175
1187 static ClientChannel create_tcp(Runtime& runtime, const std::string& host, uint16_t port, uint16_t max_queued_requests, const RetryStrategy& retry_strategy, const DecodeLevel& decode_level, std::unique_ptr<ClientStateListener> listener);
1188
1200 static ClientChannel create_rtu(Runtime& runtime, const std::string& path, const SerialPortSettings& serial_params, uint16_t max_queued_requests, const RetryStrategy& retry_strategy, const DecodeLevel& decode_level, std::unique_ptr<PortStateListener> listener);
1201
1214 static ClientChannel create_tls(Runtime& runtime, const std::string& host, uint16_t port, uint16_t max_queued_requests, const RetryStrategy& retry_strategy, const TlsClientConfig& tls_config, const DecodeLevel& decode_level, std::unique_ptr<ClientStateListener> listener);
1215
1222 void read_coils(const RequestParam& param, const AddressRange& range, std::unique_ptr<BitReadCallback> callback);
1223
1224
1231 void read_discrete_inputs(const RequestParam& param, const AddressRange& range, std::unique_ptr<BitReadCallback> callback);
1232
1233
1240 void read_holding_registers(const RequestParam& param, const AddressRange& range, std::unique_ptr<RegisterReadCallback> callback);
1241
1242
1249 void read_input_registers(const RequestParam& param, const AddressRange& range, std::unique_ptr<RegisterReadCallback> callback);
1250
1251
1258 void write_single_coil(const RequestParam& param, const BitValue& value, std::unique_ptr<WriteCallback> callback);
1259
1260
1267 void write_single_register(const RequestParam& param, const RegisterValue& value, std::unique_ptr<WriteCallback> callback);
1268
1269
1277 void write_multiple_coils(const RequestParam& param, uint16_t start, const std::vector<bool>& items, std::unique_ptr<WriteCallback> callback);
1278
1279
1287 void write_multiple_registers(const RequestParam& param, uint16_t start, const std::vector<uint16_t>& items, std::unique_ptr<WriteCallback> callback);
1288
1289};
1290
1291class Database;
1292
1295 friend class CppDatabaseFriend;
1296 // pointer to the underlying C type
1297 void* self;
1298 // constructor only accessible internally
1299 Database(void* self): self(self) {}
1300 // non-copyable
1301 Database(const Database&) = delete;
1302 Database& operator=(const Database&) = delete;
1303 // no move assignment
1304 Database& operator=(Database&& other) = delete;
1305
1306public:
1310 Database(Database&& other) noexcept : self(other.self) { other.self = nullptr; }
1311
1317 bool add_coil(uint16_t index, bool value);
1318
1324 bool add_discrete_input(uint16_t index, bool value);
1325
1331 bool add_holding_register(uint16_t index, uint16_t value);
1332
1338 bool add_input_register(uint16_t index, uint16_t value);
1339
1345 bool get_coil(uint16_t index);
1346
1352 bool get_discrete_input(uint16_t index);
1353
1359 uint16_t get_holding_register(uint16_t index);
1360
1366 uint16_t get_input_register(uint16_t index);
1367
1373 bool update_coil(uint16_t index, bool value);
1374
1380 bool update_discrete_input(uint16_t index, bool value);
1381
1387 bool update_holding_register(uint16_t index, uint16_t value);
1388
1394 bool update_input_register(uint16_t index, uint16_t value);
1395
1400 bool delete_coil(uint16_t index);
1401
1406 bool delete_discrete_input(uint16_t index);
1407
1412 bool delete_holding_register(uint16_t index);
1413
1418 bool delete_input_register(uint16_t index);
1419};
1420
1425public:
1426 virtual ~DatabaseCallback() = default;
1427
1431 virtual void callback(Database& database) = 0;
1432
1433};
1434
1435namespace functional {
1436
1439template <class T>
1441{
1442 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
1443
1444 T lambda;
1445
1446public:
1449 DatabaseCallbackLambda(const T& lambda) : lambda(lambda) {}
1450
1452 void callback(Database& database) override
1453 {
1454 lambda(database);
1455 }
1456};
1457
1462template <class T>
1464{
1465 return DatabaseCallbackLambda<T>(lambda);
1466}
1467
1468} // end namespace functional
1469
1470struct WriteResult;
1471
1478 friend class CppWriteResultFriend;
1479
1480private:
1487
1488public:
1489 WriteResult() = delete;
1490
1500
1501
1511
1512
1522
1523
1530};
1531
1536public:
1537 virtual ~WriteHandler() = default;
1538
1545 virtual WriteResult write_single_coil(uint16_t index, bool value, Database& database) = 0;
1546
1553 virtual WriteResult write_single_register(uint16_t index, uint16_t value, Database& database) = 0;
1554
1561 virtual WriteResult write_multiple_coils(uint16_t start, BitValueIterator& it, Database& database) = 0;
1562
1569 virtual WriteResult write_multiple_registers(uint16_t start, RegisterValueIterator& it, Database& database) = 0;
1570
1571};
1572
1573class DeviceMap;
1574
1577 friend class CppDeviceMapFriend;
1578 // pointer to the underlying C type
1579 void* self;
1580 // constructor only accessible internally
1581 DeviceMap(void* self): self(self) {}
1582 // non-copyable
1583 DeviceMap(const DeviceMap&) = delete;
1584 DeviceMap& operator=(const DeviceMap&) = delete;
1585 // no move assignment
1586 DeviceMap& operator=(DeviceMap&& other) = delete;
1587
1588public:
1592 DeviceMap(DeviceMap&& other) noexcept : self(other.self) { other.self = nullptr; }
1593
1597
1600
1607 bool add_endpoint(uint8_t unit_id, std::unique_ptr<WriteHandler> handler, DatabaseCallback& configure);
1608};
1609
1610struct TlsServerConfig;
1611
1614 friend class CppTlsServerConfigFriend;
1615
1616private:
1625 TlsServerConfig(const std::string& peer_cert_path, const std::string& local_cert_path, const std::string& private_key_path, const std::string& password, MinTlsVersion min_tls_version, CertificateMode certificate_mode);
1626
1627public:
1628 TlsServerConfig() = delete;
1629
1641 TlsServerConfig(const std::string& peer_cert_path, const std::string& local_cert_path, const std::string& private_key_path, const std::string& password);
1642
1643
1645 std::string peer_cert_path;
1647 std::string local_cert_path;
1649 std::string private_key_path;
1655 std::string password;
1660};
1661
1663enum class Authorization {
1665 allow = 0,
1667 deny = 1,
1668};
1669
1673const char* to_string(Authorization value);
1674
1679public:
1680 virtual ~AuthorizationHandler() = default;
1681
1688 virtual Authorization read_coils(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1689
1696 virtual Authorization read_discrete_inputs(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1697
1704 virtual Authorization read_holding_registers(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1705
1712 virtual Authorization read_input_registers(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1713
1720 virtual Authorization write_single_coil(uint8_t unit_id, uint16_t index, const char* role) = 0;
1721
1728 virtual Authorization write_single_register(uint8_t unit_id, uint16_t index, const char* role) = 0;
1729
1736 virtual Authorization write_multiple_coils(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1737
1744 virtual Authorization write_multiple_registers(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1745
1746};
1747
1748class AddressFilter;
1749
1752 friend class CppAddressFilterFriend;
1753 // pointer to the underlying C type
1754 void* self;
1755 // constructor only accessible internally
1756 AddressFilter(void* self): self(self) {}
1757 // non-copyable
1758 AddressFilter(const AddressFilter&) = delete;
1759 AddressFilter& operator=(const AddressFilter&) = delete;
1760 // no move assignment
1761 AddressFilter& operator=(AddressFilter&& other) = delete;
1762
1763public:
1767 AddressFilter(AddressFilter&& other) noexcept : self(other.self) { other.self = nullptr; }
1768
1777 AddressFilter(const std::string& address);
1778
1781
1788 void add(const std::string& address);
1789
1794};
1795
1796class Server;
1797
1799class Server {
1800 friend class CppServerFriend;
1801 // pointer to the underlying C type
1802 void* self;
1803 // constructor only accessible internally
1804 Server(void* self): self(self) {}
1805 // non-copyable
1806 Server(const Server&) = delete;
1807 Server& operator=(const Server&) = delete;
1808 // no move assignment
1809 Server& operator=(Server&& other) = delete;
1810
1811public:
1815 Server(Server&& other) noexcept : self(other.self) { other.self = nullptr; }
1816
1819
1825 void update_database(uint8_t unit_id, DatabaseCallback& transaction);
1826
1831 void set_decode_level(const DecodeLevel& level);
1832
1848 static Server create_tcp(Runtime& runtime, const std::string& address, uint16_t port, AddressFilter& filter, uint16_t max_sessions, DeviceMap& endpoints, const DecodeLevel& decode_level);
1849
1860 static Server create_rtu(Runtime& runtime, const std::string& path, const SerialPortSettings& serial_params, const RetryStrategy& retry, DeviceMap& endpoints, const DecodeLevel& decode_level);
1861
1881 static Server create_tls_with_authz(Runtime& runtime, const std::string& address, uint16_t port, AddressFilter& filter, uint16_t max_sessions, DeviceMap& endpoints, const TlsServerConfig& tls_config, std::unique_ptr<AuthorizationHandler> authorization_handler, const DecodeLevel& decode_level);
1882
1899 static Server create_tls(Runtime& runtime, const std::string& address, uint16_t port, AddressFilter& filter, uint16_t max_sessions, DeviceMap& endpoints, const TlsServerConfig& tls_config, const DecodeLevel& decode_level);
1900};
1901
1902} // end namespace rodbus
Filter used to restrict which IP addresses may communicate with a server.
Definition: rodbus.hpp:1751
AddressFilter(AddressFilter &&other) noexcept
Transfer ownership of the underlying C-type to this instance and invalidate the other instance.
Definition: rodbus.hpp:1767
static AddressFilter any()
Create an address filter that accepts any IP address.
AddressFilter(const std::string &address)
Create an address filter that matches one or more IP addresses. Ipv4 or IPv6 addresses are allowed.
~AddressFilter()
Destroy an address filter.
void add(const std::string &address)
Add an allowed IP address to the filter.
User implemented interface defines which request and roles are allowed for different functions when i...
Definition: rodbus.hpp:1678
virtual Authorization read_coils(uint8_t unit_id, const AddressRange &range, const char *role)=0
Authorize a Read Coils request.
virtual Authorization write_multiple_coils(uint8_t unit_id, const AddressRange &range, const char *role)=0
Authorize a Write Multiple Coils request.
virtual Authorization read_discrete_inputs(uint8_t unit_id, const AddressRange &range, const char *role)=0
Authorize a Read Discrete Inputs request.
virtual Authorization read_holding_registers(uint8_t unit_id, const AddressRange &range, const char *role)=0
Authorize a Read Holding Registers request.
virtual Authorization write_multiple_registers(uint8_t unit_id, const AddressRange &range, const char *role)=0
Authorize a Write Multiple Registers request.
virtual Authorization write_single_register(uint8_t unit_id, uint16_t index, const char *role)=0
Authorize a Write Single Register request.
virtual Authorization write_single_coil(uint8_t unit_id, uint16_t index, const char *role)=0
Authorize a Write Single Coil request.
virtual Authorization read_input_registers(uint8_t unit_id, const AddressRange &range, const char *role)=0
Authorize a Read Input Registers request.
Callbacks received when reading coils or discrete inputs.
Definition: rodbus.hpp:1078
virtual void on_complete(BitValueIterator &result)=0
Invoked when the asynchronous operation completes successfully.
virtual void on_failure(RequestError error)=0
Invoked when the asynchronous operation fails.
Iterator over BitValue instances.
Definition: rodbus.hpp:438
BitValueIterator(BitValueIterator &&)=default
move constructor for the iterator
BitValue get()
retrieve the current value
bool next()
move the iterator to the next value
Abstract representation of a client communication channel.
Definition: rodbus.hpp:1135
static ClientChannel create_tls(Runtime &runtime, const std::string &host, uint16_t port, uint16_t max_queued_requests, const RetryStrategy &retry_strategy, const TlsClientConfig &tls_config, const DecodeLevel &decode_level, std::unique_ptr< ClientStateListener > listener)
Create a new TLS channel instance.
static ClientChannel create_rtu(Runtime &runtime, const std::string &path, const SerialPortSettings &serial_params, uint16_t max_queued_requests, const RetryStrategy &retry_strategy, const DecodeLevel &decode_level, std::unique_ptr< PortStateListener > listener)
Create a new RTU channel instance.
static ClientChannel create_tcp(Runtime &runtime, const std::string &host, uint16_t port, uint16_t max_queued_requests, const RetryStrategy &retry_strategy, const DecodeLevel &decode_level, std::unique_ptr< ClientStateListener > listener)
Create a new TCP channel instance.
void read_input_registers(const RequestParam &param, const AddressRange &range, std::unique_ptr< RegisterReadCallback > callback)
Start an asynchronous request to read input registers.
void set_decode_level(const DecodeLevel &level)
Set the decoding level for the channel.
void enable()
Enable channel communications.
void write_multiple_registers(const RequestParam &param, uint16_t start, const std::vector< uint16_t > &items, std::unique_ptr< WriteCallback > callback)
Write multiple registers.
void read_discrete_inputs(const RequestParam &param, const AddressRange &range, std::unique_ptr< BitReadCallback > callback)
Start an asynchronous request to read discrete inputs.
void read_coils(const RequestParam &param, const AddressRange &range, std::unique_ptr< BitReadCallback > callback)
Start an asynchronous request to read coils.
void disable()
Disable channel communications.
void write_single_register(const RequestParam &param, const RegisterValue &value, std::unique_ptr< WriteCallback > callback)
Write a single register.
void read_holding_registers(const RequestParam &param, const AddressRange &range, std::unique_ptr< RegisterReadCallback > callback)
Start an asynchronous request to read holding registers.
void write_single_coil(const RequestParam &param, const BitValue &value, std::unique_ptr< WriteCallback > callback)
Write a single coil.
~ClientChannel()
Shutdown a ClientChannel and release all resources.
ClientChannel(ClientChannel &&other) noexcept
Transfer ownership of the underlying C-type to this instance and invalidate the other instance.
Definition: rodbus.hpp:1151
void write_multiple_coils(const RequestParam &param, uint16_t start, const std::vector< bool > &items, std::unique_ptr< WriteCallback > callback)
Write multiple coils.
Callback for monitoring the state of a TCP/TLS connection state.
Definition: rodbus.hpp:961
virtual void on_change(ClientState state)=0
Called when the client state changed.
Callback used to access the internal database while it is locked.
Definition: rodbus.hpp:1424
virtual void callback(Database &database)=0
callback function
Class used to add, remove, update, and retrieve values.
Definition: rodbus.hpp:1294
uint16_t get_input_register(uint16_t index)
Get the current input register value of the database.
uint16_t get_holding_register(uint16_t index)
Get the current holding register value of the database.
bool update_input_register(uint16_t index, uint16_t value)
Update the current value of a input register in the database.
bool add_coil(uint16_t index, bool value)
Add a new coil to the database.
bool add_input_register(uint16_t index, uint16_t value)
Add a new input register to the database.
bool get_discrete_input(uint16_t index)
Get the current discrete input value of the database.
bool update_coil(uint16_t index, bool value)
Update the current value of a coil in the database.
bool delete_discrete_input(uint16_t index)
Remove a discrete input address from the database.
bool update_discrete_input(uint16_t index, bool value)
Update the current value of a discrete input in the database.
bool add_holding_register(uint16_t index, uint16_t value)
Add a new holding register to the database.
Database(Database &&other) noexcept
Transfer ownership of the underlying C-type to this instance and invalidate the other instance.
Definition: rodbus.hpp:1310
bool delete_input_register(uint16_t index)
Remove a input register address from the database.
bool add_discrete_input(uint16_t index, bool value)
Add a new discrete input to the database.
bool delete_holding_register(uint16_t index)
Remove a holding register address from the database.
bool delete_coil(uint16_t index)
Remove a coil address from the database.
bool update_holding_register(uint16_t index, uint16_t value)
Update the current value of a holding register in the database.
bool get_coil(uint16_t index)
Get the current coil value of the database.
Maps endpoint handlers to Modbus address.
Definition: rodbus.hpp:1576
bool add_endpoint(uint8_t unit_id, std::unique_ptr< WriteHandler > handler, DatabaseCallback &configure)
Add an endpoint to the map.
DeviceMap()
Create a device map that will be used to bind devices to a server endpoint.
DeviceMap(DeviceMap &&other) noexcept
Transfer ownership of the underlying C-type to this instance and invalidate the other instance.
Definition: rodbus.hpp:1592
~DeviceMap()
Destroy a previously created device map.
Logging interface that receives the log messages and writes them somewhere.
Definition: rodbus.hpp:809
virtual void on_message(LogLevel level, const char *message)=0
Called when a log message was received and should be logged.
Provides a static method for configuring logging.
Definition: rodbus.hpp:858
static void configure(const LoggingConfig &config, std::unique_ptr< Logger > logger)
Set the callback that will receive all the log messages.
Exception type corresponding to the underlying error enum ParamError.
Definition: rodbus.hpp:101
ParamException(ParamError error)
construct the exception with an instance of the enum
Definition: rodbus.hpp:106
ParamError error
underlying error enum
Definition: rodbus.hpp:104
Callback interface for receiving updates about the state of a serial port.
Definition: rodbus.hpp:1029
virtual void on_change(PortState state)=0
Invoked when the serial port changes state.
Callbacks received when reading reading holding or input registers.
Definition: rodbus.hpp:1097
virtual void on_complete(RegisterValueIterator &result)=0
Invoked when the asynchronous operation completes successfully.
virtual void on_failure(RequestError error)=0
Invoked when the asynchronous operation fails.
Iterator over RegisterValue instances.
Definition: rodbus.hpp:483
bool next()
move the iterator to the next value
RegisterValue get()
retrieve the current value
RegisterValueIterator(RegisterValueIterator &&)=default
move constructor for the iterator
Exception type corresponding to the underlying error enum RequestError.
Definition: rodbus.hpp:375
RequestError error
underlying error enum
Definition: rodbus.hpp:378
RequestException(RequestError error)
construct the exception with an instance of the enum
Definition: rodbus.hpp:380
Handle to the underlying runtime.
Definition: rodbus.hpp:282
~Runtime()
Destroy a runtime.
void set_shutdown_timeout(std::chrono::steady_clock::duration timeout)
By default, when the runtime shuts down, it does so without a timeout and waits indefinitely for all ...
Runtime(const RuntimeConfig &config)
Creates a new runtime for running the protocol stack.
Runtime(Runtime &&other) noexcept
Transfer ownership of the underlying C-type to this instance and invalidate the other instance.
Definition: rodbus.hpp:298
Handle to the running server. The server runs on a background task until this class is destroyed.
Definition: rodbus.hpp:1799
void update_database(uint8_t unit_id, DatabaseCallback &transaction)
Update the database associated with a particular unit id. If the unit id exists, lock the database an...
static Server create_tls_with_authz(Runtime &runtime, const std::string &address, uint16_t port, AddressFilter &filter, uint16_t max_sessions, DeviceMap &endpoints, const TlsServerConfig &tls_config, std::unique_ptr< AuthorizationHandler > authorization_handler, const DecodeLevel &decode_level)
Create a Modbus Security (TLS) server.
static Server create_tcp(Runtime &runtime, const std::string &address, uint16_t port, AddressFilter &filter, uint16_t max_sessions, DeviceMap &endpoints, const DecodeLevel &decode_level)
Launch a TCP server.
static Server create_tls(Runtime &runtime, const std::string &address, uint16_t port, AddressFilter &filter, uint16_t max_sessions, DeviceMap &endpoints, const TlsServerConfig &tls_config, const DecodeLevel &decode_level)
Create a TLS server that does NOT require the client role extension.
~Server()
Shutdown and release all resources of a running server.
void set_decode_level(const DecodeLevel &level)
Set the decoding level for the server.
Server(Server &&other) noexcept
Transfer ownership of the underlying C-type to this instance and invalidate the other instance.
Definition: rodbus.hpp:1815
static Server create_rtu(Runtime &runtime, const std::string &path, const SerialPortSettings &serial_params, const RetryStrategy &retry, DeviceMap &endpoints, const DecodeLevel &decode_level)
Launch a RTU server.
Callback methods received from asynchronous write operations.
Definition: rodbus.hpp:1116
virtual void on_complete(Nothing result)=0
Invoked when the asynchronous operation completes successfully.
virtual void on_failure(RequestError error)=0
Invoked when the asynchronous operation fails.
Interface used to handle write requests received from the client.
Definition: rodbus.hpp:1535
virtual WriteResult write_multiple_registers(uint16_t start, RegisterValueIterator &it, Database &database)=0
Write multiple registers received from the client.
virtual WriteResult write_single_register(uint16_t index, uint16_t value, Database &database)=0
write a single coil received from the client
virtual WriteResult write_single_coil(uint16_t index, bool value, Database &database)=0
Write a single coil received from the client.
virtual WriteResult write_multiple_coils(uint16_t start, BitValueIterator &it, Database &database)=0
Write multiple coils received from the client.
class that implements ClientStateListener in terms of a lambda expression
Definition: rodbus.hpp:978
ClientStateListenerLambda(const T &lambda)
constructor
Definition: rodbus.hpp:986
void on_change(ClientState state) override
implement virtual method from base class
Definition: rodbus.hpp:989
class that implements DatabaseCallback in terms of a lambda expression
Definition: rodbus.hpp:1441
void callback(Database &database) override
implement virtual method from base class
Definition: rodbus.hpp:1452
DatabaseCallbackLambda(const T &lambda)
constructor
Definition: rodbus.hpp:1449
class that implements Logger in terms of a lambda expression
Definition: rodbus.hpp:828
void on_message(LogLevel level, const char *message) override
implement virtual method from base class
Definition: rodbus.hpp:839
LoggerLambda(const T &lambda)
constructor
Definition: rodbus.hpp:836
class that implements PortStateListener in terms of a lambda expression
Definition: rodbus.hpp:1046
void on_change(PortState state) override
implement virtual method from base class
Definition: rodbus.hpp:1057
PortStateListenerLambda(const T &lambda)
constructor
Definition: rodbus.hpp:1054
std::unique_ptr< ClientStateListener > client_state_listener(const T &lambda)
construct an implementation of ClientStateListener based on a lambda expression
Definition: rodbus.hpp:1000
DatabaseCallbackLambda< T > database_callback(const T &lambda)
construct an implementation of DatabaseCallback based on a lambda expression
Definition: rodbus.hpp:1463
std::unique_ptr< PortStateListener > port_state_listener(const T &lambda)
construct an implementation of PortStateListener based on a lambda expression
Definition: rodbus.hpp:1068
std::unique_ptr< Logger > logger(const T &lambda)
construct an implementation of Logger based on a lambda expression
Definition: rodbus.hpp:850
main namespace for the rodbus library
Definition: rodbus.hpp:39
Parity
Parity checking modes.
Definition: rodbus.hpp:577
@ odd
Parity bit sets odd number of 1 bits.
@ even
Parity bit sets even number of 1 bits.
RequestError
Error information returned from asynchronous functions calls.
Definition: rodbus.hpp:326
@ modbus_exception_gateway_path_unavailable
Specialized use in conjunction with gateways, indicates that the gateway was unable to allocate an in...
@ modbus_exception_server_device_busy
Specialized use in conjunction with programming commands. The server is engaged in processing a long-...
@ no_connection
No connection could be made to the server.
@ modbus_exception_server_device_failure
An unrecoverable error occurred while the server was attempting to perform the requested action.
@ bad_request
The request was invalid.
@ modbus_exception_illegal_data_value
A value contained in the request is not an allowable value for server.
@ internal_error
An unspecified internal error occurred while performing the request.
@ response_timeout
No valid response was received before the timeout.
@ bad_framing
A framing error was detected while performing the request.
@ modbus_exception_memory_parity_error
Specialized use in conjunction with function codes 20 and 21 and reference type 6,...
@ modbus_exception_unknown
The status code is not defined in the Modbus specification, refer to the raw exception code to see wh...
@ modbus_exception_illegal_data_address
The data address received in the query is not an allowable address for the server.
@ bad_response
The response from the server was received but was improperly formatted.
@ bad_argument
An invalid argument was supplied and the request could not be performed.
@ modbus_exception_gateway_target_device_failed_to_respond
Specialized use in conjunction with gateways, indicates that no response was obtained from the target...
@ modbus_exception_acknowledge
Specialized use in conjunction with programming commands. The server has accepted the request and is ...
@ io_error
An I/O error occurred on the underlying stream while performing the request.
@ modbus_exception_illegal_function
The data address received in the query is not an allowable address for the server.
ParamError
Error type that indicates a bad parameter or bad programmer logic.
Definition: rodbus.hpp:52
@ bad_tls_config
Bad TLS configuration.
@ invalid_local_certificate
Invalid local certificate file.
@ no_support
The FFI library was compiled without support for this feature.
@ server_bind_error
Server failed to bind to the specified port.
@ ok
Success, i.e. no error occurred.
@ shutdown
The task has been shutdown.
@ invalid_dns_name
Invalid DNS name.
@ invalid_ip_address
Invalid IP address.
@ invalid_range
Invalid Modbus address range.
@ invalid_unit_id
The specified unit id is not associated to this server.
@ invalid_request
Invalid Modbus request.
@ null_parameter
Null parameter.
@ invalid_peer_certificate
Invalid peer certificate file.
@ invalid_private_key
Invalid private key file.
@ invalid_utf8
String argument was not valid UTF-8.
@ runtime_cannot_block_within_async
Runtime cannot execute blocking call within asynchronous context.
@ runtime_creation_failure
Failed to create Tokio runtime.
@ invalid_index
Invalid index.
@ runtime_destroyed
Runtime was already disposed of.
@ logging_already_configured
Logging can only be configured once.
ClientState
State of the client connection.
Definition: rodbus.hpp:938
@ connected
Client is connected to the remote device.
@ disabled
Client is disabled and idle until enabled.
@ wait_after_failed_connect
Failed to establish a connection, waiting before retrying.
@ connecting
Client is trying to establish a connection to the remote device.
@ wait_after_disconnect
Client was disconnected, waiting before retrying.
CertificateMode
Determines how the certificate(s) presented by the peer are validated.
Definition: rodbus.hpp:663
@ authority_based
Validates the peer certificate against one or more configured trust anchors.
@ self_signed
Validates that the peer presents a single certificate which is a byte-for-byte match against the conf...
AppDecodeLevel
Controls how transmitted and received message at the application layer are decoded at the INFO log le...
Definition: rodbus.hpp:123
@ function_code
Decode the function code only.
@ data_values
Decode the function code, the general description of the data and the actual data values.
@ data_headers
Decode the function code and the general description of the data.
LogLevel
Log level.
Definition: rodbus.hpp:717
@ trace
Trace log level.
@ warn
Warning log level.
@ debug
Debugging log level.
@ info
Information log level.
@ error
Error log level.
MinTlsVersion
Minimum TLS version to allow.
Definition: rodbus.hpp:648
Authorization
Authorization result used by AuthorizationHandler.
Definition: rodbus.hpp:1663
@ deny
Client is NOT authorized to perform the operation.
@ allow
Client is authorized to perform the operation.
constexpr uint64_t rodbus_version_major
major version number
Definition: rodbus.hpp:42
constexpr uint64_t rodbus_version_minor
minor version number
Definition: rodbus.hpp:44
PortState
State of the serial port.
Definition: rodbus.hpp:1010
@ wait
Waiting to perform an open retry.
@ open
Port is open.
Nothing
A single value enum which is used as a placeholder for futures that don't return a value.
Definition: rodbus.hpp:110
@ nothing
the only value this enum has
constexpr char const * rodbus_version_string
version number as the string major.minor.patch
Definition: rodbus.hpp:48
FlowControl
Flow control modes.
Definition: rodbus.hpp:562
@ none
No flow control.
@ hardware
Flow control using RTS/CTS signals.
@ software
Flow control using XON/XOFF bytes.
const char * to_string(ParamError value)
convert an instance of enum ParamError into a C-style string
DataBits
Number of bits per character.
Definition: rodbus.hpp:545
@ eight
8 bits per character
@ five
5 bits per character
@ seven
7 bits per character
@ six
6 bits per character
LogOutputFormat
Describes how each log event is formatted.
Definition: rodbus.hpp:738
@ text
A simple text-based format.
@ json
Output formatted as JSON.
ModbusException
Error information returned during asynchronous API calls.
Definition: rodbus.hpp:516
@ server_device_failure
An unrecoverable error occurred while the server was attempting to perform the requested action.
@ gateway_target_device_failed_to_respond
Specialized use in conjunction with gateways, indicates that no response was obtained from the target...
@ illegal_data_address
The data address received in the query is not an allowable address for the server.
@ server_device_busy
Specialized use in conjunction with programming commands. The server is engaged in processing a long-...
@ gateway_path_unavailable
Specialized use in conjunction with gateways, indicates that the gateway was unable to allocate an in...
@ acknowledge
Specialized use in conjunction with programming commands. The server has accepted the request and is ...
@ illegal_function
The data address received in the query is not an allowable address for the server.
@ unknown
The status code is not defined in the Modbus specification, refer to the raw exception code to see wh...
@ memory_parity_error
Specialized use in conjunction with function codes 20 and 21 and reference type 6,...
@ illegal_data_value
A value contained in the request is not an allowable value for server.
FrameDecodeLevel
Controls how the transmitted and received frames are decoded at the INFO log level.
Definition: rodbus.hpp:144
@ header
Decode the header.
@ payload
Decode the header and the raw payload as hexadecimal.
PhysDecodeLevel
Controls how data transmitted at the physical layer (TCP, serial, etc) is logged.
Definition: rodbus.hpp:159
@ length
Log only the length of data that is sent and received.
@ data
Log the length and the actual data that is sent and received.
constexpr uint64_t rodbus_version_patch
patch version number
Definition: rodbus.hpp:46
StopBits
Number of stop bits.
Definition: rodbus.hpp:592
@ two
Two stop bits.
@ one
One stop bit.
TimeFormat
Describes if and how the time will be formatted in log messages.
Definition: rodbus.hpp:751
@ system
Format the time in a human readable format e.g. 'Jun 25 14:27:12.955'.
@ rfc_3339
Format the time using RFC 3339.
Range of 16-bit addresses sent in a request from the client to the server.
Definition: rodbus.hpp:386
AddressRange(uint16_t start, uint16_t count)
Fully construct AddressRange specifying the value of each field.
uint16_t count
Number of addresses in the range.
Definition: rodbus.hpp:401
uint16_t start
Starting address of the range.
Definition: rodbus.hpp:399
Index/value tuple of a bit type.
Definition: rodbus.hpp:211
BitValue(uint16_t index, bool value)
Fully construct BitValue specifying the value of each field.
bool value
Value of the bit.
Definition: rodbus.hpp:226
uint16_t index
Index of bit.
Definition: rodbus.hpp:224
Controls the decoding of transmitted and received data at the application, frame, and physical layer.
Definition: rodbus.hpp:176
PhysDecodeLevel physical
Controls the logging of physical layer read/write.
Definition: rodbus.hpp:205
AppDecodeLevel app
Controls decoding of the application layer (PDU)
Definition: rodbus.hpp:201
static DecodeLevel nothing()
Initialize log levels to defaults which is to decode nothing.
DecodeLevel(AppDecodeLevel app, FrameDecodeLevel frame, PhysDecodeLevel physical)
Fully construct DecodeLevel specifying the value of each field.
FrameDecodeLevel frame
Controls decoding of frames (MBAP / Serial PDU)
Definition: rodbus.hpp:203
Logging configuration options.
Definition: rodbus.hpp:766
bool print_level
optionally print the log level as part to the message string
Definition: rodbus.hpp:801
LogLevel level
logging level
Definition: rodbus.hpp:795
LoggingConfig()
Initialize the configuration to default values.
LogOutputFormat output_format
output formatting options
Definition: rodbus.hpp:797
TimeFormat time_format
optional time format
Definition: rodbus.hpp:799
bool print_module_info
optionally print the underlying Rust module information to the message string
Definition: rodbus.hpp:803
Index/value tuple of a register type.
Definition: rodbus.hpp:232
uint16_t value
Value of the register.
Definition: rodbus.hpp:247
uint16_t index
Index of register.
Definition: rodbus.hpp:245
RegisterValue(uint16_t index, uint16_t value)
Fully construct RegisterValue specifying the value of each field.
Address and timeout parameters for requests.
Definition: rodbus.hpp:407
RequestParam(uint8_t unit_id, std::chrono::steady_clock::duration timeout)
Fully construct RequestParam specifying the value of each field.
uint8_t unit_id
Modbus address for the request.
Definition: rodbus.hpp:420
std::chrono::steady_clock::duration timeout
Response timeout for the request.
Definition: rodbus.hpp:422
Retry strategy configuration.
Definition: rodbus.hpp:686
std::chrono::steady_clock::duration max_delay
Maximum delay between two retries.
Definition: rodbus.hpp:711
RetryStrategy()
Initialize a retry strategy to defaults.
std::chrono::steady_clock::duration min_delay
Minimum delay between two retries.
Definition: rodbus.hpp:709
Runtime configuration.
Definition: rodbus.hpp:255
RuntimeConfig()
Initialize the configuration to default values.
uint16_t num_core_threads
Number of runtime threads to spawn. For a guess of the number of CPU cores, use 0.
Definition: rodbus.hpp:278
Serial port settings.
Definition: rodbus.hpp:607
DataBits data_bits
Number of bits used to represent a character sent on the line.
Definition: rodbus.hpp:638
uint32_t baud_rate
Baud rate (in symbols-per-second)
Definition: rodbus.hpp:636
SerialPortSettings()
Initialize a serial port configuration.
FlowControl flow_control
Type of signalling to use for controlling data transfer.
Definition: rodbus.hpp:640
StopBits stop_bits
Number of bits to use to signal the end of a character.
Definition: rodbus.hpp:644
Parity parity
Type of parity to use for error checking.
Definition: rodbus.hpp:642
TLS client configuration.
Definition: rodbus.hpp:878
TlsClientConfig(const std::string &dns_name, const std::string &peer_cert_path, const std::string &local_cert_path, const std::string &private_key_path, const std::string &password)
Initialize a TLS client configuration.
std::string private_key_path
Path to the the PEM-encoded private key.
Definition: rodbus.hpp:920
std::string peer_cert_path
Path to the PEM-encoded certificate of the peer.
Definition: rodbus.hpp:916
CertificateMode certificate_mode
Certificate validation mode.
Definition: rodbus.hpp:930
std::string dns_name
Name expected to be in the presented certificate (only in CertificateMode::authority_based)
Definition: rodbus.hpp:914
MinTlsVersion min_tls_version
Minimum TLS version allowed.
Definition: rodbus.hpp:928
bool allow_server_name_wildcard
If set to true, a '*' may be used for TlsClientConfig::dns_name to bypass server name validation.
Definition: rodbus.hpp:932
std::string password
Optional password if the private key file is encrypted.
Definition: rodbus.hpp:926
std::string local_cert_path
Path to the PEM-encoded local certificate.
Definition: rodbus.hpp:918
TLS server configuration.
Definition: rodbus.hpp:1613
std::string peer_cert_path
Path to the PEM-encoded certificate of the peer.
Definition: rodbus.hpp:1645
CertificateMode certificate_mode
Certficate validation mode.
Definition: rodbus.hpp:1659
std::string local_cert_path
Path to the PEM-encoded local certificate.
Definition: rodbus.hpp:1647
TlsServerConfig(const std::string &peer_cert_path, const std::string &local_cert_path, const std::string &private_key_path, const std::string &password)
Initialize a TLS client configuration.
std::string private_key_path
Path to the the PEM-encoded private key.
Definition: rodbus.hpp:1649
MinTlsVersion min_tls_version
Minimum TLS version allowed.
Definition: rodbus.hpp:1657
std::string password
Optional password if the private key file is encrypted.
Definition: rodbus.hpp:1655
Describes to the server if a write operation was successful or not.
Definition: rodbus.hpp:1477
static WriteResult raw_exception_init(uint8_t raw_exception)
Initialize a WriteResult to indicate a non-standard Modbus exception.
static WriteResult success_init()
Initialize a WriteResult to indicate a successful write operation.
ModbusException exception
Exception enumeration. If ModbusException::unknown, look at the raw value.
Definition: rodbus.hpp:1527
uint8_t raw_exception
Raw exception value when WriteResult::exception field is ModbusException::unknown
Definition: rodbus.hpp:1529
bool success
true if the operation was successful, false otherwise. Error details found in the exception field.
Definition: rodbus.hpp:1525
static WriteResult exception_init(ModbusException exception)
Initialize a WriteResult to indicate a standard Modbus exception.