Modbus cpp 0.1
Loading...
Searching...
No Matches
modbusUtils.hpp
1// Modbus for c++ <https://github.com/Mazurel/Modbus>
2// Copyright (c) 2020 Mateusz Mazur aka Mazurel
3// Licensed under: MIT License <http://opensource.org/licenses/MIT>
4
5// This header files contain various utilities for Modbus Core library
6
7#pragma once
8
9#include <cstdint>
10#include <stdexcept>
11#include <string>
12#include <tuple>
13#include <vector>
14
15#include "MB/crc.hpp"
16
21namespace MB::utils {
25enum MBErrorCode : uint8_t {
26 // Documentation modbus errors
27 IllegalFunction = 0x01,
28 IllegalDataAddress = 0x02,
29 IllegalDataValue = 0x03,
30 SlaveDeviceFailure = 0x04,
31 Acknowledge = 0x05,
32 SlaveDeviceBusy = 0x06,
33 NegativeAcknowledge = 0x07,
34 MemoryParityError = 0x08,
35 GatewayPathUnavailable = 0x10,
36 GatewayTargetDeviceFailedToRespond = 0x11,
37
38 // Custom modbus errors
39 ErrorCodeCRCError = 0b0111111,
40 InvalidCRC = 0b01111110,
41 InvalidByteOrder = 0b01111101,
42 InvalidMessageID = 0b01111100,
43 ProtocolError = 0b01111011,
44 ConnectionClosed = 0b01111010,
45 Timeout = 0b01111001
46};
47
50 switch (code) {
51 case IllegalFunction:
52 case IllegalDataAddress:
53 case IllegalDataValue:
54 case SlaveDeviceFailure:
55 case Acknowledge:
56 case SlaveDeviceBusy:
57 case NegativeAcknowledge:
58 case MemoryParityError:
59 case GatewayPathUnavailable:
60 case GatewayTargetDeviceFailedToRespond:
61 return true;
62 case ErrorCodeCRCError:
63 case InvalidCRC:
64 case InvalidByteOrder:
65 case InvalidMessageID:
66 case ProtocolError:
67 case ConnectionClosed:
68 case Timeout:
69 default:
70 return false;
71 }
72}
73
75inline std::string mbErrorCodeToStr(MBErrorCode code) noexcept {
76 switch (code) {
77 case IllegalFunction:
78 return "Illegal function";
79 case IllegalDataAddress:
80 return "Illegal data address";
81 case IllegalDataValue:
82 return "Illegal data value";
83 case SlaveDeviceFailure:
84 return "Slave device failure";
85 case Acknowledge:
86 return "Acknowledge";
87 case SlaveDeviceBusy:
88 return "Slave device busy";
89 case NegativeAcknowledge:
90 return "Negative acknowledge";
91 case MemoryParityError:
92 return "Memory parity error";
93 case GatewayPathUnavailable:
94 return "Gateway path unavailable";
95 case GatewayTargetDeviceFailedToRespond:
96 return "Gateway target device failed to respond";
97 case ErrorCodeCRCError:
98 return "CRC error code error";
99 case InvalidCRC:
100 return "Invalid CRC";
101 case InvalidByteOrder:
102 return "Invalid byte order";
103 case InvalidMessageID:
104 return "Invalid messageID (TCP/IP)";
105 case ProtocolError:
106 return "Protocol error (may be timeout)";
107 case ConnectionClosed:
108 return "Connection is closed";
109 case Timeout:
110 return "Timeout";
111 default:
112 return "Undefined Error";
113 }
114}
115
117enum MBFunctionCode : uint8_t {
118 // Reading functions
119 ReadDiscreteOutputCoils = 0x01,
120 ReadDiscreteInputContacts = 0x02,
121 ReadAnalogOutputHoldingRegisters = 0x03,
122 ReadAnalogInputRegisters = 0x04,
123
124 // Single write functions
125 WriteSingleDiscreteOutputCoil = 0x05,
126 WriteSingleAnalogOutputRegister = 0x06,
127
128 // Multiple write functions
129 WriteMultipleDiscreteOutputCoils = 0x0F,
130 WriteMultipleAnalogOutputHoldingRegisters = 0x10,
131
132 // User defined
133 Undefined = 0x00
134};
135
137enum MBFunctionType { Read, WriteSingle, WriteMultiple };
138
141 switch (code) {
142 case ReadDiscreteOutputCoils:
143 case ReadAnalogInputRegisters:
144 case ReadDiscreteInputContacts:
145 case ReadAnalogOutputHoldingRegisters:
146 return Read;
147 case WriteSingleAnalogOutputRegister:
148 case WriteSingleDiscreteOutputCoil:
149 return WriteSingle;
150 case WriteMultipleAnalogOutputHoldingRegisters:
151 case WriteMultipleDiscreteOutputCoils:
152 return WriteMultiple;
153 default:
154 throw std::runtime_error("The function code is undefined");
155 }
156}
157
159enum MBFunctionRegisters { OutputCoils, InputContacts, HoldingRegisters, InputRegisters };
160
163 switch (code) {
164 case ReadDiscreteOutputCoils:
165 case WriteSingleDiscreteOutputCoil:
166 case WriteMultipleDiscreteOutputCoils:
167 return OutputCoils;
168 case ReadDiscreteInputContacts:
169 return InputContacts;
170 case ReadAnalogOutputHoldingRegisters:
171 case WriteSingleAnalogOutputRegister:
172 case WriteMultipleAnalogOutputHoldingRegisters:
173 return HoldingRegisters;
174 case ReadAnalogInputRegisters:
175 return InputRegisters;
176 default:
177 throw std::runtime_error("The function code is undefined");
178 }
179}
180
182inline std::string mbFunctionToStr(MBFunctionCode code) noexcept {
183 switch (code) {
184 case ReadDiscreteOutputCoils:
185 return "Read from output coils";
186 case ReadDiscreteInputContacts:
187 return "Read from input contacts";
188 case ReadAnalogOutputHoldingRegisters:
189 return "Read from output registers";
190 case ReadAnalogInputRegisters:
191 return "Read from input registers";
192 case WriteSingleAnalogOutputRegister:
193 return "Write to single analog register";
194 case WriteSingleDiscreteOutputCoil:
195 return "Write to single coil";
196 case WriteMultipleAnalogOutputHoldingRegisters:
197 return "Write to multiple holding registers";
198 case WriteMultipleDiscreteOutputCoils:
199 return "Write to multiple output coils";
200 default:
201 return "Undefined";
202 }
203}
204
206inline uint16_t bigEndianConv(const uint8_t *buf) {
207 return static_cast<uint16_t>(buf[1]) +
208 (static_cast<uint16_t>(buf[0]) << 8u);
209}
210
212inline uint16_t calculateCRC(const uint8_t *buff, size_t len) {
213 return MB::CRC::calculateCRC(buff, len);
214}
215
217inline uint16_t calculateCRC(const std::vector<uint8_t> &buffer) {
218 return MB::CRC::calculateCRC(buffer);
219}
220
225inline std::pair<uint8_t, uint8_t> splitUint16(const uint16_t val) {
226 return std::make_pair((val >> 8) & 0xFF, val & 0xFF);
227}
228
230inline void pushUint16(std::vector<uint8_t> &buffer, const uint16_t val) {
231 auto [high, low] = splitUint16(val);
232 buffer.push_back(high);
233 buffer.push_back(low);
234}
235
236} // namespace MB::utils
uint16_t calculateCRC(const uint8_t *buff, std::size_t len)
Calculates CRC based on the input buffer - C style.
Definition crc.cpp:3
Definition modbusUtils.hpp:21
MBFunctionType
Simplified function types.
Definition modbusUtils.hpp:137
uint16_t bigEndianConv(const uint8_t *buf)
Create uint16_t from buffer of two bytes, ex. { 0x01, 0x02 } => 0x0102.
Definition modbusUtils.hpp:206
std::pair< uint8_t, uint8_t > splitUint16(const uint16_t val)
Definition modbusUtils.hpp:225
bool isStandardErrorCode(MBErrorCode code)
Checks if error code is modbus standard error code.
Definition modbusUtils.hpp:49
void pushUint16(std::vector< uint8_t > &buffer, const uint16_t val)
Insert uint16_t into buffer of uint8_t's. Preserve big endianess.
Definition modbusUtils.hpp:230
MBFunctionRegisters
Simplified register types.
Definition modbusUtils.hpp:159
MBErrorCode
Definition modbusUtils.hpp:25
uint16_t calculateCRC(const uint8_t *buff, size_t len)
Definition modbusUtils.hpp:212
MBFunctionCode
All modbus standard function codes + Undefined one.
Definition modbusUtils.hpp:117
std::string mbFunctionToStr(MBFunctionCode code) noexcept
Converts modbus function code to its string represenatiton.
Definition modbusUtils.hpp:182
MBFunctionType functionType(const MBFunctionCode code)
Checks "Function type", according to MBFunctionType.
Definition modbusUtils.hpp:140
MBFunctionRegisters functionRegister(const MBFunctionCode code)
Get register type based on function code.
Definition modbusUtils.hpp:162
std::string mbErrorCodeToStr(MBErrorCode code) noexcept
Converts Modbus error code to it's string representation.
Definition modbusUtils.hpp:75