rllib  1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
Public Types | Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | List of all members
rlModbus Class Reference

#include <rlmodbus.h>

Collaboration diagram for rlModbus:
Collaboration graph
[legend]

Public Types

enum  Modbus {
  MODBUS_CHECKSUM_ERROR = -2, MODBUS_ERROR = -1, MODBUS_SUCCESS = 0, MODBUS_RTU = 1,
  MODBUS_ASCII = 2
}
 
enum  ModbusFunctionCodes {
  ReadCoilStatus = 1, ReadInputStatus = 2, ReadHoldingRegisters = 3, ReadInputRegisters = 4,
  ForceSingleCoil = 5, PresetSingleRegister = 6, ReadExceptionStatus = 7, FetchCommEventCtr = 11,
  FetchCommEventLog = 12, ForceMultipleCoils = 15, PresetMultipleRegs = 16, ReportSlaveID = 17,
  ReadGeneralReference = 20, WriteGeneralReference = 21, MaskWrite4XRegisters = 22, ReadWrite4XRegisters = 23,
  ReadFifoQueue = 24
}
 

Public Member Functions

 rlModbus (long max_telegram_length=1024, int mode=MODBUS_RTU, char end_delimitor=0x0a)
 
virtual ~rlModbus ()
 
int write (int slave, int function, const unsigned char *data, int len, int *transactionID=NULL)
 
int request (int slave, int function, int start_adr, int num_register)
 
int response (int *slave, int *function, unsigned char *data, int timeout=1000)
 
int readRequest (int *slave, int *function, unsigned char *data, int timeout=1000, int *transactionID=NULL)
 
void registerSocket (rlSocket *socket)
 
void registerSerial (rlSerial *serial)
 
int data2int (const unsigned char *data)
 
int int2data (int val, unsigned char *data)
 
int intsize ()
 
int readCoilStatus (int slave, int start_adr, int number_of_coils, unsigned char *status, int timeout=1000)
 
int readInputStatus (int slave, int start_adr, int number_of_inputs, unsigned char *status, int timeout=1000)
 
int readHoldingRegisters (int slave, int start_adr, int number_of_registers, int *registers, int timeout=1000)
 
int readInputRegisters (int slave, int start_adr, int number_of_registers, int *registers, int timeout=1000)
 
int forceSingleCoil (int slave, int coil_adr, int value, int timeout=1000)
 
int presetSingleRegister (int slave, int register_adr, int value, int timeout=1000)
 
int forceMultipleCoils (int slave, int coil_adr, int number_of_coils, unsigned char *coils, int timeout=1000)
 
int presetMultipleRegisters (int slave, int start_adr, int number_of_registers, int *registers, int timeout=1000)
 

Public Attributes

int autoreconnectSocket
 

Private Member Functions

int buf2int_rtu (unsigned char *buf)
 
void int2buf_rtu (int i, unsigned char *buf)
 
int buf2int_ascii (unsigned char *buf)
 
void int2buf_ascii (int i, unsigned char *buf)
 
void insertLRC (int len)
 
void insertCRC (int len)
 
int LRCerror (int len)
 
int CRCerror (int len)
 

Private Attributes

rlSockets
 
rlSerialtty
 
unsigned char * tel
 
long maxtel
 
int mode
 
char delimitor
 

Detailed Description

This class implements the modbus protocol.
You can use serial interfaces or TCP/IP.
Modbus RTU and ASCII are available.
All Modbus requests include "slave" and "function".
Then some bytes follow, which are specific to a given function.
The request is then terminated by a checksum.
This table shows the bytes that are specific to a given function.
Function Query Response
01 Read Coil Status Start adr high
Start adr low
Number of points high
Number of points low
Data Byte Count
Data1
Data2 …
8 points per byte
02 Read Input Status Start adr high
Start adr low
Number of points high
Number of points low
Data Byte Count
Data1
Data2 …
8 points per byte
03 Read Holding Registers Start adr high
Start adr low
Number of points high
Number of points low
Data Byte Count
Data1 high
Data1 low
Data2 high
Data2 low…
1 point needs 2 bytes
04 Read Input Registers Start adr high
Start adr low
Number of points high
Number of points low
Data Byte Count
Data1 high
Data1 low
Data2 high
Data2 low…
1 point needs 2 bytes
05 Force Single Coil Coil adr high
Coil adr low
Force data high
Force data low
Coil adr high
Coil adr low
Force data high
Force data low
Force data ON = 0x0ff00
Force data OFF = 0
06 Preset Single Register Register adr high
Register adr low
Preset data high
Preset data low
Register adr high
Register adr low
Preset data high
Preset data low

