FieldTalk Modbus® Slave Library
C++ Editions
FOCUS Software Engineering

Main Page | Modules | Class Hierarchy | Class List | Class Members | Related Pages

Data Provider


Detailed Description

A Data Provider acts as an agent between your Application and the Server Engine.

After instantiating a Server Engine class of any protocol flavour, you have to associate it with a Data Provider by calling addDataTable and passing a pointer to the Data Provider object.

mbusslave_collab.gif

 MbusRtuSlaveProtocol mbusProtocol;
 mbusProtocol.addDataTable(1, &dataTable);

To create an application specific Data Provider derive a new class from MbusDataTableInterface and override the required data access methods.

A minimal Data Provider which realises a Modbus slave with read access to holding registers would be:

class MyDataProvider: public MbusDataTableInterface
{
  public:

   MyDataProvider() {}

   // Override readHoldingRegistersTable method:
   int readHoldingRegistersTable(int startRef, short regArr[], int refCnt)
   {
      ... your application specific implementation
   }
};


Classes

class  MbusDataTableInterface
 This class defines the interface between a Modbus slave Server Engine and your application. Descendants of this class are referred to as Data Providers. 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 MbusDataTableInterface::readHoldingRegistersTable (int startRef, short regArr[], int refCnt)
 Override this method to implement a Data Provider function to read Holding Registers.
virtual int MbusDataTableInterface::writeHoldingRegistersTable (int startRef, const short regArr[], int refCnt)
 Override this method to implement a Data Provider function to write Holding Registers.

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 MbusDataTableInterface::readInputRegistersTable (int startRef, short regArr[], int refCnt)
 Override this method to implement a Data Provider function to read Input Registers.

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 MbusDataTableInterface::readCoilsTable (int startRef, char bitArr[], int refCnt)
 Override this method to implement a Data Provider function to read Coils.
virtual int MbusDataTableInterface::writeCoilsTable (int startRef, const char bitArr[], int refCnt)
 Override this method to implement a Data Provider function to write Coils.

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 MbusDataTableInterface::readInputDiscretesTable (int startRef, char bitArr[], int refCnt)
 Override this method to implement a Data Provider function to read Coils.

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 MbusDataTableInterface::lock ()
 You can override this method to implement a semaphore locking mechanism to synchronise data access.
virtual void MbusDataTableInterface::unlock ()
 You can override this method to implement a semaphore un-locking mechanism to synchronise data access.

Auxiliary Functions

virtual void MbusDataTableInterface::timeOutHandler ()
 Override this method to implement a function to handle master poll time-outs.
virtual char MbusDataTableInterface::readExceptionStatus ()
 Override this method to implement a function with reports the eight exception status coils (bits) within the slave device.

Function Documentation

virtual int readHoldingRegistersTable int  startRef,
short  regArr[],
int  refCnt
[virtual, inherited]
 

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 he 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 - 0x10000)
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.

virtual int readInputRegistersTable int  startRef,
short  regArr[],
int  refCnt
[virtual, inherited]
 

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 he 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 - 0x10000)
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.

virtual int readCoilsTable int  startRef,
char  bitArr[],
int  refCnt
[virtual, inherited]
 

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 he 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 - 0x10000)
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.

virtual int readInputDiscretesTable int  startRef,
char  bitArr[],
int  refCnt
[virtual, inherited]
 

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 he 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 - 0x10000)
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.

virtual void lock  )  [virtual, inherited]
 

You can override this method to implement a semaphore 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

virtual void timeOutHandler  )  [virtual, inherited]
 

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

virtual int writeHoldingRegistersTable int  startRef,
const short  regArr[],
int  refCnt
[virtual, inherited]
 

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 he 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 - 0x10000)
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.

virtual int writeCoilsTable int  startRef,
const char  bitArr[],
int  refCnt
[virtual, inherited]
 

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 he 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 - 0x10000)
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.

virtual void unlock  )  [virtual, inherited]
 

You can override this method to implement a semaphore 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

virtual char readExceptionStatus  )  [virtual, inherited]
 

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.