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