Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User Configuration of Read/Write Commands in Modbus Master (IDFGH-11983) #50

24 changes: 24 additions & 0 deletions freemodbus/common/include/esp_modbus_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,28 @@ typedef enum {
PAR_PERMS_READ_WRITE_TRIGGER = PAR_PERMS_READ_WRITE | PAR_PERMS_TRIGGER, /**< the characteristic of the device are readable & writable & triggerable */
} mb_param_perms_t;

/**
* @brief Modbus Master Read Commands
*/
typedef enum {
CMD_READ_AUTO = 0x00, /**< Signifies that the Command should be determined automatically */
CMD_READ_COILS = 0x01, /**< Command to read On/Off status of coils within the slave */
CMD_READ_DISCRETE_INPUTS = 0x02, /**< Command to read On/Off status of discrete inputs within the slave */
CMD_READ_HOLDING_REGISTERS = 0x03, /**< Command to read the binary contents of holding registers within the slave */
CMD_READ_INPUT_REGISTERS = 0x04, /**< Command to read the binary contents of input registers within the slave */
} mb_read_commands_t;

/**
* @brief Modbus Master Write Command
*/
typedef enum {
CMD_WRITE_AUTO = 0x00, /**< Signifies that the Command should be determined automatically */
CMD_WRITE_SINGLE_COIL = 0x05, /**< Command to set a single coil On/Off */
CMD_WRITE_SINGLE_HOLDING_REGISTER = 0x06, /**< Command to write to a single Holding Register */
CMD_WRITE_MULTIPLE_COILS = 0x0F, /**< Command to set multiple coils in sequence */
CMD_WRITE_MULTIPLE_HOLDING_REGISTERS = 0x10, /**< Command to write multiple holding Registers in sequence */
} mb_write_commands_t;

/**
* @brief Characteristics descriptor type is used to describe characteristic and
* link it with Modbus parameters that reflect its data.
Expand All @@ -92,6 +114,8 @@ typedef struct {
mb_descr_size_t param_size; /*!< Number of bytes in the parameter. */
mb_parameter_opt_t param_opts; /*!< Parameter options used to check limits and etc. */
mb_param_perms_t access; /*!< Access permissions based on mode */
mb_read_commands_t read_command; /*!< Read command to be executed when getting the registers contents */
mb_write_commands_t write_command; /*!< Write command to be executed when setting the register */
} mb_parameter_descriptor_t;

/**
Expand Down
10 changes: 10 additions & 0 deletions freemodbus/serial_master/modbus_controller/mbc_serial_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,11 @@ static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name,

error = mbc_serial_master_set_request(name, MB_PARAM_READ, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid)) {
// Check if there is a specific command configured for reading for this parameter and override the request command
// to the one in the parameter descriptor
if (reg_info.read_command != CMD_READ_AUTO) {
request.command = reg_info.read_command;
}
// Send request to read characteristic data
error = mbc_serial_master_send_request(&request, value_ptr);
if (error == ESP_OK) {
Expand Down Expand Up @@ -424,6 +429,11 @@ static esp_err_t mbc_serial_master_set_parameter(uint16_t cid, char* name,

error = mbc_serial_master_set_request(name, MB_PARAM_WRITE, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid)) {
// Check if there is a specific command configured for writing this parameter and override the request command
// to the one in the parameter descriptor
if (reg_info.write_command != CMD_WRITE_AUTO) {
request.command = reg_info.write_command;
}
// Send request to write characteristic data
error = mbc_serial_master_send_request(&request, value_ptr);
if (error == ESP_OK) {
Expand Down
10 changes: 10 additions & 0 deletions freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,11 @@ static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t*

error = mbc_tcp_master_set_request(name, MB_PARAM_READ, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid)) {
// Check if there is a specific command configured for reading for this parameter and override the request command
// to the one in the parameter descriptor
if (reg_info.read_command != CMD_READ_AUTO) {
request.command = reg_info.read_command;
}
// alloc buffer to store parameter data
pdata = calloc(1, (reg_info.mb_size << 1));
if (!pdata) {
Expand Down Expand Up @@ -536,6 +541,11 @@ static esp_err_t mbc_tcp_master_set_parameter(uint16_t cid, char* name, uint8_t*

error = mbc_tcp_master_set_request(name, MB_PARAM_WRITE, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid)) {
// Check if there is a specific command configured for writing this parameter and override the request command
// to the one in the parameter descriptor
if (reg_info.write_command != CMD_WRITE_AUTO) {
request.command = reg_info.write_command;
}
pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!pdata) {
return ESP_ERR_INVALID_STATE;
Expand Down
22 changes: 11 additions & 11 deletions test/serial/mb_serial_master/main/master.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,27 @@ enum {
// Parameter Options field specifies the options that can be used to process parameter value (limits or masks).
// Access Mode - can be used to implement custom options for processing of characteristic (Read/Write restrictions, factory mode values and etc).
const mb_parameter_descriptor_t device_parameters[] = {
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode, Read Command, Write Command}
{ CID_INP_DATA_0, STR("Data_channel_0"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT, 4, OPTS( -10, 10, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT, 4, OPTS( -10, 10, 1 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_HOLD_DATA_0, STR("Humidity_1"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0, 2,
HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_INP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2, 2,
HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 4, 2,
HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 10, 58,
HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, 116, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, 116, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_RELAY_P1, STR("RelayP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 2, 6,
COIL_OFFSET(coils_port0), PARAM_TYPE_U8, 1, OPTS( 0xAA, 0x15, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
COIL_OFFSET(coils_port0), PARAM_TYPE_U8, 1, OPTS( 0xAA, 0x15, 0 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_RELAY_P2, STR("RelayP2"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 10, 6,
COIL_OFFSET(coils_port1), PARAM_TYPE_U8, 1, OPTS( 0x55, 0x2A, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
COIL_OFFSET(coils_port1), PARAM_TYPE_U8, 1, OPTS( 0x55, 0x2A, 0 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO },
{ CID_DISCR_P1, STR("DiscreteInpP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_DISCRETE, 2, 7,
DISCR_OFFSET(discrete_input_port1), PARAM_TYPE_U8, 1, OPTS( 0xAA, 0x15, 0 ), PAR_PERMS_READ_WRITE_TRIGGER }
DISCR_OFFSET(discrete_input_port1), PARAM_TYPE_U8, 1, OPTS( 0xAA, 0x15, 0 ), PAR_PERMS_READ_WRITE_TRIGGER, CMD_READ_AUTO, CMD_WRITE_AUTO }
};

// Calculate number of parameters in the table
Expand Down