Line data Source code
1 :
2 :
3 : #include "modbus.hpp"
4 :
5 :
6 0 : modbus::modbus( const std::string & host,
7 : uint16_t port
8 0 : ) : PORT {port}, HOST{host} {}
9 :
10 0 : modbus::modbus(const std::string & host) : HOST{host} {}
11 :
12 0 : modbus::~modbus(void) {
13 0 : }
14 :
15 0 : void modbus::modbus_set_slave_id(int id) {
16 0 : _slaveid = id;
17 0 : }
18 :
19 0 : bool modbus::modbus_connect() {
20 0 : if(HOST == "" || PORT == 0) {
21 : //std::cout << "Missing Host and Port" << std::endl;
22 0 : return false;
23 : } else {
24 : //std::cout << "Found Proper Host "<< HOST << " and Port " <<PORT <<std::endl;
25 : }
26 :
27 0 : _socket = socket(AF_INET, SOCK_STREAM, 0);
28 0 : if(_socket == -1) {
29 : //std::cout <<"Error Opening Socket" <<std::endl;
30 0 : return false;
31 : } else {
32 : //std::cout <<"Socket Opened Successfully" << std::endl;
33 : }
34 :
35 0 : _server.sin_family = AF_INET;
36 0 : _server.sin_addr.s_addr = inet_addr(HOST.c_str());
37 0 : _server.sin_port = htons(PORT);
38 :
39 0 : if (connect(_socket, (struct sockaddr*)&_server, sizeof(_server)) < 0) {
40 : //std::cout<< "Connection Error" << std::endl;
41 0 : return false;
42 : }
43 :
44 : //std::cout<< "Connected" <<std::endl;
45 0 : _connected = true;
46 0 : return true;
47 : }
48 :
49 0 : void modbus::modbus_close() {
50 0 : close(_socket);
51 : //std::cout <<"Socket Closed" <<std::endl;
52 0 : }
53 :
54 0 : void modbus::modbus_build_request(uint8_t *to_send, int address, int func) {
55 0 : to_send[0] = (uint8_t) _msg_id >> 8;
56 0 : to_send[1] = (uint8_t) (_msg_id & 0x00FF);
57 0 : to_send[2] = 0;
58 0 : to_send[3] = 0;
59 0 : to_send[4] = 0;
60 0 : to_send[6] = (uint8_t) _slaveid;
61 0 : to_send[7] = (uint8_t) func;
62 0 : to_send[8] = (uint8_t) (address >> 8);
63 0 : to_send[9] = (uint8_t) (address & 0x00FF);
64 0 : }
65 :
66 0 : void modbus::modbus_write(int address, int amount, int func, uint16_t *value) {
67 0 : if(func == WRITE_COIL || func == WRITE_REG) {
68 : uint8_t to_send[12];
69 0 : modbus_build_request(to_send, address, func);
70 0 : to_send[5] = 6;
71 0 : to_send[10] = (uint8_t) (value[0] >> 8);
72 0 : to_send[11] = (uint8_t) (value[0] & 0x00FF);
73 0 : modbus_send(to_send, 12);
74 0 : } else if(func == WRITE_REGS){
75 0 : uint8_t to_send[13 + 2 * amount];
76 0 : modbus_build_request(to_send, address, func);
77 0 : to_send[5] = (uint8_t) (5 + 2 * amount);
78 0 : to_send[10] = (uint8_t) (amount >> 8);
79 0 : to_send[11] = (uint8_t) (amount & 0x00FF);
80 0 : to_send[12] = (uint8_t) (2 * amount);
81 0 : for(int i = 0; i < amount; i++) {
82 0 : to_send[13 + 2 * i] = (uint8_t) (value[i] >> 8);
83 0 : to_send[14 + 2 * i] = (uint8_t) (value[i] & 0x00FF);
84 : }
85 0 : modbus_send(to_send, 13 + 2 * amount);
86 0 : } else if(func == WRITE_COILS) {
87 0 : uint8_t to_send[14 + (amount -1) / 8 ];
88 0 : modbus_build_request(to_send, address, func);
89 0 : to_send[5] = (uint8_t) (7 + (amount -1) / 8);
90 0 : to_send[10] = (uint8_t) (amount >> 8);
91 0 : to_send[11] = (uint8_t) (amount >> 8);
92 0 : to_send[12] = (uint8_t) ((amount + 7) / 8);
93 0 : for(int i = 0; i < amount; i++) {
94 0 : to_send[13 + (i - 1) / 8] += (uint8_t) (value[i] << (i % 8));
95 : }
96 0 : modbus_send(to_send, 14 + (amount - 1) / 8);
97 0 : }
98 0 : }
99 :
100 0 : void modbus::modbus_read(int address, int amount, int func){
101 : uint8_t to_send[12];
102 0 : modbus_build_request(to_send, address, func);
103 0 : to_send[5] = 6;
104 0 : to_send[10] = (uint8_t) (amount >> 8);
105 0 : to_send[11] = (uint8_t) (amount & 0x00FF);
106 0 : modbus_send(to_send, 12);
107 0 : }
108 :
109 0 : void modbus::modbus_read_holding_registers(int address, int amount, uint16_t *buffer) {
110 0 : if(_connected) {
111 0 : if(amount > 65535 || address > 65535) {
112 0 : throw modbus_amount_exception();
113 : }
114 0 : modbus_read(address, amount, READ_REGS);
115 : uint8_t to_rec[MAX_MSG_LENGTH];
116 0 : modbus_receive(to_rec);
117 : try {
118 0 : modbus_error_handle(to_rec, READ_REGS);
119 0 : for(int i = 0; i < amount; i++) {
120 0 : buffer[i] = ((uint16_t)to_rec[9 + 2 * i]) << 8;
121 0 : buffer[i] += (uint16_t) to_rec[10 + 2 * i];
122 : }
123 0 : } catch (std::exception &e) {
124 0 : throw; //e;
125 0 : }
126 : } else {
127 0 : throw modbus_connect_exception();
128 : }
129 0 : }
130 :
131 0 : void modbus::modbus_read_input_registers(int address, int amount, uint16_t *buffer) {
132 0 : if(_connected){
133 0 : if(amount > 65535 || address > 65535) {
134 0 : throw modbus_amount_exception();
135 : }
136 0 : modbus_read(address, amount, READ_INPUT_REGS);
137 : uint8_t to_rec[MAX_MSG_LENGTH];
138 0 : modbus_receive(to_rec);
139 : try {
140 0 : modbus_error_handle(to_rec, READ_INPUT_REGS);
141 0 : for(int i = 0; i < amount; i++) {
142 0 : buffer[i] = ((uint16_t)to_rec[9 + 2 * i]) << 8;
143 0 : buffer[i] += (uint16_t) to_rec[10 + 2 * i];
144 : }
145 0 : } catch (std::exception &e) {
146 0 : throw; //e;
147 0 : }
148 : } else {
149 0 : throw modbus_connect_exception();
150 : }
151 0 : }
152 :
153 0 : void modbus::modbus_read_coils(int address, int amount, bool *buffer) {
154 0 : if(_connected) {
155 0 : if(amount > 2040 || address > 65535) {
156 0 : throw modbus_amount_exception();
157 : }
158 0 : modbus_read(address, amount, READ_COILS);
159 : uint8_t to_rec[MAX_MSG_LENGTH];
160 0 : modbus_receive(to_rec);
161 : try {
162 0 : modbus_error_handle(to_rec, READ_COILS);
163 0 : for(int i = 0; i < amount; i++) {
164 0 : buffer[i] = (bool) ((to_rec[9 + i / 8] >> (i % 8)) & 1);
165 : }
166 0 : } catch (std::exception &e) {
167 0 : throw; //e;
168 0 : }
169 : } else {
170 0 : throw modbus_connect_exception();
171 : }
172 0 : }
173 :
174 0 : void modbus::modbus_read_input_bits(int address, int amount, bool* buffer) {
175 0 : if(_connected) {
176 0 : if(amount > 2040 || address > 65535) {
177 0 : throw modbus_amount_exception();
178 : }
179 0 : modbus_read(address, amount, READ_INPUT_BITS);
180 : uint8_t to_rec[MAX_MSG_LENGTH];
181 0 : modbus_receive(to_rec);
182 : try {
183 0 : modbus_error_handle(to_rec, READ_INPUT_BITS);
184 0 : for(int i = 0; i < amount; i++) {
185 0 : buffer[i] = (bool) ((to_rec[9 + i / 8] >> (i % 8)) & 1);
186 : }
187 0 : } catch (std::exception &e) {
188 0 : throw; //e;
189 0 : }
190 : } else {
191 0 : throw modbus_connect_exception();
192 : }
193 0 : }
194 :
195 0 : void modbus::modbus_write_coil(int address, bool to_write) {
196 0 : if(_connected) {
197 0 : if(address > 65535) {
198 0 : throw modbus_amount_exception();
199 : }
200 0 : int value = to_write * 0xFF00;
201 0 : modbus_write(address, 1, WRITE_COIL, (uint16_t *)&value);
202 : uint8_t to_rec[MAX_MSG_LENGTH];
203 0 : modbus_receive(to_rec);
204 : try{
205 0 : modbus_error_handle(to_rec, WRITE_COIL);
206 0 : } catch (std::exception &e) {
207 0 : throw; //e;
208 0 : }
209 : } else {
210 0 : throw modbus_connect_exception();
211 : }
212 0 : }
213 :
214 0 : void modbus::modbus_write_register(int address, uint16_t value) {
215 0 : if(_connected) {
216 0 : if(address > 65535) {
217 0 : throw modbus_amount_exception();
218 : }
219 0 : modbus_write(address, 1, WRITE_REG, &value);
220 : uint8_t to_rec[MAX_MSG_LENGTH];
221 0 : modbus_receive(to_rec);
222 : try{
223 0 : modbus_error_handle(to_rec, WRITE_COIL);
224 0 : } catch (std::exception &e) {
225 0 : throw; //e;
226 0 : }
227 : } else {
228 0 : throw modbus_connect_exception();
229 : }
230 0 : }
231 :
232 0 : void modbus::modbus_write_coils(int address, int amount, bool *value) {
233 0 : if(_connected) {
234 0 : if(address > 65535 || amount > 65535) {
235 0 : throw modbus_amount_exception();
236 : }
237 0 : uint16_t temp[amount];
238 0 : for(int i = 0; i < 4; i++) {
239 0 : temp[i] = (uint16_t)value[i];
240 : }
241 0 : modbus_write(address, amount, WRITE_COILS, temp);
242 : uint8_t to_rec[MAX_MSG_LENGTH];
243 0 : modbus_receive(to_rec);
244 : try{
245 0 : modbus_error_handle(to_rec, WRITE_COILS);
246 0 : } catch (std::exception &e) {
247 0 : throw; //e;
248 0 : }
249 0 : } else {
250 0 : throw modbus_connect_exception();
251 : }
252 0 : }
253 :
254 0 : void modbus::modbus_write_registers(int address, int amount, uint16_t *value) {
255 0 : if(_connected) {
256 0 : if(address > 65535 || amount > 65535) {
257 0 : throw modbus_amount_exception();
258 : }
259 0 : modbus_write(address, amount, WRITE_REGS, value);
260 : uint8_t to_rec[MAX_MSG_LENGTH];
261 0 : modbus_receive(to_rec);
262 : try{
263 0 : modbus_error_handle(to_rec, WRITE_REGS);
264 0 : } catch (std::exception &e) {
265 0 : throw; //e;
266 0 : }
267 : } else {
268 0 : throw modbus_connect_exception();
269 : }
270 0 : }
271 :
272 0 : ssize_t modbus::modbus_send(uint8_t *to_send, int length) {
273 0 : _msg_id++;
274 0 : return send(_socket, to_send, (size_t)length, 0);
275 : }
276 :
277 0 : ssize_t modbus::modbus_receive(uint8_t *buffer) {
278 0 : return recv(_socket, (char *) buffer, MAX_MSG_LENGTH, 0);
279 : }
280 :
281 0 : void modbus::modbus_error_handle(uint8_t *msg, int func) {
282 0 : if(msg[7] == func + 0x80) {
283 0 : switch(msg[8]){
284 0 : case EX_ILLEGAL_FUNCTION:
285 0 : throw modbus_illegal_function_exception();
286 0 : case EX_ILLEGAL_ADDRESS:
287 0 : throw modbus_illegal_address_exception();
288 0 : case EX_ILLEGAL_VALUE:
289 0 : throw modbus_illegal_data_value_exception();
290 0 : case EX_SERVER_FAILURE:
291 0 : throw modbus_server_failure_exception();
292 0 : case EX_ACKNOWLEDGE:
293 0 : throw modbus_acknowledge_exception();
294 0 : case EX_SERVER_BUSY:
295 0 : throw modbus_server_busy_exception();
296 0 : case EX_GATEWAY_PROBLEMP:
297 : case EX_GATEWYA_PROBLEMF:
298 0 : throw modbus_gateway_exception();
299 0 : default:
300 0 : break;
301 : }
302 : }
303 0 : }
|