07 Read Exception Status
Coil data 8 exception status coils returned
11 Fetch Comm Event Counter
Status high
Status low
Event Count high
Event Count low

12 Fetch Comm Event Log

See: PI_MODBUS_300.pdf
15 Force Multiple Coils Coil adr high
Coil adr low
Number of coils high
Number of coils low
Force data byte count
Force data1
Force data2 ...
Coil adr high
Coil adr low
Number of coils high
Number of coils low
8 coils per byte
16 Preset Multiple Registers Start adr high
Start adr low
Number of registers high
Number of registers low
Data byte count
Data1 high
Data1 low
Data2 high
Data2 low …
Start adr high
Start adr low
Number of registers high
Number of registers low

17 Report Slave ID
Data Byte count ~ device specific See: PI_MODBUS_300.pdf
20 Read General Reference

See: PI_MODBUS_300.pdf
21 Write General Reference

See: PI_MODBUS_300.pdf
22 Mask Write 4X Register

See: PI_MODBUS_300.pdf
23 Read/Write 4X Registers

See: PI_MODBUS_300.pdf
24 Read FIFO Queue

See: PI_MODBUS_300.pdf

Definition at line 148 of file rlmodbus.h.

Member Enumeration Documentation

Enumerator:
MODBUS_CHECKSUM_ERROR 
MODBUS_ERROR 
MODBUS_SUCCESS 
MODBUS_RTU 
MODBUS_ASCII 

Definition at line 151 of file rlmodbus.h.

Enumerator:
ReadCoilStatus 
ReadInputStatus 
ReadHoldingRegisters 
ReadInputRegisters 
ForceSingleCoil 
PresetSingleRegister 
ReadExceptionStatus 
FetchCommEventCtr 
FetchCommEventLog 
ForceMultipleCoils 
PresetMultipleRegs 
ReportSlaveID 
ReadGeneralReference 
WriteGeneralReference 
MaskWrite4XRegisters 
ReadWrite4XRegisters 
ReadFifoQueue 

Definition at line 160 of file rlmodbus.h.

Constructor & Destructor Documentation

rlModbus::rlModbus ( long  max_telegram_length = 1024,
int  mode = MODBUS_RTU,
char  end_delimitor = 0x0a 
)

Definition at line 20 of file rlmodbus.cpp.

{
if(max_telegram_length < 256) max_telegram_length = 256;
tel = new unsigned char[max_telegram_length];
maxtel = max_telegram_length;
mode = _mode;
delimitor = end_delimitor;
s = NULL;
tty = NULL;
}
rlModbus::~rlModbus ( )
virtual

Definition at line 32 of file rlmodbus.cpp.

{
if(tel != NULL) delete [] tel;
}

Member Function Documentation

int rlModbus::buf2int_ascii ( unsigned char *  buf)
private

Definition at line 612 of file rlmodbus.cpp.

{
int val;
sscanf((char *) buf,"%04X",&val);
return val;
}
int rlModbus::buf2int_rtu ( unsigned char *  buf)
private

Definition at line 597 of file rlmodbus.cpp.

{
return (buf[0]*256 + buf[1]);
}
int rlModbus::CRCerror ( int  len)
private

Definition at line 746 of file rlmodbus.cpp.

{
unsigned char crc_high, crc_low;
unsigned index;
int i;
if(len < 2) return 1;
crc_high = crc_low = 0xff;
for(i=0; i<len-2; i++)
{
index = crc_low ^ tel[i];
crc_low = crc_high ^ array_crc_low[index];
crc_high = array_crc_high[index];
}
if(crc_low != tel[len-2]) return 1;
if(crc_high != tel[len-1]) return 1;
return 0;
}
int rlModbus::data2int ( const unsigned char *  data)

Definition at line 37 of file rlmodbus.cpp.

