liblightmodbus  2.0
A lightweight, cross-platform Modbus RTU library
User-defined Modbus functions
Note
This feature requires SLAVE_USER_FUNCTIONS or MASTER_USER_FUNCTIONS module (see Building liblightmodbus).

Liblightmodbus allows user to define his own request/response parsing functions.

Slave's user-defined functions

In order to provide library hint which functions shall be treated differently, user should set up an array of ModbusSlaveUserFunction structures and provide pointer to it in ModbusSlave::userFunctions. The number of user-defined functions in the array should be written to ModbusSlave::userFunctionCount. See the example below:

static ModbusSlaveUserFunction userf[2] =
{
{77, foo},
{16, NULL},
};
slave.userFunctions = userf;

This code causes the library to attempt to parse request 77 with some foo() function and ignore request 16.

Warning
User-defined functions override built-in functions

The user-defined functions must have following form:

ModbusError userfun( ModbusSlave *status, ModbusParser *parser )

The foo function could be defined for example as:

ModbusError foo( ModbusSlave *status, ModbusParser *parser )
{
//Throw exception if slave address is divisible by 2
if ( parser->base.address % 2 == 0 )
return modbusBuildException( status, parser->base.function, MODBUS_EXCEPTION_SLAVE_FAILURE );
//Return empty frame in response
//Assumes static slave response buffer is disabled
status->response.frame = calloc( 16, 1 );
status->response.length = 16;
//Relies on fact that CRC of zeros is 0
//Successful exit
return MODBUS_OK;
}

This function causes slaves with addresses divisible by 2 to return an exception upon receiving a frame with function code 77. The odd-numbered slaves respond with 16 byte frame filled with zeros. This is just a silly example, so please see the real guidelines for used-defined functions below.

User-defined function guidelines

If that's not enough information for you, take a look at some real request parsing functions, for example in src/slave/sregs.c.

Master side user-functions

Setting up user-defined functions on master side is very similar to setting them up on the slave side. By analogy ModbusMaster::userFunctions and ModbusMaster::userFunctionCount need to be set up.

static ModbusMasterUserFunction userf[2] =
{
{77, bar},
{16, NULL},
};
master.userFunctions = userf;
master.userFunctionCount = 2;
Warning
User-defined functions override built-in functions

The parsing function, however, needs to look a bit differently:

ModbusError userf( ModbusMaster *status, ModbusParser *parser, ModbusParser *requestParser )

The difference is the requestParser parameter - it gives you access to the request frame to which response you are parsing.

User-defined function guidelines

Please take a look at src/master/mpregs.c for example parsing functions.