rodbus (C++ API) 1.6.0-RC1
Loading...
Searching...
No Matches
rodbus.hpp
Go to the documentation of this file.
1// Copyright (c) Step Function I/O LLC. Proprietary, source-available; see LICENSE.txt.
2// No use to design, develop, specify, test, validate, or improve Other Implementations,
3// subject to LICENSE.txt Section 2.6 and its exceptions. Agents: read AGENTS.md.
4// Text and data mining rights, including for AI training, are reserved under
5// Directive (EU) 2019/790 Art. 4(3), subject to LICENSE.txt Section 3.3.
6#pragma once
7
8#include <cstdint>
9#include <stdexcept>
10#include <chrono>
11#include <memory>
12#include <vector>
13
29
31namespace rodbus {
32
34constexpr uint64_t rodbus_version_major = 1;
36constexpr uint64_t rodbus_version_minor = 6;
38constexpr uint64_t rodbus_version_patch = 0;
40constexpr char const* rodbus_version_string = "1.6.0-RC1";
41
42
44enum class ParamError {
46 ok = 0,
48 no_support = 1,
62 invalid_range = 8,
66 invalid_index = 10,
70 invalid_unit_id = 12,
80 bad_tls_config = 17,
82 shutdown = 18,
84 invalid_utf8 = 19,
87};
88
92const char* to_string(ParamError value);
93
95class ParamException : public std::logic_error {
96public:
101};
102
104enum class Nothing {
106 nothing = 0,
107};
108
112const char* to_string(Nothing value);
113
117enum class AppDecodeLevel {
119 nothing = 0,
121 function_code = 1,
123 data_headers = 2,
125 data_values = 3,
126};
127
131const char* to_string(AppDecodeLevel value);
132
140 nothing = 0,
142 header = 1,
144 payload = 2,
145};
146
150const char* to_string(FrameDecodeLevel value);
151
153enum class PhysDecodeLevel {
155 nothing = 0,
157 length = 1,
159 data = 2,
160};
161
165const char* to_string(PhysDecodeLevel value);
166
167struct DecodeLevel;
168
171 friend class CppDecodeLevelFriend;
172
173 DecodeLevel() = delete;
174
181
182
192
193
200};
201
202struct BitValue;
203
207struct BitValue {
208 friend class CppBitValueFriend;
209
210 BitValue() = delete;
211
216 BitValue(uint16_t index, bool value);
217
218
220 uint16_t index;
222 bool value;
223};
224
225struct RegisterValue;
226
231 friend class CppRegisterValueFriend;
232
233 RegisterValue() = delete;
234
239 RegisterValue(uint16_t index, uint16_t value);
240
241
243 uint16_t index;
245 uint16_t value;
246};
247
248class Runtime;
249
250struct RuntimeConfig;
251
254 friend class CppRuntimeConfigFriend;
255
256private:
261
262public:
263
271
272
277};
278
280class Runtime {
281 friend class CppRuntimeFriend;
282 // pointer to the underlying C type
283 void* self;
284 // constructor only accessible internally
285 Runtime(void* self): self(self) {}
286 // non-copyable
287 Runtime(const Runtime&) = delete;
288 Runtime& operator=(const Runtime&) = delete;
289 // no move assignment
290 Runtime& operator=(Runtime&& other) = delete;
291
292public:
296 Runtime(Runtime&& other) noexcept : self(other.self) { other.self = nullptr; }
297
304 Runtime(const RuntimeConfig& config);
305
310
318 void set_shutdown_timeout(std::chrono::steady_clock::duration timeout);
319};
320
324enum class RequestError {
326 ok = 0,
328 shutdown = 1,
330 no_connection = 2,
334 bad_request = 4,
336 bad_response = 5,
338 io_error = 6,
340 bad_framing = 7,
342 internal_error = 8,
344 bad_argument = 9,
365};
366
370const char* to_string(RequestError value);
371
373class RequestException : public std::logic_error {
374public:
379};
380
381struct AddressRange;
382
385 friend class CppAddressRangeFriend;
386
387 AddressRange() = delete;
388
393 AddressRange(uint16_t start, uint16_t count);
394
395
397 uint16_t start;
399 uint16_t count;
400};
401
402struct RequestParam;
403
406 friend class CppRequestParamFriend;
407
408 RequestParam() = delete;
409
414 RequestParam(uint8_t unit_id, std::chrono::steady_clock::duration timeout);
415
416
418 uint8_t unit_id;
420 std::chrono::steady_clock::duration timeout;
421};
422
423class BitValueIterator;
424
436class BitValueIterator final {
437
438 friend class CppBitValueIteratorFriend;
439
440 // underlying opaque c type
441 void* iter;
442 // pointer to the last retrieved c value
443 void* current;
444
445 // internal constructor
446 BitValueIterator(void* iter) : iter(iter), current(nullptr) {}
447
448 BitValueIterator() = delete; // no default construction
449 BitValueIterator(const BitValueIterator&) = delete; // no copies
450 BitValueIterator& operator=(const BitValueIterator&) = delete; // no self-assignment
451 BitValueIterator& operator=(BitValueIterator&&) = delete; // no move self-assignment
452
453public:
454
457
460 bool next();
461
466};
467
469
482
483 friend class CppRegisterValueIteratorFriend;
484
485 // underlying opaque c type
486 void* iter;
487 // pointer to the last retrieved c value
488 void* current;
489
490 // internal constructor
491 RegisterValueIterator(void* iter) : iter(iter), current(nullptr) {}
492
493 RegisterValueIterator() = delete; // no default construction
494 RegisterValueIterator(const RegisterValueIterator&) = delete; // no copies
495 RegisterValueIterator& operator=(const RegisterValueIterator&) = delete; // no self-assignment
496 RegisterValueIterator& operator=(RegisterValueIterator&&) = delete; // no move self-assignment
497
498public:
499
502
505 bool next();
506
511};
512
514enum class ModbusException {
524 acknowledge = 5,
534 unknown = 255,
535};
536
540const char* to_string(ModbusException value);
541
543enum class DataBits {
545 five = 0,
547 six = 1,
549 seven = 2,
551 eight = 3,
552};
553
557const char* to_string(DataBits value);
558
560enum class FlowControl {
562 none = 0,
564 software = 1,
566 hardware = 2,
567};
568
572const char* to_string(FlowControl value);
573
575enum class Parity {
577 none = 0,
579 odd = 1,
581 even = 2,
582};
583
587const char* to_string(Parity value);
588
590enum class StopBits {
592 one = 0,
594 two = 1,
595};
596
600const char* to_string(StopBits value);
601
602struct SerialPortSettings;
603
606 friend class CppSerialPortSettingsFriend;
607
608private:
617
618public:
619
631
632
636 uint32_t baud_rate;
645};
646
648enum class MinTlsVersion {
650 v12 = 0,
654 v13 = 1,
655};
656
660const char* to_string(MinTlsVersion value);
661
665enum class CertificateMode {
671 authority_based = 0,
675 self_signed = 1,
676};
677
681const char* to_string(CertificateMode value);
682
683struct RetryStrategy;
684
689 friend class CppRetryStrategyFriend;
690
691private:
696 RetryStrategy(std::chrono::steady_clock::duration min_delay, std::chrono::steady_clock::duration max_delay);
697
698public:
699
708
709
711 std::chrono::steady_clock::duration min_delay;
713 std::chrono::steady_clock::duration max_delay;
714};
715
719enum class LogLevel {
721 error = 0,
723 warn = 1,
725 info = 2,
727 debug = 3,
729 trace = 4,
730};
731
735const char* to_string(LogLevel value);
736
737struct LoggingConfig;
738
740enum class LogOutputFormat {
742 text = 0,
744 json = 1,
745};
746
750const char* to_string(LogOutputFormat value);
751
753enum class TimeFormat {
755 none = 0,
757 rfc_3339 = 1,
759 system = 2,
760};
761
765const char* to_string(TimeFormat value);
766
769 friend class CppLoggingConfigFriend;
770
771private:
780
781public:
782
794
795
806};
807
811class Logger {
812public:
813 virtual ~Logger() = default;
814
819 virtual void on_message(LogLevel level, const char* message) = 0;
820
821};
822
824namespace functional {
825
828template <class T>
829class LoggerLambda final : public Logger
830{
831 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
832
833 T lambda;
834
835public:
838 LoggerLambda(const T& lambda) : lambda(lambda) {}
839
841 void on_message(LogLevel level, const char* message) override
842 {
843 lambda(level, message);
844 }
845};
846
851template <class T>
852std::unique_ptr<Logger> logger(const T& lambda)
853{
854 return std::make_unique<LoggerLambda<T>>(lambda); ;
855}
856
857} // end namespace functional
858
860class Logging {
861 Logging() = delete;
862public:
872 static void configure(const LoggingConfig& config, std::unique_ptr<Logger> logger);
873};
874
875class ClientChannel;
876
877struct TlsClientConfig;
878
881 friend class CppTlsClientConfigFriend;
882
883private:
894 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);
895
896public:
897 TlsClientConfig() = delete;
898
912 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);
913
914
916 std::string dns_name;
918 std::string peer_cert_path;
920 std::string local_cert_path;
922 std::string private_key_path;
928 std::string password;
935};
936
940enum class ClientState {
942 disabled = 0,
944 connecting = 1,
946 connected = 2,
952 shutdown = 5,
953};
954
958const char* to_string(ClientState value);
959
964public:
965 virtual ~ClientStateListener() = default;
966
970 virtual void on_change(ClientState state) = 0;
971
972};
973
974namespace functional {
975
978template <class T>
980{
981 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
982
983 T lambda;
984
985public:
988 ClientStateListenerLambda(const T& lambda) : lambda(lambda) {}
989
991 void on_change(ClientState state) override
992 {
993 lambda(state);
994 }
995};
996
1001template <class T>
1002std::unique_ptr<ClientStateListener> client_state_listener(const T& lambda)
1003{
1004 return std::make_unique<ClientStateListenerLambda<T>>(lambda); ;
1005}
1006
1007} // end namespace functional
1008
1012enum class PortState {
1014 disabled = 0,
1016 wait = 1,
1018 open = 2,
1020 shutdown = 3,
1021};
1022
1026const char* to_string(PortState value);
1027
1032public:
1033 virtual ~PortStateListener() = default;
1034
1038 virtual void on_change(PortState state) = 0;
1039
1040};
1041
1042namespace functional {
1043
1046template <class T>
1048{
1049 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
1050
1051 T lambda;
1052
1053public:
1056 PortStateListenerLambda(const T& lambda) : lambda(lambda) {}
1057
1059 void on_change(PortState state) override
1060 {
1061 lambda(state);
1062 }
1063};
1064
1069template <class T>
1070std::unique_ptr<PortStateListener> port_state_listener(const T& lambda)
1071{
1072 return std::make_unique<PortStateListenerLambda<T>>(lambda); ;
1073}
1074
1075} // end namespace functional
1076
1083public:
1084 virtual ~BitReadCallback() = default;
1085
1089 virtual void on_complete(BitValueIterator& result) = 0;
1090
1094 virtual void on_failure(RequestError error) = 0;
1095
1096};
1097
1104public:
1105 virtual ~RegisterReadCallback() = default;
1106
1110 virtual void on_complete(RegisterValueIterator& result) = 0;
1111
1115 virtual void on_failure(RequestError error) = 0;
1116
1117};
1118
1123public:
1124 virtual ~WriteCallback() = default;
1125
1129 virtual void on_complete(Nothing result) = 0;
1130
1134 virtual void on_failure(RequestError error) = 0;
1135
1136};
1137
1142 friend class CppClientChannelFriend;
1143 // pointer to the underlying C type
1144 void* self;
1145 // constructor only accessible internally
1146 ClientChannel(void* self): self(self) {}
1147 // non-copyable
1148 ClientChannel(const ClientChannel&) = delete;
1149 ClientChannel& operator=(const ClientChannel&) = delete;
1150 // no move assignment
1151 ClientChannel& operator=(ClientChannel&& other) = delete;
1152
1153public:
1157 ClientChannel(ClientChannel&& other) noexcept : self(other.self) { other.self = nullptr; }
1158
1161
1167 void enable();
1168
1174 void disable();
1175
1180 void set_decode_level(const DecodeLevel& level);
1181
1195 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);
1196
1210 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);
1211
1226 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);
1227
1234 void read_coils(const RequestParam& param, const AddressRange& range, std::unique_ptr<BitReadCallback> callback);
1235
1236
1243 void read_discrete_inputs(const RequestParam& param, const AddressRange& range, std::unique_ptr<BitReadCallback> callback);
1244
1245
1252 void read_holding_registers(const RequestParam& param, const AddressRange& range, std::unique_ptr<RegisterReadCallback> callback);
1253
1254
1261 void read_input_registers(const RequestParam& param, const AddressRange& range, std::unique_ptr<RegisterReadCallback> callback);
1262
1263
1270 void write_single_coil(const RequestParam& param, const BitValue& value, std::unique_ptr<WriteCallback> callback);
1271
1272
1279 void write_single_register(const RequestParam& param, const RegisterValue& value, std::unique_ptr<WriteCallback> callback);
1280
1281
1289 void write_multiple_coils(const RequestParam& param, uint16_t start, const std::vector<bool>& items, std::unique_ptr<WriteCallback> callback);
1290
1291
1299 void write_multiple_registers(const RequestParam& param, uint16_t start, const std::vector<uint16_t>& items, std::unique_ptr<WriteCallback> callback);
1300
1301};
1302
1303class Database;
1304
1307 friend class CppDatabaseFriend;
1308 // pointer to the underlying C type
1309 void* self;
1310 // constructor only accessible internally
1311 Database(void* self): self(self) {}
1312 // non-copyable
1313 Database(const Database&) = delete;
1314 Database& operator=(const Database&) = delete;
1315 // no move assignment
1316 Database& operator=(Database&& other) = delete;
1317
1318public:
1322 Database(Database&& other) noexcept : self(other.self) { other.self = nullptr; }
1323
1329 bool add_coil(uint16_t index, bool value);
1330
1336 bool add_discrete_input(uint16_t index, bool value);
1337
1343 bool add_holding_register(uint16_t index, uint16_t value);
1344
1350 bool add_input_register(uint16_t index, uint16_t value);
1351
1357 bool get_coil(uint16_t index);
1358
1364 bool get_discrete_input(uint16_t index);
1365
1371 uint16_t get_holding_register(uint16_t index);
1372
1378 uint16_t get_input_register(uint16_t index);
1379
1385 bool update_coil(uint16_t index, bool value);
1386
1392 bool update_discrete_input(uint16_t index, bool value);
1393
1399 bool update_holding_register(uint16_t index, uint16_t value);
1400
1406 bool update_input_register(uint16_t index, uint16_t value);
1407
1412 bool delete_coil(uint16_t index);
1413
1418 bool delete_discrete_input(uint16_t index);
1419
1424 bool delete_holding_register(uint16_t index);
1425
1430 bool delete_input_register(uint16_t index);
1431};
1432
1437public:
1438 virtual ~DatabaseCallback() = default;
1439
1443 virtual void callback(Database& database) = 0;
1444
1445};
1446
1447namespace functional {
1448
1451template <class T>
1453{
1454 static_assert(std::is_copy_constructible<T>::value, "Lambda expression must be copy constructible. Does it contain something that is move-only?");
1455
1456 T lambda;
1457
1458public:
1461 DatabaseCallbackLambda(const T& lambda) : lambda(lambda) {}
1462
1464 void callback(Database& database) override
1465 {
1466 lambda(database);
1467 }
1468};
1469
1474template <class T>
1476{
1477 return DatabaseCallbackLambda<T>(lambda);
1478}
1479
1480} // end namespace functional
1481
1482struct WriteResult;
1483
1490 friend class CppWriteResultFriend;
1491
1492private:
1499
1500public:
1501 WriteResult() = delete;
1502
1512
1513
1523
1524
1534
1535
1542};
1543
1548public:
1549 virtual ~WriteHandler() = default;
1550
1557 virtual WriteResult write_single_coil(uint16_t index, bool value, Database& database) = 0;
1558
1565 virtual WriteResult write_single_register(uint16_t index, uint16_t value, Database& database) = 0;
1566
1573 virtual WriteResult write_multiple_coils(uint16_t start, BitValueIterator& it, Database& database) = 0;
1574
1581 virtual WriteResult write_multiple_registers(uint16_t start, RegisterValueIterator& it, Database& database) = 0;
1582
1583};
1584
1585class DeviceMap;
1586
1589 friend class CppDeviceMapFriend;
1590 // pointer to the underlying C type
1591 void* self;
1592 // constructor only accessible internally
1593 DeviceMap(void* self): self(self) {}
1594 // non-copyable
1595 DeviceMap(const DeviceMap&) = delete;
1596 DeviceMap& operator=(const DeviceMap&) = delete;
1597 // no move assignment
1598 DeviceMap& operator=(DeviceMap&& other) = delete;
1599
1600public:
1604 DeviceMap(DeviceMap&& other) noexcept : self(other.self) { other.self = nullptr; }
1605
1609
1612
1619 bool add_endpoint(uint8_t unit_id, std::unique_ptr<WriteHandler> handler, DatabaseCallback& configure);
1620};
1621
1622struct TlsServerConfig;
1623
1626 friend class CppTlsServerConfigFriend;
1627
1628private:
1637 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);
1638
1639public:
1640 TlsServerConfig() = delete;
1641
1653 TlsServerConfig(const std::string& peer_cert_path, const std::string& local_cert_path, const std::string& private_key_path, const std::string& password);
1654
1655
1657 std::string peer_cert_path;
1659 std::string local_cert_path;
1661 std::string private_key_path;
1667 std::string password;
1672};
1673
1675enum class Authorization {
1677 allow = 0,
1679 deny = 1,
1680};
1681
1685const char* to_string(Authorization value);
1686
1691public:
1692 virtual ~AuthorizationHandler() = default;
1693
1700 virtual Authorization read_coils(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1701
1708 virtual Authorization read_discrete_inputs(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1709
1716 virtual Authorization read_holding_registers(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1717
1724 virtual Authorization read_input_registers(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1725
1732 virtual Authorization write_single_coil(uint8_t unit_id, uint16_t index, const char* role) = 0;
1733
1740 virtual Authorization write_single_register(uint8_t unit_id, uint16_t index, const char* role) = 0;
1741
1748 virtual Authorization write_multiple_coils(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1749
1756 virtual Authorization write_multiple_registers(uint8_t unit_id, const AddressRange& range, const char* role) = 0;
1757
1758};
1759
1760class AddressFilter;
1761
1764 friend class CppAddressFilterFriend;
1765 // pointer to the underlying C type
1766 void* self;
1767 // constructor only accessible internally
1768 AddressFilter(void* self): self(self) {}
1769 // non-copyable
1770 AddressFilter(const AddressFilter&) = delete;
1771 AddressFilter& operator=(const AddressFilter&) = delete;
1772 // no move assignment
1773 AddressFilter& operator=(AddressFilter&& other) = delete;
1774
1775public:
1779 AddressFilter(AddressFilter&& other) noexcept : self(other.self) { other.self = nullptr; }
1780
1791 AddressFilter(const std::string& address);
1792
1795
1802 void add(const std::string& address);
1803
1808};
1809
1810class Server;
1811
1813class Server {
1814 friend class CppServerFriend;
1815 // pointer to the underlying C type
1816 void* self;
1817 // constructor only accessible internally
1818 Server(void* self): self(self) {}
1819 // non-copyable
1820 Server(const Server&) = delete;
1821 Server& operator=(const Server&) = delete;
1822 // no move assignment
1823 Server& operator=(Server&& other) = delete;
1824
1825public:
1829 Server(Server&& other) noexcept : self(other.self) { other.self = nullptr; }
1830
1833
1839 void update_database(uint8_t unit_id, DatabaseCallback& transaction);
1840
1845 void set_decode_level(const DecodeLevel& level);
1846
1862 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);
1863
1874 static Server create_rtu(Runtime& runtime, const std::string& path, const SerialPortSettings& serial_params, const RetryStrategy& retry, DeviceMap& endpoints, const DecodeLevel& decode_level);
1875
1895 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);
1896
1913 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);
1914};
1915
1916} // end namespace rodbus
Filter used to restrict which IP addresses may communicate with a server.
Definition: rodbus.hpp:1763
AddressFilter(AddressFilter &&other) noexcept
Transfer ownership of the underlying C-type to this instance and invalidate the other instance.
Definition: rodbus.hpp:1779
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:1690
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:1082
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:436
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:1141
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:1157
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:963
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:1436
virtual void callback(Database &database)=0
callback function
Class used to add, remove, update, and retrieve values.
Definition: rodbus.hpp:1306
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:1322
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:1588
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:1604
~DeviceMap()
Destroy a previously created device map.
Logging interface that receives the log messages and writes them somewhere.
Definition: rodbus.hpp:811
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:860
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:95
ParamException(ParamError error)
construct the exception with an instance of the enum
Definition: rodbus.hpp:100
ParamError error
underlying error enum
Definition: rodbus.hpp:98
Callback interface for receiving updates about the state of a serial port.
Definition: rodbus.hpp:1031
virtual void on_change(PortState state)=0
Invoked when the serial port changes state.
Callbacks received when reading holding or input registers.
Definition: rodbus.hpp:1103
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:481
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:373
RequestError error
underlying error enum
Definition: rodbus.hpp:376
RequestException(RequestError error)
construct the exception with an instance of the enum
Definition: rodbus.hpp:378
Handle to the underlying runtime.
Definition: rodbus.hpp:280
~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:296
Handle to the running server. The server runs on a background task until this class is destroyed.
Definition: rodbus.hpp:1813
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:1829
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:1122
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:1547
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 register 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:980
ClientStateListenerLambda(const T &lambda)
constructor
Definition: rodbus.hpp:988
void on_change(ClientState state) override
implement virtual method from base class
Definition: rodbus.hpp:991
class that implements DatabaseCallback in terms of a lambda expression
Definition: rodbus.hpp:1453
void callback(Database &database) override
implement virtual method from base class
Definition: rodbus.hpp:1464
DatabaseCallbackLambda(const T &lambda)
constructor
Definition: rodbus.hpp:1461
class that implements Logger in terms of a lambda expression
Definition: rodbus.hpp:830
void on_message(LogLevel level, const char *message) override
implement virtual method from base class
Definition: rodbus.hpp:841
LoggerLambda(const T &lambda)
constructor
Definition: rodbus.hpp:838
class that implements PortStateListener in terms of a lambda expression
Definition: rodbus.hpp:1048
void on_change(PortState state) override
implement virtual method from base class
Definition: rodbus.hpp:1059
PortStateListenerLambda(const T &lambda)
constructor
Definition: rodbus.hpp:1056
std::unique_ptr< ClientStateListener > client_state_listener(const T &lambda)
construct an implementation of ClientStateListener based on a lambda expression
Definition: rodbus.hpp:1002
DatabaseCallbackLambda< T > database_callback(const T &lambda)
construct an implementation of DatabaseCallback based on a lambda expression
Definition: rodbus.hpp:1475
std::unique_ptr< PortStateListener > port_state_listener(const T &lambda)
construct an implementation of PortStateListener based on a lambda expression
Definition: rodbus.hpp:1070
std::unique_ptr< Logger > logger(const T &lambda)
construct an implementation of Logger based on a lambda expression
Definition: rodbus.hpp:852
main namespace for the rodbus library
Definition: rodbus.hpp:31
Parity
Parity checking modes.
Definition: rodbus.hpp:575
@ 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:324
@ 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
The channel had no connection (or open serial port) for the request: it was disabled,...
@ 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:44
@ 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.
@ too_many_requests
Number of requests exceeds configured limit.
@ 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:940
@ 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:665
@ 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:117
@ 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:719
@ 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
@ v12
Allow TLS 1.2 and TLS 1.3.
@ v13
Allow only TLS 1.3.
Authorization
Authorization result used by AuthorizationHandler.
Definition: rodbus.hpp:1675
@ 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:34
constexpr uint64_t rodbus_version_minor
minor version number
Definition: rodbus.hpp:36
PortState
State of the serial port.
Definition: rodbus.hpp:1012
@ 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:104
@ nothing
the only value this enum has
constexpr char const * rodbus_version_string
version number as the string major.minor.patch
Definition: rodbus.hpp:40
FlowControl
Flow control modes.
Definition: rodbus.hpp:560
@ 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:543
@ 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:740
@ text
A simple text-based format.
@ json
Output formatted as JSON.
ModbusException
Error information returned during asynchronous API calls.
Definition: rodbus.hpp:514
@ 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:138
@ 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:153
@ 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:38
StopBits
Number of stop bits.
Definition: rodbus.hpp:590
@ two
Two stop bits.
@ one
One stop bit.
TimeFormat
Describes if and how the time will be formatted in log messages.
Definition: rodbus.hpp:753
@ 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:384
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:399
uint16_t start
Starting address of the range.
Definition: rodbus.hpp:397
Bit value and its address.
Definition: rodbus.hpp:207
BitValue(uint16_t index, bool value)
Fully construct BitValue specifying the value of each field.
bool value
Value of the bit.
Definition: rodbus.hpp:222
uint16_t index
Address of the bit.
Definition: rodbus.hpp:220
Controls the decoding of transmitted and received data at the application, frame, and physical layer.
Definition: rodbus.hpp:170
PhysDecodeLevel physical
Controls the logging of physical layer read/write.
Definition: rodbus.hpp:199
AppDecodeLevel app
Controls decoding of the application layer (PDU)
Definition: rodbus.hpp:195
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:197
Logging configuration options.
Definition: rodbus.hpp:768
bool print_level
optionally print the log level as part to the message string
Definition: rodbus.hpp:803
LogLevel level
logging level
Definition: rodbus.hpp:797
LoggingConfig()
Initialize the configuration to default values.
LogOutputFormat output_format
output formatting options
Definition: rodbus.hpp:799
TimeFormat time_format
optional time format
Definition: rodbus.hpp:801
bool print_module_info
optionally print the underlying Rust module information to the message string
Definition: rodbus.hpp:805
Register value and its address.
Definition: rodbus.hpp:230
uint16_t value
Value of the register.
Definition: rodbus.hpp:245
uint16_t index
Address of the register.
Definition: rodbus.hpp:243
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:405
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:418
std::chrono::steady_clock::duration timeout
Response timeout for the request. It covers sending the request and receiving the response....
Definition: rodbus.hpp:420
Retry strategy configuration.
Definition: rodbus.hpp:688
std::chrono::steady_clock::duration max_delay
Maximum delay between two retries.
Definition: rodbus.hpp:713
RetryStrategy()
Initialize a retry strategy to defaults.
std::chrono::steady_clock::duration min_delay
Minimum delay between two retries.
Definition: rodbus.hpp:711
Runtime configuration.
Definition: rodbus.hpp:253
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:276
Serial port settings.
Definition: rodbus.hpp:605
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:880
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 PEM-encoded private key.
Definition: rodbus.hpp:922
std::string peer_cert_path
Path to the PEM-encoded trusted CA certificate(s) in CertificateMode::authority_based mode,...
Definition: rodbus.hpp:918
CertificateMode certificate_mode
Certificate validation mode.
Definition: rodbus.hpp:932
std::string dns_name
Name expected to be in the presented certificate (only in CertificateMode::authority_based)
Definition: rodbus.hpp:916
MinTlsVersion min_tls_version
Minimum TLS version allowed.
Definition: rodbus.hpp:930
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:934
std::string password
Optional password if the private key file is encrypted.
Definition: rodbus.hpp:928
std::string local_cert_path
Path to the PEM-encoded local certificate.
Definition: rodbus.hpp:920
TLS server configuration.
Definition: rodbus.hpp:1625
std::string peer_cert_path
Path to the PEM-encoded trusted CA certificate(s) in CertificateMode::authority_based mode,...
Definition: rodbus.hpp:1657
CertificateMode certificate_mode
Certificate validation mode.
Definition: rodbus.hpp:1671
std::string local_cert_path
Path to the PEM-encoded local certificate.
Definition: rodbus.hpp:1659
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 server configuration.
std::string private_key_path
Path to the PEM-encoded private key.
Definition: rodbus.hpp:1661
MinTlsVersion min_tls_version
Minimum TLS version allowed.
Definition: rodbus.hpp:1669
std::string password
Optional password if the private key file is encrypted.
Definition: rodbus.hpp:1667
Describes to the server if a write operation was successful or not.
Definition: rodbus.hpp:1489
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:1539
uint8_t raw_exception
Raw exception value when WriteResult::exception field is ModbusException::unknown
Definition: rodbus.hpp:1541
bool success
true if the operation was successful, false otherwise. Error details found in the exception field.
Definition: rodbus.hpp:1537
static WriteResult exception_init(ModbusException exception)
Initialize a WriteResult to indicate a standard Modbus exception.