modbusbase.h
4.78 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
/*
* 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
// 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 260
// 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
// Modbus base class. Providing all Modbus PDUs without transport implementation
class ModbusBase
{
public:
bool err{};
int err_no{};
std::string m_error_msg;
ModbusBase();
virtual ~ModbusBase();
/*!
* Set slave id for this context
* \param slave_id - The slave id this system is known under.
*/
void setSlaveId(int slave_id) { m_slaveId = slave_id; }
// Pure virtuals. Override when inherited.
virtual bool Connect() const = 0;
virtual void Close() = 0;
virtual bool isConnected() const - 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, uitn16_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);
int writeRegister(uint16_t address, const uint16_t &value);
int writeCoils(uint16_t address, uint16_t amount, const bool *value);
int writeRegisters(uint16_t address, uint16_t amount, const uint16_t *value);
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);
virtual ssize_t modbusSend(uint8_t *to_send, size_t length) = 0;
virtual ssize_t modbusReceive(uint8_t *buffer) const = 0;
void modbusErrorHandle(const uint8_t *msg, int function_code);
void setBadConnection();
void setBadInput();
private: // Members (Giggity!)
bool m_connected{};
uint32_t m_msg_id{};
int m_slaveId{};
};