{
return (data[0]*256)+data[1];
}
int rlModbus::forceMultipleCoils ( int  slave,
int  coil_adr,
int  number_of_coils,
unsigned char *  coils,
int  timeout = 1000 
)

Definition at line 920 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (coil_adr / 256) & 0x0ff;
data[1] = coil_adr & 0x0ff;
data[2] = (number_of_coils / 256) & 0x0ff;
data[3] = number_of_coils & 0x0ff;
data[4] = (number_of_coils / 8) + 1;
int i;
for(i=0; i<data[4]; i++) data[5+i] = coils[i];
ret = write(slave, ForceMultipleCoils, data, 5+i);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, data, timeout);
if(ret < 0 || ret_slave != slave || ret_function != ForceMultipleCoils)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, ForceMultipleCoils, ret_function, timeout);
return MODBUS_ERROR;
}
return ret;
}
int rlModbus::forceSingleCoil ( int  slave,
int  coil_adr,
int  value,
int  timeout = 1000 
)

Definition at line 871 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (coil_adr / 256) & 0x0ff;
data[1] = coil_adr & 0x0ff;
data[2] = 0;
data[3] = 0;
if(value) data[2] = 0x0ff;
ret = write(slave, ForceSingleCoil, data, 4);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, data, timeout);
if(ret < 0 || ret_slave != slave || ret_function != ForceSingleCoil)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, ForceSingleCoil, ret_function, timeout);
return MODBUS_ERROR;
}
return ret;
}
void rlModbus::insertCRC ( int  len)
private

Definition at line 728 of file rlmodbus.cpp.

{
unsigned char crc_high, crc_low;
unsigned index;
int i;
if(len < 0) return;
crc_high = crc_low = 0xff;
for(i=0; i<len; i++)
{
index = crc_low ^ tel[i];
crc_low = crc_high ^ array_crc_low[index];
crc_high = array_crc_high[index];
}
tel[len] = crc_low;
tel[len+1] = crc_high;
}
void rlModbus::insertLRC ( int  len)
private

Definition at line 625 of file rlmodbus.cpp.

{
unsigned char lrc;
int i,high,low,val;
if(len < 0) return;
lrc = 0;
for(i=1; i<len; i+=2) // exclude starting ':' and trailing <CR><LF>
{
sscanf((const char *) &tel[i], "%1X", &high);
sscanf((const char *) &tel[i+1], "%1X", &low);
val = high*16 + low;
lrc += val;
}
lrc = ((unsigned char)(-((char) lrc)));
sprintf((char *) &tel[len],"%02X",(unsigned int) lrc);
}
void rlModbus::int2buf_ascii ( int  i,
unsigned char *  buf 
)
private

Definition at line 620 of file rlmodbus.cpp.

{
sprintf((char *) buf,"%04X",i);
}
void rlModbus::int2buf_rtu ( int  i,
unsigned char *  buf 
)
private

Definition at line 602 of file rlmodbus.cpp.

{
int high, low;
high = i / 256;
low = i & 0x0ff;
buf[0] = (unsigned char) high;
buf[1] = (unsigned char) low;
}
int rlModbus::int2data ( int  val,
unsigned char *  data 
)

Definition at line 42 of file rlmodbus.cpp.

{
data[0] = (unsigned char) val / 256;
data[1] = (unsigned char) val & 0x0ff;
return 0;
}
int rlModbus::intsize ( )

Definition at line 49 of file rlmodbus.cpp.

{
return 2;
}
int rlModbus::LRCerror ( int  len)
private

Definition at line 643 of file rlmodbus.cpp.

{
unsigned char *cptr;
unsigned char lrc;
int i,high,low,val;
if(len < 0) return 1;
tel[maxtel-1] = '\0';
cptr = (unsigned char *) strchr((char *)tel,':');
if(cptr == NULL) return 1;
cptr++;
lrc = 0;
for(i=1; i<len+2; i+=2) // exclude starting ':' and trailing <CR><LF>
{ // len is without lrc -> len+2
sscanf((const char *) cptr++, "%1X", &high);
sscanf((const char *) cptr++, "%1X", &low);
val = high*16 + low;
lrc += val;
}
if(lrc == 0) return 0; // lrc ok
return 1; // lrc error
}
int rlModbus::presetMultipleRegisters ( int  slave,
int  start_adr,
int  number_of_registers,
int *  registers,
int  timeout = 1000 
)

