diff --git a/freemodbus/common/include/esp_modbus_master.h b/freemodbus/common/include/esp_modbus_master.h index 7eded34..69502b2 100644 --- a/freemodbus/common/include/esp_modbus_master.h +++ b/freemodbus/common/include/esp_modbus_master.h @@ -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. @@ -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; /** diff --git a/freemodbus/serial_master/modbus_controller/mbc_serial_master.c b/freemodbus/serial_master/modbus_controller/mbc_serial_master.c index f8769a2..f12015f 100644 --- a/freemodbus/serial_master/modbus_controller/mbc_serial_master.c +++ b/freemodbus/serial_master/modbus_controller/mbc_serial_master.c @@ -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, ®_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) { @@ -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, ®_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) { diff --git a/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c b/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c index a04e18b..3bf9afb 100644 --- a/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c +++ b/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c @@ -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, ®_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) { @@ -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, ®_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; diff --git a/test/serial/mb_serial_master/main/master.c b/test/serial/mb_serial_master/main/master.c index 633bf4c..128810f 100644 --- a/test/serial/mb_serial_master/main/master.c +++ b/test/serial/mb_serial_master/main/master.c @@ -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