rllib  1
rlmodbus.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rlmodbus.cpp - description
3  -------------------
4  begin : Tue Mar 13 2003
5  copyright : (C) 2003 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 #include "rlmodbus.h"
17 #include <stdio.h>
18 #include <string.h>
19 
20 rlModbus::rlModbus(long max_telegram_length, int _mode, char end_delimitor)
21 {
22  if(max_telegram_length < 256) max_telegram_length = 256;
23  tel = new unsigned char[max_telegram_length];
24  maxtel = max_telegram_length;
25  mode = _mode;
26  delimitor = end_delimitor;
27  s = NULL;
28  tty = NULL;
30 }
31 
33 {
34  if(tel != NULL) delete [] tel;
35 }
36 
37 int rlModbus::data2int(const unsigned char *data)
38 {
39  return (data[0]*256)+data[1];
40 }
41 
42 int rlModbus::int2data(int val, unsigned char *data)
43 {
44  data[0] = (unsigned char) val / 256;
45  data[1] = (unsigned char) val & 0x0ff;
46  return 0;
47 }
48 
50 {
51  return 2;
52 }
53 
54 int rlModbus::write(int slave, int function, const unsigned char *data, int datalen, int *transactionID)
55 {
56  int len,i;
57 
58  if(slave < 0 || slave > 255) return MODBUS_ERROR;
59  len = 0;
60  if(mode == MODBUS_ASCII)
61  {
62  tel[len++] = ':';
63  sprintf((char *) &tel[len], "%02X", slave); len += 2;
64  sprintf((char *) &tel[len], "%02X", function); len += 2;
65  for(i=0; i<datalen; i++)
66  {
67  sprintf((char *) &tel[len], "%02X",(int) data[i]); len += 2;
68  if((len+4) > maxtel) return MODBUS_ERROR;
69  }
70  insertLRC(len); len += 2;
71  tel[len++] = 0x0d;
72  if(delimitor == 0x0a) tel[len++] = 0x0a;
73  }
74  else if(mode == MODBUS_RTU)
75  {
76  if(s != NULL)
77  {
78  if(transactionID == NULL)
79  {
80  tel[len++] = 0; // bytes 0,1 Transaction ID. Not important. Usually zero when making a request, the server will copy them faithfully into the response.
81  tel[len++] = 0;
82  }
83  else
84  {
85  tel[len++] = ((*transactionID) & 0xFF00) / 256; // bytes 0,1 Transaction ID.
86  tel[len++] = (*transactionID) & 0xFF;
87  }
88  tel[len++] = 0; // bytes 2,3 Protocol number. Must be zero.
89  tel[len++] = 0;
90  tel[len++] = 0; // byte 4 Length (upper byte). Since all requests will be less than 256 bytes in length (!), this will always be zero.
91  tel[len++] = 2+datalen; // byte 5 Length (lower byte). Equal to the number of bytes which follow
92  }
93  tel[len++] = (unsigned char) slave;
94  tel[len++] = (unsigned char) function;
95  for(i=0; i<datalen; i++)
96  {
97  tel[len++] = data[i];
98  if((len+2) > maxtel) return MODBUS_ERROR;
99  }
100  insertCRC(len); len += 2;
101  }
102  else return MODBUS_ERROR;
103 
104  if(s != NULL)
105  {
106  if(s->isConnected() == 0)
107  {
109  if(s->isConnected() == 0) return MODBUS_ERROR;
110  }
111  if(s->write(tel,len-2) < 0) return MODBUS_ERROR; // don't send LRC or CRC
112  }
113  else if(tty != NULL)
114  {
115  if(tty->writeBlock(tel,len) < 0) return MODBUS_ERROR;
116  }
117  else return MODBUS_ERROR;
118  return MODBUS_SUCCESS;
119 }
120 
121 int rlModbus::request(int slave, int function, int start_adr, int num_register)
122 {
123  unsigned char data[4];
124 
125  data[0] = (unsigned char) ( start_adr / 256 );
126  data[1] = (unsigned char) ( start_adr & 0x0ff );
127  data[2] = (unsigned char) ( num_register / 256 );
128  data[3] = (unsigned char) ( num_register & 0x0ff );
129  return write(slave, function, data, 4);
130 }
131 
132 int rlModbus::response(int *slave, int *function, unsigned char *data, int timeout)
133 {
134  unsigned char *telptr;
135  int ret,len,byte_count,idata,i,itel,val;
136 
137  len = 0;
138  if(mode != MODBUS_ASCII && mode != MODBUS_RTU) return MODBUS_ERROR;
139  if(s != NULL)
140  {
141  if(s->isConnected() == 0) return MODBUS_ERROR;
142  if(mode == MODBUS_RTU)
143  {
144  if(s->read((char *) tel, 6, timeout) <= 0) return MODBUS_ERROR;
145  // bytes 0,1 Transaction ID faithfully copied from the request message
146  // bytes 2,3 Protocol number always zero
147  // byte 4 Response length (upper byte) Always zero
148  // byte 5 Response length (lower byte). Equal to the number of bytes which follow
149  // Here comes the normal Modus telegram
150  if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
151  *slave = tel[0];
152  *function = tel[1];
153  switch(*function)
154  {
155  case ReadCoilStatus:
156  case ReadInputStatus:
158  case ReadInputRegisters:
159  case FetchCommEventLog:
160  case ReportSlaveID:
164  if(s->read((char *) tel, 1, timeout) <= 0) return MODBUS_ERROR;
165  byte_count = tel[0];
166  if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
167  return byte_count;
168  case ForceSingleCoil:
170  case FetchCommEventCtr:
171  case ForceMultipleCoils:
172  case PresetMultipleRegs:
173  byte_count = 4;
174  if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
175  return byte_count;
176  case ReadExceptionStatus:
177  byte_count = 1;
178  if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
179  return byte_count;
181  byte_count = 6;
182  if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
183  return byte_count;
184  case ReadFifoQueue:
185  if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
186  byte_count = tel[0]*256 + tel[1];
187  if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
188  return byte_count;
189  default:
190  return MODBUS_ERROR;
191  }
192  }
193  }
194  else if(tty != NULL)
195  {
196  if(mode == MODBUS_ASCII)
197  {
198  //printf("modbus ascii\n");
199  for(i=0; i<maxtel; i++)
200  {
201  ret = tty->select(timeout);
202  if(ret == 0) return MODBUS_ERROR;
203  //printf("readChar\n");
204  itel = tty->readChar();
205  if(itel < 0) return MODBUS_ERROR;
206  tel[i] = (unsigned char) itel;
207  if(tel[i] == 0x0d && delimitor != 0x0a) break;
208  if(tel[i] == 0x0a) break;
209  }
210  tel[i] = '\0';
211  telptr = (unsigned char *) strchr((const char *) tel,':');
212  if(telptr == NULL) return MODBUS_ERROR;
213  len++;
214  sscanf((char *) &telptr[len],"%02X",slave); len += 2;
215  sscanf((char *) &telptr[len],"%02X",function); len += 2;
216  switch(*function)
217  {
218  case ReadCoilStatus:
219  case ReadInputStatus:
221  case ReadInputRegisters:
222  case FetchCommEventLog:
223  case ReportSlaveID:
227  sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
228  for(idata=0; idata<byte_count; idata++)
229  {
230  sscanf((const char *) &telptr[len], "%02X", &val); len += 2;
231  data[idata] = val;
232  }
233  data[idata] = 0x0ff; // terminator, this data can't come over modbus
234  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
235  return byte_count;
236  case ForceSingleCoil:
238  case FetchCommEventCtr:
239  case ForceMultipleCoils:
240  case PresetMultipleRegs:
241  byte_count = 8;
242  for(idata=0; idata<(byte_count/2); idata++)
243  {
244  data[idata] = buf2int_ascii(&telptr[len]); len += 2;
245  }
246  data[idata] = 0x0ff; // terminator, this data can't come over modbus
247  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
248  return byte_count;
249  case ReadExceptionStatus:
250  byte_count = 2;
251  for(idata=0; idata<(byte_count/2); idata++)
252  {
253  data[idata] = buf2int_ascii(&telptr[len]); len += 2;
254  }
255  data[idata] = 0x0ff; // terminator, this data can't come over modbus
256  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
257  return byte_count;
259  byte_count = 12;
260  for(idata=0; idata<(byte_count/2); idata++)
261  {
262  data[idata] = buf2int_ascii(&telptr[len]); len += 2;
263  }
264  data[idata] = 0x0ff; // terminator, this data can't come over modbus
265  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
266  return byte_count;
267  case ReadFifoQueue:
268  sscanf((char *) &telptr[len],"%04X",&byte_count); len += 4;
269  for(idata=0; idata<(byte_count/2); idata++)
270  {
271  data[idata] = buf2int_ascii(&telptr[len]); len += 2;
272  }
273  data[idata] = 0x0ff; // terminator, this data can't come over modbus
274  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
275  return byte_count;
276  break;
277  default:
278  return MODBUS_ERROR;
279  }
280  }
281  else if(mode == MODBUS_RTU)
282  {
283  ret = tty->select(timeout);
284  if(ret == 0) return MODBUS_ERROR;
285  if(tty->readBlock(tel, 2, timeout) <= 0) return MODBUS_ERROR;
286  *slave = tel[len++];
287  *function = tel[len++];
288  switch(*function)
289  {
290  case ReadCoilStatus:
291  case ReadInputStatus:
293  case ReadInputRegisters:
294  case FetchCommEventLog:
295  case ReportSlaveID:
299  if(tty->select(timeout) == 0) return MODBUS_ERROR;
300  if(tty->readBlock(&tel[len], 1, timeout) <= 0) return MODBUS_ERROR;
301  byte_count = tel[len++];
302  if(tty->select(timeout) == 0) return MODBUS_ERROR;
303  if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
304  memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
305  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
306  return byte_count;
307  case ForceSingleCoil:
309  case FetchCommEventCtr:
310  case ForceMultipleCoils:
311  case PresetMultipleRegs:
312  byte_count = 4;
313  if(tty->select(timeout) == 0) return MODBUS_ERROR;
314  if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
315  memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
316  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
317  return byte_count;
318  case ReadExceptionStatus:
319  byte_count = 1;
320  if(tty->select(timeout) == 0) return MODBUS_ERROR;
321  if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
322  memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
323  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
324  return byte_count;
326  byte_count = 6;
327  if(tty->select(timeout) == 0) return MODBUS_ERROR;
328  if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
329  memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
330  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
331  return byte_count;
332  case ReadFifoQueue:
333  if(tty->select(timeout) == 0) return MODBUS_ERROR;
334  if(tty->readBlock(&tel[len], 2, timeout) <= 0) return MODBUS_ERROR;
335  byte_count = tel[len]*256 + tel[len+1]; len += 2;
336  if(tty->select(timeout) == 0) return MODBUS_ERROR;
337  if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
338  memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
339  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
340  return byte_count;
341  default:
342  return MODBUS_ERROR;
343  }
344  }
345  }
346  else return MODBUS_ERROR;
347  return MODBUS_SUCCESS;
348 }
349 
350 int rlModbus::readRequest(int *slave, int *function, unsigned char *data, int timeout, int *transactionID)
351 {
352  unsigned char *telptr;
353  int ret,len,byte_count,i,itel,val;
354 
355  len = 0;
356  if(mode != MODBUS_ASCII && mode != MODBUS_RTU) return MODBUS_ERROR;
357  if(s != NULL)
358  {
359  if(s->isConnected() == 0) return MODBUS_ERROR;
360  if(mode == MODBUS_RTU)
361  {
362  if(s->read((char *) tel, 6, timeout) <= 0) return MODBUS_ERROR;
363  if(transactionID != NULL) *transactionID = tel[0] * 256 + tel[1]; // return transactionID
364  // bytes 0,1 Transaction ID faithfully copied from the request message
365  // bytes 2,3 Protocol number always zero
366  // byte 4 Response length (upper byte) Always zero
367  // byte 5 Response length (lower byte). Equal to the number of bytes which follow
368  // Here comes the normal Modus telegram
369  if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
370  *slave = tel[0];
371  *function = tel[1];
372  switch(*function)
373  {
374  case ReadCoilStatus:
375  case ReadInputStatus:
377  case ReadInputRegisters:
378  case ForceSingleCoil:
380  if(s->read((char *) data, 4, timeout) <= 0) return MODBUS_ERROR;
381  return 4;
382  case ReadExceptionStatus:
383  case FetchCommEventCtr:
384  case FetchCommEventLog:
385  case ReportSlaveID:
386  return 0;
387  case ForceMultipleCoils:
388  case PresetMultipleRegs:
389  if(s->read((char *) data, 5, timeout) <= 0) return MODBUS_ERROR;
390  byte_count = data[4];
391  if(s->read((char *) &data[4], byte_count, timeout) <= 0) return MODBUS_ERROR;
392  return 4+byte_count;
395  if(s->read((char *) data, 1, timeout) <= 0) return MODBUS_ERROR;
396  byte_count = data[0];
397  if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
398  return byte_count;
400  if(s->read((char *) data, 6, timeout) <= 0) return MODBUS_ERROR;
401  return 6;
403  if(s->read((char *) data, 9, timeout) <= 0) return MODBUS_ERROR;
404  byte_count = data[8];
405  if(s->read((char *) &data[8], byte_count, timeout) <= 0) return MODBUS_ERROR;
406  return 8+byte_count;
407  case ReadFifoQueue:
408  if(s->read((char *) data, 2, timeout) <= 0) return MODBUS_ERROR;
409  return 2;
410  default:
411  return MODBUS_ERROR;
412  }
413  }
414  }
415  else if(tty != NULL)
416  {
417  if(mode == MODBUS_ASCII)
418  {
419  //printf("modbus ascii\n");
420  for(i=0; i<maxtel; i++)
421  {
422  ret = tty->select(timeout);
423  if(ret == 0) return MODBUS_ERROR;
424  //printf("readChar\n");
425  itel = tty->readChar();
426  if(itel < 0) return MODBUS_ERROR;
427  tel[i] = (unsigned char) itel;
428  if(tel[i] == 0x0d && delimitor != 0x0a) break;
429  if(tel[i] == 0x0a) break;
430  }
431  tel[i] = '\0';
432  telptr = (unsigned char *) strchr((const char *) tel,':');
433  if(telptr == NULL) return MODBUS_ERROR;
434  len++;
435  sscanf((char *) &telptr[len],"%02X",slave); len += 2;
436  sscanf((char *) &telptr[len],"%02X",function); len += 2;
437  switch(*function)
438  {
439  case ReadCoilStatus:
440  case ReadInputStatus:
442  case ReadInputRegisters:
443  case ForceSingleCoil:
445  sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
446  sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
447  sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
448  sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
449  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
450  return 4;
451  case ReadExceptionStatus:
452  case FetchCommEventCtr:
453  case FetchCommEventLog:
454  case ReportSlaveID:
455  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
456  return 0;
457  case ForceMultipleCoils:
458  case PresetMultipleRegs:
459  sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
460  sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
461  sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
462  sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
463  sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
464  for(i=0; i<byte_count; i++)
465  {
466  sscanf((char *) &telptr[len],"%02X",&val); data[4+i] = (unsigned char) val; len += 2;
467  }
468  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
469  return 4+byte_count;
472  sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
473  for(i=0; i<byte_count; i++)
474  {
475  sscanf((char *) &telptr[len],"%02X",&val); data[i] = (unsigned char) val; len += 2;
476  }
477  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
478  return byte_count;
480  sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
481  sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
482  sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
483  sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
484  sscanf((char *) &telptr[len],"%02X",&val); data[4] = (unsigned char) val; len += 2;
485  sscanf((char *) &telptr[len],"%02X",&val); data[5] = (unsigned char) val; len += 2;
486  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
487  return 6;
489  sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
490  sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
491  sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
492  sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
493  sscanf((char *) &telptr[len],"%02X",&val); data[4] = (unsigned char) val; len += 2;
494  sscanf((char *) &telptr[len],"%02X",&val); data[5] = (unsigned char) val; len += 2;
495  sscanf((char *) &telptr[len],"%02X",&val); data[6] = (unsigned char) val; len += 2;
496  sscanf((char *) &telptr[len],"%02X",&val); data[7] = (unsigned char) val; len += 2;
497  sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
498  for(i=0; i<byte_count; i++)
499  {
500  sscanf((char *) &telptr[len],"%02X",&val); data[8+i] = (unsigned char) val; len += 2;
501  }
502  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
503  return 8+byte_count;
504  case ReadFifoQueue:
505  sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
506  sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
507  if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
508  return 2;
509  default:
510  return MODBUS_ERROR;
511  }
512  }
513  else if(mode == MODBUS_RTU)
514  {
515  ret = tty->select(timeout);
516  if(ret == 0) return MODBUS_ERROR;
517  if(tty->readBlock(tel, 2, timeout) <= 0) return MODBUS_ERROR;
518  *slave = tel[len++];
519  *function = tel[len++];
520  ret = tty->select(timeout);
521  if(ret == 0) return MODBUS_ERROR;
522  switch(*function)
523  {
524  case ReadCoilStatus:
525  case ReadInputStatus:
527  case ReadInputRegisters:
528  case ForceSingleCoil:
530  if(tty->readBlock(data, 4+2, timeout) <= 0) return MODBUS_ERROR;
531  memcpy(&tel[len],data,4+2); len += 4+2;
532  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
533  return 4;
534  case ReadExceptionStatus:
535  case FetchCommEventCtr:
536  case FetchCommEventLog:
537  case ReportSlaveID:
538  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
539  return 0;
540  case ForceMultipleCoils:
541  case PresetMultipleRegs:
542  if(tty->readBlock(data, 5, timeout) <= 0) return MODBUS_ERROR;
543  memcpy(&tel[len],data,5); len += 5;
544  byte_count = data[4];
545  if(tty->readBlock(&data[4], byte_count+2, timeout) <= 0) return MODBUS_ERROR;
546  memcpy(&tel[len],&data[4],byte_count+2); len += byte_count+2;
547  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
548  return 4+byte_count;
551  if(tty->readBlock(data, 1, timeout) <= 0) return MODBUS_ERROR;
552  memcpy(&tel[len],data,1); len++;
553  byte_count = data[0];
554  if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
555  memcpy(&tel[len],data,byte_count+2); len += byte_count+2;
556  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
557  return byte_count;
559  if(tty->readBlock(data, 6+2, timeout) <= 0) return MODBUS_ERROR;
560  memcpy(&tel[len],data,6+2); len += 6+2;
561  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
562  return 6;
564  if(tty->readBlock(data, 9, timeout) <= 0) return MODBUS_ERROR;
565  memcpy(&tel[len],data,9); len += 9;
566  byte_count = data[8];
567  if(tty->readBlock(&data[8], byte_count+2, timeout) <= 0) return MODBUS_ERROR;
568  memcpy(&tel[len],&data[8],byte_count+2); len += byte_count+2;
569  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
570  return 8+byte_count;
571  case ReadFifoQueue:
572  if(tty->readBlock(data, 2+2, timeout) <= 0) return MODBUS_ERROR;
573  memcpy(&tel[len],data,2+2); len += 2+2;
574  if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
575  return 2;
576  default:
577  return MODBUS_ERROR;
578  }
579  }
580  }
581  else return MODBUS_ERROR;
582  return MODBUS_SUCCESS;
583 }
584 
586 {
587  tty = NULL;
588  s = socket;
589 }
590 
592 {
593  s = NULL;
594  tty = serial;
595 }
596 
597 int rlModbus::buf2int_rtu(unsigned char *buf)
598 {
599  return (buf[0]*256 + buf[1]);
600 }
601 
602 void rlModbus::int2buf_rtu(int i, unsigned char *buf)
603 {
604  int high, low;
605 
606  high = i / 256;
607  low = i & 0x0ff;
608  buf[0] = (unsigned char) high;
609  buf[1] = (unsigned char) low;
610 }
611 
612 int rlModbus::buf2int_ascii(unsigned char *buf)
613 {
614  int val;
615 
616  sscanf((char *) buf,"%04X",&val);
617  return val;
618 }
619 
620 void rlModbus::int2buf_ascii(int i, unsigned char *buf)
621 {
622  sprintf((char *) buf,"%04X",i);
623 }
624 
625 void rlModbus::insertLRC(int len)
626 {
627  unsigned char lrc;
628  int i,high,low,val;
629 
630  if(len < 0) return;
631  lrc = 0;
632  for(i=1; i<len; i+=2) // exclude starting ':' and trailing <CR><LF>
633  {
634  sscanf((const char *) &tel[i], "%1X", &high);
635  sscanf((const char *) &tel[i+1], "%1X", &low);
636  val = high*16 + low;
637  lrc += val;
638  }
639  lrc = ((unsigned char)(-((char) lrc)));
640  sprintf((char *) &tel[len],"%02X",(unsigned int) lrc);
641 }
642 
643 int rlModbus::LRCerror(int len)
644 {
645  unsigned char *cptr;
646  unsigned char lrc;
647  int i,high,low,val;
648 
649  if(len < 0) return 1;
650  tel[maxtel-1] = '\0';
651  cptr = (unsigned char *) strchr((char *)tel,':');
652  if(cptr == NULL) return 1;
653  cptr++;
654  lrc = 0;
655  for(i=1; i<len+2; i+=2) // exclude starting ':' and trailing <CR><LF>
656  { // len is without lrc -> len+2
657  sscanf((const char *) cptr++, "%1X", &high);
658  sscanf((const char *) cptr++, "%1X", &low);
659  val = high*16 + low;
660  lrc += val;
661  }
662  if(lrc == 0) return 0; // lrc ok
663  return 1; // lrc error
664 }
665 
666 /* Table of CRC values for high-order byte */
667 static const unsigned char array_crc_low[] =
668 {
669 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
670 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
671 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
672 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
673 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
674 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
675 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
676 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
677 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
678 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
679 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
680 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
681 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
682 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
683 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
684 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
685 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
686 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
687 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
688 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
689 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
690 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
691 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
692 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
693 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
694 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
695 };
696 
697 /* Table of CRC values for low-order byte */
698 static const unsigned char array_crc_high[] =
699 {
700 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
701 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
702 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
703 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
704 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
705 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
706 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
707 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
708 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
709 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
710 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
711 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
712 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
713 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
714 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
715 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
716 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
717 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
718 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
719 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
720 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
721 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
722 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
723 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
724 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
725 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
726 };
727 
728 void rlModbus::insertCRC(int len)
729 {
730  unsigned char crc_high, crc_low;
731  unsigned index;
732  int i;
733 
734  if(len < 0) return;
735  crc_high = crc_low = 0xff;
736  for(i=0; i<len; i++)
737  {
738  index = crc_low ^ tel[i];
739  crc_low = crc_high ^ array_crc_low[index];
740  crc_high = array_crc_high[index];
741  }
742  tel[len] = crc_low;
743  tel[len+1] = crc_high;
744 }
745 
746 int rlModbus::CRCerror(int len)
747 {
748  unsigned char crc_high, crc_low;
749  unsigned index;
750  int i;
751 
752  if(len < 2) return 1;
753  crc_high = crc_low = 0xff;
754  for(i=0; i<len-2; i++)
755  {
756  index = crc_low ^ tel[i];
757  crc_low = crc_high ^ array_crc_low[index];
758  crc_high = array_crc_high[index];
759  }
760  if(crc_low != tel[len-2]) return 1;
761  if(crc_high != tel[len-1]) return 1;
762  return 0;
763 }
764 
765 int rlModbus::readCoilStatus(int slave, int start_adr, int number_of_coils, unsigned char *status, int timeout)
766 {
767  int ret;
768  int ret_slave, ret_function;
769  unsigned char data[256];
770 
771  data[0] = (start_adr / 256) & 0x0ff;
772  data[1] = start_adr & 0x0ff;
773  data[2] = (number_of_coils / 256) & 0x0ff;
774  data[3] = number_of_coils & 0x0ff;
775  ret = write(slave, ReadCoilStatus, data, 4);
776  if(ret < 0) return MODBUS_ERROR;
777 
778  ret = response(&ret_slave, &ret_function, status, timeout);
779  if(ret < 0 || ret_slave != slave || ret_function != ReadCoilStatus)
780  {
781  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
782  ret, slave, ret_slave, ReadCoilStatus, ret_function, timeout);
783  return MODBUS_ERROR;
784  }
785 
786  return ret;
787 }
788 
789 int rlModbus::readInputStatus(int slave, int start_adr, int number_of_inputs, unsigned char *status, int timeout)
790 {
791  int ret;
792  int ret_slave, ret_function;
793  unsigned char data[256];
794 
795  data[0] = (start_adr / 256) & 0x0ff;
796  data[1] = start_adr & 0x0ff;
797  data[2] = (number_of_inputs / 256) & 0x0ff;
798  data[3] = number_of_inputs & 0x0ff;
799  ret = write(slave, ReadInputStatus, data, 4);
800  if(ret < 0) return MODBUS_ERROR;
801 
802  ret = response(&ret_slave, &ret_function, status, timeout);
803  if(ret < 0 || ret_slave != slave || ret_function != ReadInputStatus)
804  {
805  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
806  ret, slave, ret_slave, ReadInputStatus, ret_function, timeout);
807  return MODBUS_ERROR;
808  }
809 
810  return ret;
811 }
812 
813 int rlModbus::readHoldingRegisters(int slave, int start_adr, int number_of_registers, int *registers, int timeout)
814 {
815  int ret;
816  int ret_slave, ret_function;
817  unsigned char data[256];
818 
819  data[0] = (start_adr / 256) & 0x0ff;
820  data[1] = start_adr & 0x0ff;
821  data[2] = (number_of_registers / 256) & 0x0ff;
822  data[3] = number_of_registers & 0x0ff;
823  ret = write(slave, ReadHoldingRegisters, data, 4);
824  if(ret < 0) return MODBUS_ERROR;
825 
826  ret = response(&ret_slave, &ret_function, data, timeout);
827  if(ret < 0 || ret_slave != slave || ret_function != ReadHoldingRegisters)
828  {
829  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
830  ret, slave, ret_slave, ReadHoldingRegisters, ret_function, timeout);
831  return MODBUS_ERROR;
832  }
833  int j = 0;
834  for(int i=0; i<ret; i+=2)
835  {
836  registers[j++] = ((data[i] * 256) & 0x0ff) + (data[i+1] & 0x0ff);
837  }
838 
839  return ret;
840 }
841 
842 int rlModbus::readInputRegisters(int slave, int start_adr, int number_of_registers, int *registers, int timeout)
843 {
844  int ret;
845  int ret_slave, ret_function;
846  unsigned char data[256];
847 
848  data[0] = (start_adr / 256) & 0x0ff;
849  data[1] = start_adr & 0x0ff;
850  data[2] = (number_of_registers / 256) & 0x0ff;
851  data[3] = number_of_registers & 0x0ff;
852  ret = write(slave, ReadInputRegisters, data, 4);
853  if(ret < 0) return MODBUS_ERROR;
854 
855  ret = response(&ret_slave, &ret_function, data, timeout);
856  if(ret < 0 || ret_slave != slave || ret_function != ReadInputRegisters)
857  {
858  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
859  ret, slave, ret_slave, ReadInputRegisters, ret_function, timeout);
860  return MODBUS_ERROR;
861  }
862  int j=0;
863  for(int i=0; i<ret; i+=2)
864  {
865  registers[j++] = ((data[i] * 256) & 0x0ff) + (data[i+1] & 0x0ff);
866  }
867 
868  return ret;
869 }
870 
871 int rlModbus::forceSingleCoil(int slave, int coil_adr, int value, int timeout)
872 {
873  int ret;
874  int ret_slave, ret_function;
875  unsigned char data[256];
876 
877  data[0] = (coil_adr / 256) & 0x0ff;
878  data[1] = coil_adr & 0x0ff;
879  data[2] = 0;
880  data[3] = 0;
881  if(value) data[2] = 0x0ff;
882  ret = write(slave, ForceSingleCoil, data, 4);
883  if(ret < 0) return MODBUS_ERROR;
884 
885  ret = response(&ret_slave, &ret_function, data, timeout);
886  if(ret < 0 || ret_slave != slave || ret_function != ForceSingleCoil)
887  {
888  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
889  ret, slave, ret_slave, ForceSingleCoil, ret_function, timeout);
890  return MODBUS_ERROR;
891  }
892 
893  return ret;
894 }
895 
896 int rlModbus::presetSingleRegister(int slave, int register_adr, int value, int timeout)
897 {
898  int ret;
899  int ret_slave, ret_function;
900  unsigned char data[256];
901 
902  data[0] = (register_adr / 256) & 0x0ff;
903  data[1] = register_adr & 0x0ff;
904  data[2] = (value / 256) & 0x0ff;
905  data[3] = value & 0x0ff;
906  ret = write(slave, PresetSingleRegister, data, 4);
907  if(ret < 0) return MODBUS_ERROR;
908 
909  ret = response(&ret_slave, &ret_function, data, timeout);
910  if(ret < 0 || ret_slave != slave || ret_function != PresetSingleRegister)
911  {
912  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
913  ret, slave, ret_slave, PresetSingleRegister, ret_function, timeout);
914  return MODBUS_ERROR;
915  }
916 
917  return ret;
918 }
919 
920 int rlModbus::forceMultipleCoils(int slave, int coil_adr, int number_of_coils, unsigned char *coils, int timeout)
921 {
922  int ret;
923  int ret_slave, ret_function;
924  unsigned char data[256];
925 
926  data[0] = (coil_adr / 256) & 0x0ff;
927  data[1] = coil_adr & 0x0ff;
928  data[2] = (number_of_coils / 256) & 0x0ff;
929  data[3] = number_of_coils & 0x0ff;
930  data[4] = (number_of_coils / 8) + 1;
931  int i;
932  for(i=0; i<data[4]; i++) data[5+i] = coils[i];
933  ret = write(slave, ForceMultipleCoils, data, 5+i);
934  if(ret < 0) return MODBUS_ERROR;
935 
936  ret = response(&ret_slave, &ret_function, data, timeout);
937  if(ret < 0 || ret_slave != slave || ret_function != ForceMultipleCoils)
938  {
939  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
940  ret, slave, ret_slave, ForceMultipleCoils, ret_function, timeout);
941  return MODBUS_ERROR;
942  }
943 
944  return ret;
945 }
946 
947 int rlModbus::presetMultipleRegisters(int slave, int start_adr, int number_of_registers, int *registers, int timeout)
948 {
949  int ret;
950  int ret_slave, ret_function;
951  unsigned char data[256];
952 
953  data[0] = (start_adr / 256) & 0x0ff;
954  data[1] = start_adr & 0x0ff;
955  data[2] = (number_of_registers / 256) & 0x0ff;
956  data[3] = number_of_registers & 0x0ff;
957  data[4] = (number_of_registers * 2) & 0x0ff;
958  int j=5;
959  for(int i=0; i<number_of_registers; i++)
960  {
961  data[j++] = (registers[i] / 256) & 0x0ff;
962  data[j++] = registers[i] & 0x0ff;
963  }
964  ret = write(slave, PresetMultipleRegs, data, j);
965  if(ret < 0) return MODBUS_ERROR;
966 
967  ret = response(&ret_slave, &ret_function, data, timeout);
968  if(ret < 0 || ret_slave != slave || ret_function != PresetMultipleRegs)
969  {
970  printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
971  ret, slave, ret_slave, PresetMultipleRegs, ret_function, timeout);
972  return MODBUS_ERROR;
973  }
974 
975  return ret;
976 }
977 
978 
int LRCerror(int len)
Definition: rlmodbus.cpp:643
void insertCRC(int len)
Definition: rlmodbus.cpp:728
int readBlock(unsigned char *buf, int len, int timeout=-1)
Definition: rlserial.cpp:498
int readInputStatus(int slave, int start_adr, int number_of_inputs, unsigned char *status, int timeout=1000)
Definition: rlmodbus.cpp:789
int write(const void *buf, int len)
Definition: rlsocket.cpp:282
int mode
Definition: rlmodbus.h:252
void insertLRC(int len)
Definition: rlmodbus.cpp:625
int int2data(int val, unsigned char *data)
Definition: rlmodbus.cpp:42
int readCoilStatus(int slave, int start_adr, int number_of_coils, unsigned char *status, int timeout=1000)
Definition: rlmodbus.cpp:765
void registerSerial(rlSerial *serial)
Definition: rlmodbus.cpp:591
rlSerial * tty
Definition: rlmodbus.h:249
void int2buf_ascii(int i, unsigned char *buf)
Definition: rlmodbus.cpp:620
long maxtel
Definition: rlmodbus.h:251
virtual ~rlModbus()
Definition: rlmodbus.cpp:32
int buf2int_ascii(unsigned char *buf)
Definition: rlmodbus.cpp:612
void registerSocket(rlSocket *socket)
Definition: rlmodbus.cpp:585
static const unsigned char array_crc_low[]
Definition: rlmodbus.cpp:667
int autoreconnectSocket
Definition: rlmodbus.h:214
static const unsigned char array_crc_high[]
Definition: rlmodbus.cpp:698
int write(int slave, int function, const unsigned char *data, int len, int *transactionID=NULL)
Definition: rlmodbus.cpp:54
unsigned char * tel
Definition: rlmodbus.h:250
int select(int timeout=500)
Definition: rlserial.cpp:719
int read(void *buf, int len, int timeout=0)
Definition: rlsocket.cpp:191
rlSocket * s
Definition: rlmodbus.h:248
int buf2int_rtu(unsigned char *buf)
Definition: rlmodbus.cpp:597
int forceSingleCoil(int slave, int coil_adr, int value, int timeout=1000)
Definition: rlmodbus.cpp:871
int presetMultipleRegisters(int slave, int start_adr, int number_of_registers, int *registers, int timeout=1000)
Definition: rlmodbus.cpp:947
int readChar()
Definition: rlserial.cpp:405
int intsize()
Definition: rlmodbus.cpp:49
rlModbus(long max_telegram_length=1024, int mode=MODBUS_RTU, char end_delimitor=0x0a)
Definition: rlmodbus.cpp:20
int readHoldingRegisters(int slave, int start_adr, int number_of_registers, int *registers, int timeout=1000)
Definition: rlmodbus.cpp:813
int forceMultipleCoils(int slave, int coil_adr, int number_of_coils, unsigned char *coils, int timeout=1000)
Definition: rlmodbus.cpp:920
int presetSingleRegister(int slave, int register_adr, int value, int timeout=1000)
Definition: rlmodbus.cpp:896
void int2buf_rtu(int i, unsigned char *buf)
Definition: rlmodbus.cpp:602
int connect()
Definition: rlsocket.cpp:307
char delimitor
Definition: rlmodbus.h:253
int response(int *slave, int *function, unsigned char *data, int timeout=1000)
Definition: rlmodbus.cpp:132
int isConnected()
Definition: rlsocket.cpp:543
int data2int(const unsigned char *data)
Definition: rlmodbus.cpp:37
int request(int slave, int function, int start_adr, int num_register)
Definition: rlmodbus.cpp:121
int readInputRegisters(int slave, int start_adr, int number_of_registers, int *registers, int timeout=1000)
Definition: rlmodbus.cpp:842
int writeBlock(const unsigned char *buf, int len)
Definition: rlserial.cpp:584
int readRequest(int *slave, int *function, unsigned char *data, int timeout=1000, int *transactionID=NULL)
Definition: rlmodbus.cpp:350
int CRCerror(int len)
Definition: rlmodbus.cpp:746