Definition at line 947 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (start_adr / 256) & 0x0ff;
data[1] = start_adr & 0x0ff;
data[2] = (number_of_registers / 256) & 0x0ff;
data[3] = number_of_registers & 0x0ff;
data[4] = (number_of_registers * 2) & 0x0ff;
int j=5;
for(int i=0; i<number_of_registers; i++)
{
data[j++] = (registers[i] / 256) & 0x0ff;
data[j++] = registers[i] & 0x0ff;
}
ret = write(slave, PresetMultipleRegs, data, j);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, data, timeout);
if(ret < 0 || ret_slave != slave || ret_function != PresetMultipleRegs)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, PresetMultipleRegs, ret_function, timeout);
return MODBUS_ERROR;
}
return ret;
}
int rlModbus::presetSingleRegister ( int  slave,
int  register_adr,
int  value,
int  timeout = 1000 
)

Definition at line 896 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (register_adr / 256) & 0x0ff;
data[1] = register_adr & 0x0ff;
data[2] = (value / 256) & 0x0ff;
data[3] = value & 0x0ff;
ret = write(slave, PresetSingleRegister, data, 4);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, data, timeout);
if(ret < 0 || ret_slave != slave || ret_function != PresetSingleRegister)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, PresetSingleRegister, ret_function, timeout);
return MODBUS_ERROR;
}
return ret;
}
int rlModbus::readCoilStatus ( int  slave,
int  start_adr,
int  number_of_coils,
unsigned char *  status,
int  timeout = 1000 
)

Definition at line 765 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (start_adr / 256) & 0x0ff;
data[1] = start_adr & 0x0ff;
data[2] = (number_of_coils / 256) & 0x0ff;
data[3] = number_of_coils & 0x0ff;
ret = write(slave, ReadCoilStatus, data, 4);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, status, timeout);
if(ret < 0 || ret_slave != slave || ret_function != ReadCoilStatus)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, ReadCoilStatus, ret_function, timeout);
return MODBUS_ERROR;
}
return ret;
}
int rlModbus::readHoldingRegisters ( int  slave,
int  start_adr,
int  number_of_registers,
int *  registers,
int  timeout = 1000 
)

Definition at line 813 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (start_adr / 256) & 0x0ff;
data[1] = start_adr & 0x0ff;
data[2] = (number_of_registers / 256) & 0x0ff;
data[3] = number_of_registers & 0x0ff;
ret = write(slave, ReadHoldingRegisters, data, 4);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, data, timeout);
if(ret < 0 || ret_slave != slave || ret_function != ReadHoldingRegisters)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, ReadHoldingRegisters, ret_function, timeout);
return MODBUS_ERROR;
}
int j = 0;
for(int i=0; i<ret; i+=2)
{
registers[j++] = ((data[i] * 256) & 0x0ff) + (data[i+1] & 0x0ff);
}
return ret;
}
int rlModbus::readInputRegisters ( int  slave,
int  start_adr,
int  number_of_registers,
int *  registers,
int  timeout = 1000 
)

Definition at line 842 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (start_adr / 256) & 0x0ff;
data[1] = start_adr & 0x0ff;
data[2] = (number_of_registers / 256) & 0x0ff;
data[3] = number_of_registers & 0x0ff;
ret = write(slave, ReadInputRegisters, data, 4);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, data, timeout);
if(ret < 0 || ret_slave != slave || ret_function != ReadInputRegisters)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, ReadInputRegisters, ret_function, timeout);
return MODBUS_ERROR;
}
int j=0;
for(int i=0; i<ret; i+=2)
{
registers[j++] = ((data[i] * 256) & 0x0ff) + (data[i+1] & 0x0ff);
}
return ret;
}
int rlModbus::readInputStatus ( int  slave,
int  start_adr,
int  number_of_inputs,
unsigned char *  status,
int  timeout = 1000 
)

Definition at line 789 of file rlmodbus.cpp.

