mirror of
https://github.com/espressif/esp-modbus.git
synced 2025-07-30 18:37:16 +02:00
add custom commands into master data dict v2
This commit is contained in:
@ -73,6 +73,7 @@ enum {
|
||||
CID_HOLD_DATA_1,
|
||||
CID_INP_DATA_2,
|
||||
CID_HOLD_DATA_2,
|
||||
CID_HOLD_CUSTOM1,
|
||||
CID_HOLD_TEST_REG,
|
||||
CID_RELAY_P1,
|
||||
CID_RELAY_P2,
|
||||
@ -133,6 +134,10 @@ const mb_parameter_descriptor_t device_parameters[] = {
|
||||
TEST_HOLD_REG_START(holding_data2), TEST_HOLD_REG_SIZE(holding_data2),
|
||||
HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4,
|
||||
OPTS( TEST_HUMI_MIN, TEST_HUMI_MAX, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||
{ CID_HOLD_CUSTOM1, STR("CustomHoldReg"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
|
||||
TEST_HOLD_REG_START(holding_area1_end), 1,
|
||||
HOLD_OFFSET(holding_area1_end), PARAM_TYPE_U16, 2,
|
||||
OPTS( 0x03, 0x06, 0x5555 ), PAR_PERMS_READ_WRITE_CUST_CMD },
|
||||
{ CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
|
||||
TEST_HOLD_REG_START(test_regs), TEST_ARR_REG_SZ,
|
||||
HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, (TEST_ARR_REG_SZ * 2),
|
||||
@ -320,8 +325,9 @@ static void master_operation_func(void *arg)
|
||||
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
|
||||
void *temp_data_ptr = master_get_param_data(param_descriptor);
|
||||
assert(temp_data_ptr);
|
||||
if ((param_descriptor->param_type == PARAM_TYPE_ASCII) &&
|
||||
(param_descriptor->cid == CID_HOLD_TEST_REG)) {
|
||||
if ((param_descriptor->cid >= CID_HOLD_CUSTOM1)
|
||||
&& (param_descriptor->cid <= CID_HOLD_TEST_REG)) {
|
||||
// Check test parameters
|
||||
if (TEST_VERIFY_VALUES(master_handle, param_descriptor, (uint32_t *)temp_data_ptr) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%" PRIx32 ") read successful.",
|
||||
(int)param_descriptor->cid,
|
||||
|
@ -102,6 +102,7 @@ enum {
|
||||
CID_HOLD_DATA_1,
|
||||
CID_INP_DATA_2,
|
||||
CID_HOLD_DATA_2,
|
||||
CID_HOLD_CUSTOM1,
|
||||
CID_HOLD_TEST_REG,
|
||||
CID_RELAY_P1,
|
||||
CID_RELAY_P2,
|
||||
@ -162,6 +163,10 @@ const mb_parameter_descriptor_t device_parameters[] = {
|
||||
TEST_HOLD_REG_START(holding_data2), TEST_HOLD_REG_SIZE(holding_data2),
|
||||
HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4,
|
||||
OPTS( TEST_HUMI_MIN, TEST_HUMI_MAX, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||
{ CID_HOLD_CUSTOM1, STR("CustomHoldReg"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
|
||||
TEST_HOLD_REG_START(holding_area1_end), 1,
|
||||
HOLD_OFFSET(holding_area1_end), PARAM_TYPE_U16, 2,
|
||||
OPTS( 0x03, 0x06, 0x5555 ), PAR_PERMS_READ_WRITE_CUST_CMD },
|
||||
{ CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
|
||||
TEST_HOLD_REG_START(test_regs), TEST_ARR_REG_SZ,
|
||||
HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, (TEST_ARR_REG_SZ * 2),
|
||||
@ -460,8 +465,9 @@ static void master_operation_func(void *arg)
|
||||
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
|
||||
void *temp_data_ptr = master_get_param_data(param_descriptor);
|
||||
assert(temp_data_ptr);
|
||||
if ((param_descriptor->param_type == PARAM_TYPE_ASCII) &&
|
||||
(param_descriptor->cid == CID_HOLD_TEST_REG)) {
|
||||
if ((param_descriptor->cid >= CID_HOLD_CUSTOM1)
|
||||
&& (param_descriptor->cid <= CID_HOLD_TEST_REG)) {
|
||||
// Check test parameters
|
||||
if (TEST_VERIFY_VALUES(master_handle, param_descriptor, (uint32_t *)temp_data_ptr) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%" PRIx32 ") read successful.",
|
||||
(int)param_descriptor->cid,
|
||||
|
@ -8,6 +8,9 @@
|
||||
#include "mbc_master.h" // for master interface define
|
||||
#include "esp_modbus_master.h" // for public interface defines
|
||||
|
||||
// Helper macro to set custom command
|
||||
#define SET_CMD(mode, rd_cmd, wr_cmd) ((mode == MB_PARAM_WRITE) ? wr_cmd : (mode == MB_PARAM_READ) ? rd_cmd : 0)
|
||||
|
||||
static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_MASTER";
|
||||
|
||||
// This file implements public API for Modbus master controller.
|
||||
@ -714,3 +717,46 @@ esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// Helper function to get configured Modbus command for each type of Modbus register area.
|
||||
// Supports custom command options using the PAR_PERMS_CUST_CMD permission.
|
||||
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *pdescr, mb_param_mode_t mode)
|
||||
{
|
||||
MB_RETURN_ON_FALSE((pdescr), 0, TAG, "incorrect data pointer.");
|
||||
uint8_t command = 0;
|
||||
switch(pdescr->mb_param_type)
|
||||
{
|
||||
case MB_PARAM_HOLDING:
|
||||
if (pdescr->access & PAR_PERMS_CUST_CMD) {
|
||||
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, (uint8_t)pdescr->param_opts.cust_cmd_write);
|
||||
} else {
|
||||
command = SET_CMD(mode, MB_FUNC_READ_HOLDING_REGISTER, MB_FUNC_WRITE_MULTIPLE_REGISTERS);
|
||||
}
|
||||
break;
|
||||
case MB_PARAM_INPUT:
|
||||
if (pdescr->access & PAR_PERMS_CUST_CMD) {
|
||||
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, 0);
|
||||
} else {
|
||||
command = SET_CMD(mode, MB_FUNC_READ_INPUT_REGISTER, 0);
|
||||
}
|
||||
break;
|
||||
case MB_PARAM_COIL:
|
||||
if (pdescr->access & PAR_PERMS_CUST_CMD) {
|
||||
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, (uint8_t)pdescr->param_opts.cust_cmd_write);
|
||||
} else {
|
||||
command = SET_CMD(mode, MB_FUNC_READ_COILS, MB_FUNC_WRITE_MULTIPLE_COILS);
|
||||
}
|
||||
break;
|
||||
case MB_PARAM_DISCRETE:
|
||||
if (pdescr->access & PAR_PERMS_CUST_CMD) {
|
||||
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, 0);
|
||||
} else {
|
||||
command = SET_CMD(mode, MB_FUNC_READ_DISCRETE_INPUTS, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, (unsigned)pdescr->mb_param_type);
|
||||
break;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
@ -45,6 +45,37 @@ extern "C" {
|
||||
#define MB_EACH_ELEM(psrc, pdest, arr_size, elem_size) \
|
||||
(int i = 0; (i < (arr_size / elem_size)); i++, pdest += elem_size, psrc += elem_size)
|
||||
|
||||
/**
|
||||
* @brief Request mode for parameter to use in data dictionary
|
||||
*/
|
||||
typedef enum {
|
||||
MB_PARAM_READ, /*!< Read parameter values. */
|
||||
MB_PARAM_WRITE /*!< Write parameter values. */
|
||||
} mb_param_mode_t;
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Modbus parameter options for description table
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
int opt1; /*!< Parameter option1 */
|
||||
int opt2; /*!< Parameter option2 */
|
||||
int opt3; /*!< Parameter option3 */
|
||||
};
|
||||
struct {
|
||||
int min; /*!< Parameter minimum value */
|
||||
int max; /*!< Parameter maximum value */
|
||||
int step; /*!< Step of parameter change tracking */
|
||||
};
|
||||
struct {
|
||||
int cust_cmd_read; /*!< Parameter custom read request command */
|
||||
int cust_cmd_write; /*!< Parameter custom write request command */
|
||||
int cust_cmd_not_used; /*!< Not used option for custom request */
|
||||
};
|
||||
} mb_parameter_opt_t;
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Modbus descriptor table parameter type defines.
|
||||
*/
|
||||
@ -109,23 +140,6 @@ typedef enum {
|
||||
PARAM_MAX_SIZE
|
||||
} mb_descr_size_t;
|
||||
|
||||
/*!
|
||||
* \brief Modbus parameter options for description table (associated with the characteristic).
|
||||
* and can be used in user application to process data.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
int opt1; /*!< Parameter option1 */
|
||||
int opt2; /*!< Parameter option2 */
|
||||
int opt3; /*!< Parameter option3 */
|
||||
}; /*!< Parameter options version 1 */
|
||||
struct {
|
||||
int min; /*!< Parameter minimum value */
|
||||
int max; /*!< Parameter maximum value */
|
||||
int step; /*!< Step of parameter change tracking */
|
||||
}; /*!< Parameter options version 2 */
|
||||
} mb_parameter_opt_t;
|
||||
|
||||
/**
|
||||
* @brief Permissions for the characteristics
|
||||
*/
|
||||
@ -133,12 +147,15 @@ typedef enum {
|
||||
PAR_PERMS_READ = 1 << BIT0, /**< the characteristic of the device are readable */
|
||||
PAR_PERMS_WRITE = 1 << BIT1, /**< the characteristic of the device are writable*/
|
||||
PAR_PERMS_TRIGGER = 1 << BIT2, /**< the characteristic of the device are triggerable */
|
||||
PAR_PERMS_CUST_CMD = 1 << BIT3, /**< the characteristic uses custom commands */
|
||||
PAR_PERMS_READ_WRITE = PAR_PERMS_READ | PAR_PERMS_WRITE, /**< the characteristic of the device are readable & writable */
|
||||
PAR_PERMS_READ_TRIGGER = PAR_PERMS_READ | PAR_PERMS_TRIGGER, /**< the characteristic of the device are readable & triggerable */
|
||||
PAR_PERMS_WRITE_TRIGGER = PAR_PERMS_WRITE | PAR_PERMS_TRIGGER, /**< the characteristic of the device are writable & triggerable */
|
||||
PAR_PERMS_READ_WRITE_TRIGGER = PAR_PERMS_READ_WRITE | PAR_PERMS_TRIGGER, /**< the characteristic of the device are readable & writable & triggerable */
|
||||
PAR_PERMS_READ_WRITE_CUST_CMD = PAR_PERMS_READ_WRITE | PAR_PERMS_CUST_CMD /**< the characteristic supports custom read/write commands */
|
||||
} mb_param_perms_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Characteristics descriptor type is used to describe characteristic and
|
||||
* link it with Modbus parameters that reflect its data.
|
||||
@ -466,6 +483,18 @@ mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint
|
||||
*/
|
||||
esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param_type, size_t param_size);
|
||||
|
||||
/**
|
||||
* @brief The helper function to get supported modbus function code (command) according to parameter type
|
||||
*
|
||||
* @param[in] pdescr the pointer to the characteristic descriptor in data dictionary
|
||||
* @param[in] mode access mode for characteristic
|
||||
*
|
||||
* @return
|
||||
* - modbus function code, if the command is correctly configured
|
||||
* - 0 - invalid argument or command not found
|
||||
*/
|
||||
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *pdescr, mb_param_mode_t mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -31,14 +31,6 @@ extern "C" {
|
||||
// will be dependent on response time set by timer + convertion time if the command is received
|
||||
#define MB_MAX_RESP_DELAY_MS (3000)
|
||||
|
||||
/**
|
||||
* @brief Request mode for parameter to use in data dictionary
|
||||
*/
|
||||
typedef enum {
|
||||
MB_PARAM_READ, /*!< Read parameter values. */
|
||||
MB_PARAM_WRITE /*!< Write parameter values. */
|
||||
} mb_param_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Modbus controller handler structure
|
||||
*/
|
||||
|
@ -312,40 +312,6 @@ static esp_err_t mbc_serial_master_get_cid_info(void *ctx, uint16_t cid, const m
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Helper function to get modbus command for each type of Modbus register area
|
||||
static uint8_t mbc_serial_master_get_command(mb_param_type_t param_type, mb_param_mode_t mode)
|
||||
{
|
||||
uint8_t command = 0;
|
||||
switch (param_type)
|
||||
{
|
||||
case MB_PARAM_HOLDING:
|
||||
command = (mode == MB_PARAM_WRITE) ? MB_FUNC_WRITE_MULTIPLE_REGISTERS : MB_FUNC_READ_HOLDING_REGISTER;
|
||||
break;
|
||||
case MB_PARAM_INPUT:
|
||||
command = MB_FUNC_READ_INPUT_REGISTER;
|
||||
break;
|
||||
case MB_PARAM_COIL:
|
||||
command = (mode == MB_PARAM_WRITE) ? MB_FUNC_WRITE_MULTIPLE_COILS : MB_FUNC_READ_COILS;
|
||||
break;
|
||||
case MB_PARAM_DISCRETE:
|
||||
if (mode != MB_PARAM_WRITE)
|
||||
{
|
||||
command = MB_FUNC_READ_DISCRETE_INPUTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "%s: Incorrect mode (%u)",
|
||||
__FUNCTION__, (unsigned)mode);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "%s: Incorrect param type (%u)",
|
||||
__FUNCTION__, (unsigned)param_type);
|
||||
break;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
// Helper to search parameter by name in the parameter description table
|
||||
// and fills Modbus request fields accordingly
|
||||
static esp_err_t mbc_serial_master_set_request(void *ctx, uint16_t cid, mb_param_mode_t mode,
|
||||
@ -365,7 +331,7 @@ static esp_err_t mbc_serial_master_set_request(void *ctx, uint16_t cid, mb_param
|
||||
request->slave_addr = reg_ptr->mb_slave_addr;
|
||||
request->reg_start = reg_ptr->mb_reg_start;
|
||||
request->reg_size = reg_ptr->mb_size;
|
||||
request->command = mbc_serial_master_get_command(reg_ptr->mb_param_type, mode);
|
||||
request->command = mbc_master_get_command(reg_ptr, mode);
|
||||
MB_RETURN_ON_FALSE((request->command > 0), ESP_ERR_INVALID_ARG, TAG, "mb incorrect command or parameter type.");
|
||||
if (reg_data)
|
||||
{
|
||||
|
@ -317,41 +317,6 @@ static esp_err_t mbc_tcp_master_get_cid_info(void *ctx, uint16_t cid, const mb_p
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Helper function to get modbus command for each type of Modbus register area
|
||||
static uint8_t mbc_tcp_master_get_command(mb_param_type_t param_type, mb_param_mode_t mode)
|
||||
{
|
||||
uint8_t command = 0;
|
||||
switch(param_type){ // Check commands
|
||||
case MB_PARAM_HOLDING:
|
||||
command = (mode == MB_PARAM_WRITE) ?
|
||||
MB_FUNC_WRITE_MULTIPLE_REGISTERS :
|
||||
MB_FUNC_READ_HOLDING_REGISTER;
|
||||
break;
|
||||
case MB_PARAM_INPUT:
|
||||
command = MB_FUNC_READ_INPUT_REGISTER;
|
||||
break;
|
||||
case MB_PARAM_COIL:
|
||||
command = (mode == MB_PARAM_WRITE) ?
|
||||
MB_FUNC_WRITE_MULTIPLE_COILS :
|
||||
MB_FUNC_READ_COILS;
|
||||
break;
|
||||
case MB_PARAM_DISCRETE:
|
||||
if (mode != MB_PARAM_WRITE) {
|
||||
command = MB_FUNC_READ_DISCRETE_INPUTS;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%s: Incorrect mode (%u)",
|
||||
__FUNCTION__, (unsigned)mode);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "%s: Incorrect param type (%u)",
|
||||
__FUNCTION__, (unsigned)param_type);
|
||||
break;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
// Helper to search parameter in the parameter description table and fills Modbus request fields accordingly
|
||||
static esp_err_t mbc_tcp_master_set_request(void *ctx, uint16_t cid, mb_param_mode_t mode, mb_param_request_t *request,
|
||||
mb_parameter_descriptor_t *reg_data)
|
||||
@ -368,7 +333,7 @@ static esp_err_t mbc_tcp_master_set_request(void *ctx, uint16_t cid, mb_param_mo
|
||||
request->slave_addr = reg_ptr->mb_slave_addr;
|
||||
request->reg_start = reg_ptr->mb_reg_start;
|
||||
request->reg_size = reg_ptr->mb_size;
|
||||
request->command = mbc_tcp_master_get_command(reg_ptr->mb_param_type, mode);
|
||||
request->command = mbc_master_get_command(reg_ptr, mode);
|
||||
MB_RETURN_ON_FALSE((request->command > 0), ESP_ERR_INVALID_ARG, TAG, "mb incorrect command or parameter type.");
|
||||
if (reg_data) {
|
||||
*reg_data = *reg_ptr; // Set the cid registered parameter data
|
||||
|
Reference in New Issue
Block a user