This class defines the interface between a Modbus slave Server Engine and your application.
More...
|
Data Access Methods to support read and write of output registers (holding registers) in table 4:00000.
This table is accessed by the following Modbus functions:
- Modbus function 16 (10 hex), Preset Multiple Registers/Write Multiple Registers
- Modbus function 3 (03 hex), Read Holding Registers/Read Multiple Registers
- Modbus function 6 (06 hex), Preset Single Register/Write Single Register.
- Modbus function 22 (16 hex), Mask Write Register.
- Modbus function 23 (17 hex), Read/Write Registers.
|
| virtual int | readHoldingRegistersTable (int startRef, short regArr[], int refCnt) |
| | Override this method to implement a Data Provider function to read Holding Registers. More...
|
| |
| virtual int | writeHoldingRegistersTable (int startRef, const short regArr[], int refCnt) |
| | Override this method to implement a Data Provider function to write Holding Registers. More...
|
| |
| virtual int | readEnronRegistersTable (int startRef, long regArr[], int refCnt) |
| | Implement this function only if your slave device has to process register ranges as Daniel/ENRON 32-bit registers. More...
|
| |
| virtual int | writeEnronRegistersTable (int startRef, const long regArr[], int refCnt) |
| | Implement this function only if your slave device has to process register ranges as Daniel/ENRON 32-bit registers. More...
|
| |
|
Data Access Methods to support read of input registers in table 3:00000.
This table is accessed by the following Modbus functions:
- Modbus function 4 (04 hex), Read Input Registers.
- Note
- Input registers cannot be written
|
| virtual int | readInputRegistersTable (int startRef, short regArr[], int refCnt) |
| | Override this method to implement a Data Provider function to read Input Registers. More...
|
| |
|
Data Access Methods to support read and write of discrete outputs (coils) in table 0:00000.
This table is accessed by the following Modbus functions:
- Modbus function 1 (01 hex), Read Coil Status/Read Coils.
- Modbus function 5 (05 hex), Force Single Coil/Write Coil.
- Modbus function 15 (0F hex), Force Multiple Coils.
|
| virtual int | readCoilsTable (int startRef, char bitArr[], int refCnt) |
| | Override this method to implement a Data Provider function to read Coils. More...
|
| |
| virtual int | writeCoilsTable (int startRef, const char bitArr[], int refCnt) |
| | Override this method to implement a Data Provider function to write Coils. More...
|
| |
|
Data Access Methods to support read discrete inputs (input status) in table 1:00000.
This table is accessed by the following Modbus functions:
- Modbus function 2 (02 hex), Read Inputs Status/Read Input Discretes.
- Note
- Input Discretes cannot be written
|
| virtual int | readInputDiscretesTable (int startRef, char bitArr[], int refCnt) |
| | Override this method to implement a Data Provider function to read Coils. More...
|
| |
|
- Modbus function 20 (13 hex), Read File Records.
- Modbus function 21 (15 hex), Write File Records.
|
| virtual int | readFileRecord (int refType, int fileNo, int startRef, short regArr[], int refCnt) |
| | Override this method to implement a Data Provider function to read File Records which is Modbus function code 20 (14 hex). More...
|
| |
| virtual int | writeFileRecord (int refType, int fileNo, int startRef, short regArr[], int refCnt) |
| | Override this method to implement a Data Provider function to write File Records which is Modbus function code 21 (15 hex). More...
|
| |
|
| virtual char | readExceptionStatus () |
| | Override this method to implement a function with reports the eight exception status coils (bits) within the slave device. More...
|
| |
| virtual int | reportSlaveId (char bufferArr[], int maxBufSize) |
| | Override this method to implement a function which reports the Slave ID. More...
|
| |
| virtual int | reportRunIndicatorStatus () |
| | Override this method to implement a function which reports the Run Indicator of a device. More...
|
| |
| virtual int | readDeviceIdentification (int objId, char bufferArr[], int maxBufSize) |
| | Override this method to implement Read Device Identification objects to support Modbus function 43 (hex 2B) subfunction 14 (hex 0E). More...
|
| |
|
Implementation of these functions may only be required in multithreaded applications, if you are running the server loop in a separate thread and in addition require data consistency over a block of Modbus registers.
Data consistency within a single register is always maintained if the code executes on a 16-bit or 32-bit machine, because the CPU is accessing these data types atomically.
|
| virtual void | lock () |
| | You can override this method to implement a mutex locking mechanism to synchronise data access. More...
|
| |
| virtual void | unlock () |
| | You can override this method to implement a mutex un-locking mechanism to synchronise data access. More...
|
| |
This class defines the interface between a Modbus slave Server Engine and your application.
Descendants of this class are referred to as Data Providers.
To create an application specific Data Provider derive a new class from MbusDataTableInterface and override the required data access methods.
- See also
- Server Functions common to all Modbus Protocol Flavours
-
MbusRtuSlaveProtocol, MbusAsciiSlaveProtocol, MbusTcpSlaveProtocol
◆ readHoldingRegistersTable()
| virtual int readHoldingRegistersTable |
( |
int |
startRef, |
|
|
short |
regArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to read Holding Registers.
When a slave receives a poll request for the 4:00000 data table it calls this method to retrieve the data.
A simple implementation which holds the application data in an array of shorts (short regData[0x10000]) could be:
{
startRef--;
if (startRef + refCnt > (int) sizeof(regData) / sizeof(short))
return 0;
memcpy(regArr, ®Data[startRef], refCnt * sizeof(short));
return 1;
}
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| regArr | Buffer which has to be filled with the reply data |
| refCnt | Number of registers to be retrieved (Range: 0 - 125) |
- Return values
-
| 1 | Indicate a successful access and that valid reply data is contained in regArr. The Server Engine will reply the data passed in regArr to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- Yes
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ writeHoldingRegistersTable()
| virtual int writeHoldingRegistersTable |
( |
int |
startRef, |
|
|
const short |
regArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to write Holding Registers.
When a slave receives a write request for the 4:00000 data table it calls this method to pass the data to the application.
A simple implementation which holds the application data in an array of shorts (short regData[0x10000]) could be:
{
startRef--;
if (startRef + refCnt > (int) sizeof(regData) / sizeof(short))
return 0;
memcpy(®Data[startRef], regArr, refCnt * sizeof(short));
return 1;
}
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| regArr | Buffer which contains the received data |
| refCnt | Number of registers received (Range: 0 - 125) |
- Return values
-
| 1 | Indicate a successful access. The Server Engine will send a positive reply to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- Yes
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ readEnronRegistersTable()
| virtual int readEnronRegistersTable |
( |
int |
startRef, |
|
|
long |
regArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Implement this function only if your slave device has to process register ranges as Daniel/ENRON 32-bit registers.
If a register range is processed as Daniel/ENRON register then this range is not available as normal Holding Register range.
- Note
- Daniel/ENRON is a prorietary 32-bit format which uses a non-standard Modbus frame and not understood by most master devices.
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| regArr | Buffer which has to be filled with the reply data |
| refCnt | Number of registers to be retrieved (Range: 0 - 62) |
- Return values
-
| 1 | Indicate a successful access and that valid reply data is contained in regArr. The Server Engine will reply the data passed in regArr to the master using the Daniel/ENRON frame format. |
| 0 | Indicate that the requested range is not to be processed using the Daniel/ENRON frame format. A subsequent call to readHoldingRegistersTable() will be made to process the range in standard Modbus frame format. |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates that the requested register range is processed as standard Modbus registers by a subsequent call to readHoldingRegistersTable().
◆ writeEnronRegistersTable()
| virtual int writeEnronRegistersTable |
( |
int |
startRef, |
|
|
const long |
regArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Implement this function only if your slave device has to process register ranges as Daniel/ENRON 32-bit registers.
If a register range is processed as Daniel/ENRON register then this range is not available as normal Holding Register range.
- Note
- Daniel/ENRON is a prorietary 32-bit format which uses a non-standard Modbus frame and not understood by most master devices.
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| regArr | Buffer which contains the received data |
| refCnt | Number of registers received (Range: 0 - 62) |
- Return values
-
| 1 | Indicate that a successful access. The Server Engine will send a positive reply to the master. |
| 0 | Indicate that the requested range is not to be processed using the Daniel/ENRON frame format. A subsequent call to writeHoldingRegistersTable() will be made to process the range in standard Modbus frame format. |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates that the requested register range is processed as standard Modbus registers by a subsequent call to writeHoldingRegistersTable().
◆ readInputRegistersTable()
| virtual int readInputRegistersTable |
( |
int |
startRef, |
|
|
short |
regArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to read Input Registers.
When a slave receives a poll request for the 3:00000 data table it calls this method to retrieve the data.
A simple and very common implementation is to map the Input Registers to the same address space than the Holding Registers table:
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| regArr | Buffer which has to be filled with the reply data |
| refCnt | Number of registers to be retrieved (Range: 0 - 125) |
- Return values
-
| 1 | Indicate a successful access and that valid reply data is contained in regArr. The Server Engine will reply the data passed in regArr to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ readCoilsTable()
| virtual int readCoilsTable |
( |
int |
startRef, |
|
|
char |
bitArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to read Coils.
When a slave receives a poll request for the 0:00000 data table it calls this method to retrieve the data.
A simple implementation which holds the boolean application data in an array of chars (char bitData[2000]) could be:
{
startRef--;
if (startRef + refCnt > (int) sizeof(bitData) / sizeof(char))
return 0;
memcpy(bitArr, &bitData[startRef], refCnt * sizeof(char));
return 1;
}
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| bitArr | Buffer which has to be filled with the reply data. Each char represents one coil! |
| refCnt | Number of coils to be retrieved (Range: 0 - 2000) |
- Return values
-
| 1 | Indicate a successful access and that valid reply data is contained in regArr. The Server Engine will reply the data passed in regArr to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ writeCoilsTable()
| virtual int writeCoilsTable |
( |
int |
startRef, |
|
|
const char |
bitArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to write Coils.
When a slave receives a write request for the 0:00000 data table it calls this method to pass the data to the application.
A simple implementation which holds the boolean application data in an array of chars (char bitData[2000]) could be:
{
startRef--;
if (startRef + refCnt > (int) sizeof(bitData) / sizeof(char))
return 0;
memcpy(&bitData[startRef], bitArr, refCnt * sizeof(char));
return 1;
}
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| bitArr | Buffer which contains the received data. Each char repesents one coil! |
| refCnt | Number of coils received (Range: 0 - 2000) |
- Return values
-
| 1 | Indicate a successful access. The Server Engine will send a positive reply to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ readInputDiscretesTable()
| virtual int readInputDiscretesTable |
( |
int |
startRef, |
|
|
char |
bitArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to read Coils.
When a slave receives a poll request for the 1:00000 data table it calls this method to retrieve the data.
A simple and very common implementation is to map the Input Discretes to the same address space than the Coils table:
- Parameters
-
| startRef | Start register (Range: 1 - 65536) |
| bitArr | Buffer which has to be filled with the reply data. Each char repesents one discrete! |
| refCnt | Number of discretes to be retrieved (Range: 0 - 2000) |
- Return values
-
| 1 | Indicate a successful access and that valid reply data is contained in regArr. The Server Engine will reply the data passed in regArr to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ readFileRecord()
| virtual int readFileRecord |
( |
int |
refType, |
|
|
int |
fileNo, |
|
|
int |
startRef, |
|
|
short |
regArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to read File Records which is Modbus function code 20 (14 hex).
When a slave receives a poll request for function code 20 it calls this method to retrieve the data.
- Parameters
-
| refType | Reference type (typically this is 6) |
| fileNo | File number (typically 0, 1, 3 or 4) |
| startRef | Record Number (equivalent to the start register) |
| regArr | Buffer which has to be filled with the reply data |
| refCnt | Record count (a record is 2 bytes long) |
- Return values
-
| 1 | Indicate a successful access and that valid reply data is contained in regArr. The Server Engine will reply the data passed in regArr to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ writeFileRecord()
| virtual int writeFileRecord |
( |
int |
refType, |
|
|
int |
fileNo, |
|
|
int |
startRef, |
|
|
short |
regArr[], |
|
|
int |
refCnt |
|
) |
| |
|
inlinevirtual |
Override this method to implement a Data Provider function to write File Records which is Modbus function code 21 (15 hex).
When a slave receives a write request for function code 21 it calls this method to pass the data to the application.
- Parameters
-
| refType | Reference type (typically this is 6) |
| fileNo | File number (typically 0, 1, 3 or 4) |
| startRef | Record Number (equivalent to the start register) |
| regArr | Buffer which contains the received data |
| refCnt | Record count received (a record is 2 bytes long) |
- Return values
-
| 1 | Indicate a successful access. The Server Engine will send a positive reply to the master. |
| 0 | Indicate that access has been denied or is out of range. The Server Engine will reply to the master with an exception reply message |
- Required:
- No
- Default Implementation:
- Returns 0 which indicates to Server Engine that this address range is unsupported.
◆ readExceptionStatus()
| virtual char readExceptionStatus |
( |
| ) |
|
|
inlinevirtual |
Override this method to implement a function with reports the eight exception status coils (bits) within the slave device.
The exception status coils are device specific and usually used to report a device' principal status or a device' major failure codes as a 8-bit word.
- Returns
- Exception status byte
- Required:
- No
- Default Implementation:
- Returns 0 as exception status byte.
◆ reportSlaveId()
| virtual int reportSlaveId |
( |
char |
bufferArr[], |
|
|
int |
maxBufSize |
|
) |
| |
|
inlinevirtual |
Override this method to implement a function which reports the Slave ID.
This is called when function code 17 (11 hex) Report Slave ID is sent by a master.
The Slave ID is a device-specific ASCII string which must be copied into the supplied buffer array. The string must NOT be 0 terminated.
A simple implementation could be:
{
strncpy(bufferArr, PRODUCT_NAME, maxBufSize);
return strlen(PRODUCT_NAME);
}
- Returns
- The actual ASCII string length in bytes
- Note
- The Slave ID is not to be mistaken for the Modbus Slave Address. The Slave ID is a string vs the Slave Address is a numeric value and the latter is used by a master device to address a specific device.
- Required:
- No
- Default Implementation:
- Returns 0 which causes a slave failure exception reply
◆ reportRunIndicatorStatus()
| virtual int reportRunIndicatorStatus |
( |
| ) |
|
|
inlinevirtual |
Override this method to implement a function which reports the Run Indicator of a device.
This is called when function code 17 (11 hex) Report Slave ID is sent by a master.
The Run Indicator is one byte which is 0x00 for OFF and 0xFF for ON.
- Returns
- Run Indicator status byte
- Required:
- No
- Default Implementation:
- Returns 0 (OFF) as run indicator status byte.
◆ readDeviceIdentification()
| virtual int readDeviceIdentification |
( |
int |
objId, |
|
|
char |
bufferArr[], |
|
|
int |
maxBufSize |
|
) |
| |
|
inlinevirtual |
Override this method to implement Read Device Identification objects to support Modbus function 43 (hex 2B) subfunction 14 (hex 0E).
This function allows a master to retrieve various objects with meta information about a slave device. The objects are returned as ASCII string. The string must NOT be 0 terminated.
| Object Id | Object Name / Description |
| 0x00 | VendorName |
| 0x01 | ProductCode |
| 0x02 | MajorMinorRevision |
| 0x03 | VendorUrl |
| 0x04 | ProductName |
| 0x05 | ModelName |
| 0x06 | UserApplicationName |
| 0x07 - 0x7F | Reserved |
| 0x80 - 0xFF | Vendor specific private objects |
A simple implementation could be:
{
switch (objId)
{
case 0:
if (bufferArr)
{
strncpy(bufferArr, VENDOR_NAME, maxBufSize);
}
return strlen(VENDOR_NAME);
case 1:
if (bufferArr)
{
strncpy(bufferArr, PRODUCT_CODE, maxBufSize);
}
return strlen(PRODUCT_CODE);
case 4:
if (bufferArr)
{
strncpy(bufferArr, PRODUCT_NAME, maxBufSize);
}
return strlen(PRODUCT_NAME);
}
return 0;
}
- Parameters
-
| objId | ID number (0x00 - 0xFF) |
| bufferArr | 0 for size query otherwise a pointer where to store the requested Device ID string. |
| maxBufSize | Maximum space in the buffer in bytes |
- Returns
- The string length in bytes
- Note
- bufferArr will be 0 during the size query phase and the implementation must return only the object length in that case and not attempt to copy any Device ID string into bufferArr!
- Required:
- No
- Default Implementation:
- Returns 0 which sends an unsupported ID exception reply
◆ timeOutHandler()
| virtual void timeOutHandler |
( |
| ) |
|
|
inlinevirtual |
Override this method to implement a function to handle master poll time-outs.
A master should poll a slave cyclically. If no master is polling within the time-out period this method is called. A slave can take certain actions if the master has lost connection, e.g. go into a fail-safe state.
- Required:
- No
- Default Implementation:
- Empty
◆ getMasterInfo()
Retrieves a MasterInfo object which will hold additional information about the currently processed Modbus request.
This is the protocol type, the slave ID, the IP address and the transaction ID of the current request.
The pointer and data is only valid during the execution of a data table callback method (like readHoldingRegistersTable or writeHoldingRegistersTable)
- Returns
- Pointer to current MasterInfo object
◆ lock()
You can override this method to implement a mutex locking mechanism to synchronise data access.
This is not needed in single threaded applications but may be necessary in multithreaded applications if you are running the server loop in a separate thread and require data consistency over a block of Modbus registers. Data consistency within a single register is always maintained if the code executes on a 16-bit or 32-bit machine, because the CPU is accessing these data types atomically.
This function is called by the server before calling any data read or write functions.
- Required:
- No
- Default Implementation:
- Empty
◆ unlock()
You can override this method to implement a mutex un-locking mechanism to synchronise data access.
This is not needed in single threaded applications but may be necessary in multithreaded applications if you are running the server loop in a separate thread and require data consistency over a block of Modbus registers. Data consistency within a single register is always maintained if the code executes on a 16-bit or 32-bit machine, because the CPU is accessing these data types atomically.
This function is called by the server after calling any data read or write functions.
- Required:
- No
- Default Implementation:
- Empty