{
int ret;
int ret_slave, ret_function;
unsigned char data[256];
data[0] = (start_adr / 256) & 0x0ff;
data[1] = start_adr & 0x0ff;
data[2] = (number_of_inputs / 256) & 0x0ff;
data[3] = number_of_inputs & 0x0ff;
ret = write(slave, ReadInputStatus, data, 4);
if(ret < 0) return MODBUS_ERROR;
ret = response(&ret_slave, &ret_function, status, timeout);
if(ret < 0 || ret_slave != slave || ret_function != ReadInputStatus)
{
printf("rlMOdbus::ERROR response ret=%d slave=%d ret_slave=%d function=%d ret_function=%d timeout=%d\n",
ret, slave, ret_slave, ReadInputStatus, ret_function, timeout);
return MODBUS_ERROR;
}
return ret;
}
int rlModbus::readRequest ( int *  slave,
int *  function,
unsigned char *  data,
int  timeout = 1000,
int *  transactionID = NULL 
)

Definition at line 350 of file rlmodbus.cpp.

{
unsigned char *telptr;
int ret,len,byte_count,i,itel,val;
len = 0;
if(s != NULL)
{
if(s->isConnected() == 0) return MODBUS_ERROR;
{
if(s->read((char *) tel, 6, timeout) <= 0) return MODBUS_ERROR;
if(transactionID != NULL) *transactionID = tel[0] * 256 + tel[1]; // return transactionID
// bytes 0,1 Transaction ID faithfully copied from the request message
// bytes 2,3 Protocol number always zero
// byte 4 Response length (upper byte) Always zero
// byte 5 Response length (lower byte). Equal to the number of bytes which follow
// Here comes the normal Modus telegram
if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
*slave = tel[0];
*function = tel[1];
switch(*function)
{
if(s->read((char *) data, 4, timeout) <= 0) return MODBUS_ERROR;
return 4;
return 0;
if(s->read((char *) data, 5, timeout) <= 0) return MODBUS_ERROR;
byte_count = data[4];
if(s->read((char *) &data[4], byte_count, timeout) <= 0) return MODBUS_ERROR;
return 4+byte_count;
if(s->read((char *) data, 1, timeout) <= 0) return MODBUS_ERROR;
byte_count = data[0];
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
if(s->read((char *) data, 6, timeout) <= 0) return MODBUS_ERROR;
return 6;
if(s->read((char *) data, 9, timeout) <= 0) return MODBUS_ERROR;
byte_count = data[8];
if(s->read((char *) &data[8], byte_count, timeout) <= 0) return MODBUS_ERROR;
return 8+byte_count;
if(s->read((char *) data, 2, timeout) <= 0) return MODBUS_ERROR;
return 2;
default:
return MODBUS_ERROR;
}
}
}
else if(tty != NULL)
{
{
//printf("modbus ascii\n");
for(i=0; i<maxtel; i++)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
//printf("readChar\n");
itel = tty->readChar();
if(itel < 0) return MODBUS_ERROR;
tel[i] = (unsigned char) itel;
if(tel[i] == 0x0d && delimitor != 0x0a) break;
if(tel[i] == 0x0a) break;
}
tel[i] = '\0';
telptr = (unsigned char *) strchr((const char *) tel,':');
if(telptr == NULL) return MODBUS_ERROR;
len++;
sscanf((char *) &telptr[len],"%02X",slave); len += 2;
sscanf((char *) &telptr[len],"%02X",function); len += 2;
switch(*function)
{
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4;
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 0;
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(i=0; i<byte_count; i++)
{
sscanf((char *) &telptr[len],"%02X",&val); data[4+i] = (unsigned char) val; len += 2;
}
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4+byte_count;
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(i=0; i<byte_count; i++)
{
sscanf((char *) &telptr[len],"%02X",&val); data[i] = (unsigned char) val; len += 2;
}
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[4] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[5] = (unsigned char) val; len += 2;
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 6;
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[2] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[3] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[4] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[5] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[6] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[7] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(i=0; i<byte_count; i++)
{
sscanf((char *) &telptr[len],"%02X",&val); data[8+i] = (unsigned char) val; len += 2;
}
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 8+byte_count;
sscanf((char *) &telptr[len],"%02X",&val); data[0] = (unsigned char) val; len += 2;
sscanf((char *) &telptr[len],"%02X",&val); data[1] = (unsigned char) val; len += 2;
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 2;
default:
return MODBUS_ERROR;
}
}
else if(mode == MODBUS_RTU)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
if(tty->readBlock(tel, 2, timeout) <= 0) return MODBUS_ERROR;
*slave = tel[len++];
*function = tel[len++];
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
switch(*function)
{
if(tty->readBlock(data, 4+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,4+2); len += 4+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 0;
if(tty->readBlock(data, 5, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,5); len += 5;
byte_count = data[4];
if(tty->readBlock(&data[4], byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 4+byte_count;
if(tty->readBlock(data, 1, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,1); len++;
byte_count = data[0];
if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
if(tty->readBlock(data, 6+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,6+2); len += 6+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 6;
if(tty->readBlock(data, 9, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,9); len += 9;
byte_count = data[8];
if(tty->readBlock(&data[8], byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 8+byte_count;
if(tty->readBlock(data, 2+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,2+2); len += 2+2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return 2;
default:
return MODBUS_ERROR;
}
}
}
else return MODBUS_ERROR;
}
void rlModbus::registerSerial ( rlSerial serial)

Definition at line 591 of file rlmodbus.cpp.

{
s = NULL;
tty = serial;
}
void rlModbus::registerSocket ( rlSocket socket)

Definition at line 585 of file rlmodbus.cpp.

{
tty = NULL;
s = socket;
}
int rlModbus::request ( int  slave,
int  function,
int  start_adr,
int  num_register 
)

Definition at line 121 of file rlmodbus.cpp.

{
unsigned char data[4];
data[0] = (unsigned char) ( start_adr / 256 );
data[1] = (unsigned char) ( start_adr & 0x0ff );
data[2] = (unsigned char) ( num_register / 256 );
data[3] = (unsigned char) ( num_register & 0x0ff );
return write(slave, function, data, 4);
}
int rlModbus::response ( int *  slave,
int *  function,
unsigned char *  data,
int  timeout = 1000 
)

Definition at line 132 of file rlmodbus.cpp.

{
unsigned char *telptr;
int ret,len,byte_count,idata,i,itel,val;
len = 0;
if(s != NULL)
{
if(s->isConnected() == 0) return MODBUS_ERROR;
{
if(s->read((char *) tel, 6, timeout) <= 0) return MODBUS_ERROR;
// bytes 0,1 Transaction ID faithfully copied from the request message
// bytes 2,3 Protocol number always zero
// byte 4 Response length (upper byte) Always zero
// byte 5 Response length (lower byte). Equal to the number of bytes which follow
// Here comes the normal Modus telegram
if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
*slave = tel[0];
*function = tel[1];
switch(*function)
{
if(s->read((char *) tel, 1, timeout) <= 0) return MODBUS_ERROR;
byte_count = tel[0];
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
byte_count = 4;
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
byte_count = 1;
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
byte_count = 6;
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
if(s->read((char *) tel, 2, timeout) <= 0) return MODBUS_ERROR;
byte_count = tel[0]*256 + tel[1];
if(s->read((char *) data, byte_count, timeout) <= 0) return MODBUS_ERROR;
return byte_count;
default:
return MODBUS_ERROR;
}
}
}
else if(tty != NULL)
{
{
//printf("modbus ascii\n");
for(i=0; i<maxtel; i++)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
//printf("readChar\n");
itel = tty->readChar();
if(itel < 0) return MODBUS_ERROR;
tel[i] = (unsigned char) itel;
if(tel[i] == 0x0d && delimitor != 0x0a) break;
if(tel[i] == 0x0a) break;
}
tel[i] = '\0';
telptr = (unsigned char *) strchr((const char *) tel,':');
if(telptr == NULL) return MODBUS_ERROR;
len++;
sscanf((char *) &telptr[len],"%02X",slave); len += 2;
sscanf((char *) &telptr[len],"%02X",function); len += 2;
switch(*function)
{
sscanf((char *) &telptr[len],"%02X",&byte_count); len += 2;
for(idata=0; idata<byte_count; idata++)
{
sscanf((const char *) &telptr[len], "%02X", &val); len += 2;
data[idata] = val;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
byte_count = 8;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
byte_count = 2;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
byte_count = 12;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
sscanf((char *) &telptr[len],"%04X",&byte_count); len += 4;
for(idata=0; idata<(byte_count/2); idata++)
{
data[idata] = buf2int_ascii(&telptr[len]); len += 2;
}
data[idata] = 0x0ff; // terminator, this data can't come over modbus
if(LRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
break;
default:
return MODBUS_ERROR;
}
}
else if(mode == MODBUS_RTU)
{
ret = tty->select(timeout);
if(ret == 0) return MODBUS_ERROR;
if(tty->readBlock(tel, 2, timeout) <= 0) return MODBUS_ERROR;
*slave = tel[len++];
*function = tel[len++];
switch(*function)
{
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(&tel[len], 1, timeout) <= 0) return MODBUS_ERROR;
byte_count = tel[len++];
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
byte_count = 4;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
byte_count = 1;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
byte_count = 6;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(&tel[len], 2, timeout) <= 0) return MODBUS_ERROR;
byte_count = tel[len]*256 + tel[len+1]; len += 2;
if(tty->select(timeout) == 0) return MODBUS_ERROR;
if(tty->readBlock(data, byte_count+2, timeout) <= 0) return MODBUS_ERROR;
memcpy(&tel[len],data,byte_count+2); len += byte_count + 2;
if(CRCerror(len) == 1) return MODBUS_CHECKSUM_ERROR;
return byte_count;
default:
return MODBUS_ERROR;
}
}
}
else return MODBUS_ERROR;
}
int rlModbus::write ( int  slave,
int  function,
const unsigned char *  data,
int  len,
int *  transactionID = NULL 
)

Definition at line 54 of file rlmodbus.cpp.

{
int len,i;
if(slave < 0 || slave > 255) return MODBUS_ERROR;
len = 0;
{
tel[len++] = ':';
sprintf((char *) &tel[len], "%02X", slave); len += 2;
sprintf((char *) &tel[len], "%02X", function); len += 2;
for(i=0; i<datalen; i++)
{
sprintf((char *) &tel[len], "%02X",(int) data[i]); len += 2;
if((len+4) > maxtel) return MODBUS_ERROR;
}
insertLRC(len); len += 2;
tel[len++] = 0x0d;
if(delimitor == 0x0a) tel[len++] = 0x0a;
}
else if(mode == MODBUS_RTU)
{
if(s != NULL)
{
if(transactionID == NULL)
{
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.
tel[len++] = 0;
}
else
{
tel[len++] = ((*transactionID) & 0xFF00) / 256; // bytes 0,1 Transaction ID.
tel[len++] = (*transactionID) & 0xFF;
}
tel[len++] = 0; // bytes 2,3 Protocol number. Must be zero.
tel[len++] = 0;
tel[len++] = 0; // byte 4 Length (upper byte). Since all requests will be less than 256 bytes in length (!), this will always be zero.
tel[len++] = 2+datalen; // byte 5 Length (lower byte). Equal to the number of bytes which follow
}
tel[len++] = (unsigned char) slave;
tel[len++] = (unsigned char) function;
for(i=0; i<datalen; i++)
{
tel[len++] = data[i];
if((len+2) > maxtel) return MODBUS_ERROR;
}
insertCRC(len); len += 2;
}
else return MODBUS_ERROR;
if(s != NULL)
{
if(s->isConnected() == 0)
{
if(s->isConnected() == 0) return MODBUS_ERROR;
}
if(s->write(tel,len-2) < 0) return MODBUS_ERROR; // don't send LRC or CRC
}
else if(tty != NULL)
{
if(tty->writeBlock(tel,len) < 0) return MODBUS_ERROR;
}
else return MODBUS_ERROR;
}

Member Data Documentation

int rlModbus::autoreconnectSocket

Definition at line 192 of file rlmodbus.h.

char rlModbus::delimitor
private

Definition at line 216 of file rlmodbus.h.

long rlModbus::maxtel
private

Definition at line 214 of file rlmodbus.h.

int rlModbus::mode
private

Definition at line 215 of file rlmodbus.h.

rlSocket* rlModbus::s
private

Definition at line 211 of file rlmodbus.h.

unsigned char* rlModbus::tel
private

Definition at line 213 of file rlmodbus.h.

rlSerial* rlModbus::tty
private

Definition at line 212 of file rlmodbus.h.


The documentation for this class was generated from the following files: