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