modbusbase.h
6.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
* Copyright (c) 2022 Peter M. Groen
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <cstring>
#include <string>
#include <stdint.h>
// Create a simple logger for console output during debugging.
// TODO: Replace with a custom logger by using std::function
// to keep it consistent with TrueMQTT.
#ifdef ENABLE_MODBUS_LOGGING
#include <cstdio>
#define LOG(fmt, ...) printf("[ modbus-cpp ]" fmt, ##__VA_ARGS__)
#else
#define LOG(...) (void)0
#endif
#define MAX_MSG_LENGTH_TCP 260
#define MAX_MSG_LENGTH_RTU 252
// Function Codes
#define READ_COILS 0x01
#define READ_INPUT_BITS 0x02
#define READ_REGS 0x03
#define READ_INPUT_REGS 0x04
#define WRITE_COIL 0x05
#define WRITE_REG 0x06
#define WRITE_COILS 0x0F
#define WRITE_REGS 0x10
// Exception codes
#define EX_ILLEGAL_FUNCTION 0x01
#define EX_ILLEGAL_ADDRESS 0x02
#define EX_ILLEGAL_VALUE 0x03
#define EX_SERVER_FAILURE 0x04
#define EX_ACKNOWLEDGE 0x05
#define EX_SERVER_BUSY 0x06
#define EX_NEGATIVE_ACK 0x07
#define EX_MEM_PARITY_PROB 0x08
#define EX_GATEWAY_PROBLEMP 0x0A
#define EX_GATEWAY_PROBLEMF 0x0B
#define EX_BAD_DATA 0xFF
#define BAD_CON -1
namespace osdev {
namespace components {
namespace modbus {
// Modbus base class. Providing all Modbus PDUs without transport implementation
class ModbusBase
{
public:
ModbusBase();
virtual ~ModbusBase();
// Pure virtuals. Override when inherited.
virtual bool Connect() = 0;
virtual void Close() = 0;
// Modbus implementation(s)
/*!
* Read Coils
* MODBUS Function 0x01
* \param address - Reference Address
* \param amount - Amount of Coils to Read
* \param buffer - Buffer to Store Data Read from Coils
*/
int readCoils(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible?
/*!
* Read Input Bits
* MODBUS Function 0x02
* \param address - Refernce Address
* \param amount - Amount of BITS to Read
* \param buffer - Buffer to store Data Read from Input Bits
*/
int readInputBits(uint16_t address, uint16_t amount, bool *buffer); // Replace buffer with something sensible?
/*!
* Read Holding Registers
* MODBUS Function 0x03
* \param address - Reference Address
* \param amount - Amount of Registers to Read
* \param buffer - Buffer to Store Data Read from Registers
*/
int readHoldingRegisters(uint16_t address, uint16_t amount, uint16_t *buffer);
/*!
* Read Input Registers
* MODBUS Function 0x04
* \param address - Reference Address
* \param amount - Amount of registers to read
* \param buffer - Buffer to store Data Read from Registers
*/
int readInputRegisters(uint16_t address, uint16_t amount, uint16_t *buffer);
/*!
* Write Single Coils
* MODBUS Function 0x05
* \param address - Reference Address
* \param to_write - Value to be written to Coil
*/
int writeCoil(uint16_t address, const bool &to_write);
/*!
* Write Single Register
* MODBUS Function 0x06
* \param address - Reference Address
* \param value - Value to Be Written to Register
*/
int writeRegister(uint16_t address, const uint16_t &value);
/*!
* Write Multiple Coils
* MODBUS Function 0x0F
* \param address - Reference Address
* \param amount - Amount of coils to write
* \param value - Values to Be Written to Coils
*/
int writeCoils(uint16_t address, uint16_t amount, const bool *value);
/*!
* Write Multiple Registers
* MODBUS Function 0x10
* \param address - Reference Address
* \param amount - Amount of Value to Write
* \param value - Values to Be Written to the Registers
*/
int writeRegisters(uint16_t address, uint16_t amount, const uint16_t *value);
// Getters and Setters.
void setConnected(bool connected = false){ m_connected = connected;}
bool getConnected() const { return m_connected; }
void setMessageId( uint32_t message_id ) { m_msg_id = message_id; }
uint32_t getMessageId() const { return m_msg_id; }
void setSlaveId(int slave_id){ m_slaveId = slave_id; }
int getSlaveId() const { return m_slaveId; }
void setError(bool error, int error_number = 0, const std::string &error_message = std::string())
{
m_error = error;
m_error_number = error_number;
m_error_message = error_message;
}
bool getError() const { return m_error; }
int getErrorNumber() const { return m_error_number; }
std::string getErrorMessage() const { return m_error_message;}
private: // Methods
/*!
* Modbus Request Builder
* \param to_send - Message buffer to be send
* \param address - Reference Address
* \param function_code - Modbus Functional Code
*/
void buildRequest(uint8_t *to_send, uint16_t address, int function_code) const;
int modbusRead(uint16_t address, uint16_t amount, int function_code);
/*!
* Write Request Builder and Sender
* \param address - Reference address
* \param amount - Amount of data to be written
* \param function_code - Modbus Functional Code
* \param value - Data to be written
*
* \return int -
*/
int modbusWrite(uint16_t address, uint16_t amount, int function_code, const uint16_t *value);
/*!
* \brief modbusSend
* \param to_send
* \param length
* \return
*/
virtual ssize_t modbusSend(uint8_t *to_send, size_t length) = 0;
/*!
* \brief modbusReceive
* \param buffer
* \return
*/
virtual ssize_t modbusReceive(uint8_t *buffer) const = 0;
/*!
* \brief modbusErrorHandle
* \param msg
* \param function_code
*/
void modbusErrorHandle(const uint8_t *msg, int function_code);
/*!
* \brief setBadConnection
*/
void setBadConnection();
/*!
* \brief setBadInput
*/
void setBadInput();
private: // Members (Giggity!)
bool m_connected{};
uint32_t m_msg_id{};
int m_slaveId{};
bool m_error{};
int m_error_number{};
std::string m_error_message;
};
} // End namespace modbus
} // End namespace components
} // End namespace osdev