FieldTalk Modbus Slave C++ Library Library version 2.11.0

- Introduction
- Chapters
- Modules
- Classes

- Class List
- Class Hierarchy
- Class Members

List of all members
MbusDataTableInterface Interface Reference
Data Provider

This class defines the interface between a Modbus slave Server Engine and your application. More...

## Data Access Methods for Table 4:00000 (Holding Registers)
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 for Table 3:00000 (Input Registers)
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 for Table 0:00000 (Coils)
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 for Table 1:00000 (Input Discretes)
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...

## Data Access Methods for File Records
- 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...

## Data Access for Status and Diagnostic Information
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...

## Auxiliary Functions
virtual void | timeOutHandler ()
| Override this method to implement a function to handle master poll time-outs. More...
MasterInfo * | getMasterInfo ()
| Retrieves a MasterInfo object which will hold additional information about the currently processed Modbus request. More...

## Data Access Synchronisation Functions
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...

## Detailed Description

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

## Member Function Documentation

## ◆ readHoldingRegistersTable()

virtual int readHoldingRegistersTable | ( | int | startRef,
|  | short | regArr[],
|  | int | refCnt
| ) |  |
| inline virtual

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:

int readHoldingRegistersTable(int startRef, short regArr[], int refCnt)
{
startRef--; // Adjust Modbus reference counting
if (startRef + refCnt > (int) sizeof(regData) / sizeof(short))
return 0;
memcpy(regArr, &regData[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
| ) |  |
| inline virtual

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:

int writeHoldingRegistersTable(int startRef, const short regArr[], int refCnt)
{
startRef--; // Adjust Modbus reference counting
if (startRef + refCnt > (int) sizeof(regData) / sizeof(short))
return 0;
memcpy(&regData[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
| ) |  |
| inline virtual

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
| ) |  |
| inline virtual

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
| ) |  |
| inline virtual

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:

int readInputRegistersTable(int startRef, short regArr[], int refCnt)
{
return readHoldingRegistersTable(startRef, regArr, refCnt);
}

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
| ) |  |
| inline virtual

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:

int readCoilsTable(int startRef, char bitArr[], int refCnt)
{
startRef--; // Adjust Modbus reference counting
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
| ) |  |
| inline virtual

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:

int writeCoilsTable(int startRef, const char bitArr[], int refCnt)
{
startRef--; // Adjust Modbus reference counting
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
| ) |  |
| inline virtual

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:

int readInputDiscretesTable(int startRef, char bitArr[], int refCnt)
{
return readCoilsTable(startRef, bitArr, refCnt);
}

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
| ) |  |
| inline virtual

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
| ) |  |
| inline virtual

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 | ( |  | ) |
| inline virtual

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
| ) |  |
| inline virtual

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:

int reportSlaveId(char bufferArr[], int maxBufSize)
{
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 | ( |  | ) |
| inline virtual

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
| ) |  |
| inline virtual

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:

int readDeviceIdentification(int objId, char bufferArr[], int maxBufSize)
{
switch (objId)
{
case 0: // VendorName
if (bufferArr)
{
strncpy(bufferArr, VENDOR_NAME, maxBufSize);
}
return strlen(VENDOR_NAME);
case 1: // ProductCode
if (bufferArr)
{
strncpy(bufferArr, PRODUCT_CODE, maxBufSize);
}
return strlen(PRODUCT_CODE);
case 4: // ProductName
if (bufferArr)
{
strncpy(bufferArr, PRODUCT_NAME, maxBufSize);
}
return strlen(PRODUCT_NAME);
}
return 0; // Return 0 for object not found
}

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 | ( |  | ) |
| inline virtual

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()

MasterInfo* getMasterInfo | ( |  | ) |
| inline

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()

virtual void lock | ( |  | ) |
| inline virtual

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()

virtual void unlock | ( |  | ) |
| inline virtual

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