feature add custom fc handlers for master and slave v2

This commit is contained in:
Alex Lisitsyn committed 2025-04-03 18:52:24 +08:00
1 parent 439c767aed
commit 8215e3d0d2
51 files changed
+1345 -300

No files matched your search

@@ -20,7 +20,7 @@
#define MASTER_MAX_CIDS num_device_parameters
// Number of reading of parameters from slave
#define MASTER_MAX_RETRY 30
#define MASTER_MAX_RETRY (10)
// Timeout to update cid over Modbus
#define UPDATE_CIDS_TIMEOUT_MS (500)
@@ -56,7 +56,9 @@
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
#define EACH_ITEM(array, length) \
(typeof(*(array)) *pitem = (array); (pitem < &((array)[length])); pitem++)
(typeof(*(array)) *pitem = (array); (pitem < &((array)[length])); pitem++)
#define MB_CUST_DATA_LEN 100 // The length of custom command buffer
static const char *TAG = "MASTER_TEST";
@@ -217,6 +219,8 @@ const mb_parameter_descriptor_t device_parameters[] = {
// Calculate number of parameters in the table
const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0]));
static char my_custom_data[MB_CUST_DATA_LEN] = {0}; // the custom data buffer
static void *master_handle = NULL;
// The function to get pointer to parameter storage (instance) according to parameter description table
@@ -309,8 +313,24 @@ static void master_operation_func(void *arg)
const mb_parameter_descriptor_t *param_descriptor = NULL;
ESP_LOGI(TAG, "Start modbus test...");
char *pcustom_string = "Master";
mb_param_request_t req = {
.slave_addr = MB_DEVICE_ADDR1, // the slave UID to send the request
.command = 0x41, // the custom function code,
.reg_start = 0, // unused,
.reg_size = (strlen(pcustom_string) >> 1) // length of the data to send (registers)
};
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
// Send the request with custom command (vendor speciic)
// This function supports sending of only even number of bytes
// as instructed by req.reg_size (Modbus register = 2 bytes)
err = mbc_master_send_request(master_handle, &req, pcustom_string);
if (err != ESP_OK) {
ESP_LOGE("CUSTOM_DATA", "Send custom request fail.");
}
#if CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT
// Command - 17 (0x11) Report Slave ID
// The command contains vendor specific data and should be interpreted accordingly.
// This version of command handler needs to define the maximum number
@@ -318,12 +338,10 @@ static void master_operation_func(void *arg)
// The returned slave info data will be stored into the `info_buf`.
// Request fields: slave_addr - the UID of slave, reg_start - not used,
// reg_size = max size of buffer (registers).
mb_param_request_t req = {
.slave_addr = MB_DEVICE_ADDR1, // slave UID to retrieve ID
.command = 0x11, // the <Report Slave ID> command,
.reg_start = 0, // must be zero,
.reg_size = (CONFIG_FMB_CONTROLLER_SLAVE_ID_MAX_SIZE >> 1) // the expected length of buffer in registers
};
req.slave_addr = MB_DEVICE_ADDR1; // slave UID to retrieve ID
req.command = 0x11; // the <Report Slave ID> command,
req.reg_start = 0; // must be zero,
req.reg_size = (CONFIG_FMB_CONTROLLER_SLAVE_ID_MAX_SIZE >> 1); // the expected length of buffer in registers
uint8_t info_buf[CONFIG_FMB_CONTROLLER_SLAVE_ID_MAX_SIZE] = {0}; // The buffer to save slave ID
@@ -467,6 +485,21 @@ static void master_operation_func(void *arg)
ESP_ERROR_CHECK(mbc_master_delete(master_handle));
}
// This is the custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU frame from slave starting from function code,
// plen - the pointer to length of the frame. After return from the handler the modbus object will
// handle the end of transaction according to the exception returned.
mb_exception_t my_custom_handler(void *inst, uint8_t *frame_ptr, uint16_t *plen)
{
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen && *plen < (MB_CUST_DATA_LEN - 1)), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame buffer");
ESP_LOGD(TAG, "Custom handler, Frame ptr: %p, len: %u", frame_ptr, *plen);
strncpy((char *)&my_custom_data[0], (char *)&frame_ptr[1], MB_CUST_DATA_LEN);
ESP_LOG_BUFFER_HEXDUMP("CUSTOM_DATA", &my_custom_data[0], (*plen - 1), ESP_LOG_WARN);
return MB_EX_NONE;
}
// Modbus master initialization
static esp_err_t master_init(void)
{
@@ -492,6 +525,19 @@ static esp_err_t master_init(void)
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mb controller initialization fail, returns(0x%x).", (int)err);
const uint8_t override_command = 0x41;
// Delete the handler for specified command, if available
err = mbc_delete_handler(master_handle, override_command);
MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_INVALID_STATE), ESP_ERR_INVALID_STATE, TAG,
"could not override handler, returned (0x%x).", (int)err);
err = mbc_set_handler(master_handle, override_command, my_custom_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"could not override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(master_handle, override_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_handler), ESP_ERR_INVALID_STATE, TAG,
"could not get handler for command %d, returned (0x%x).", (int)override_command, (int)err);
// Set UART pin numbers
err = uart_set_pin(MB_PORT_NUM, CONFIG_MB_UART_TXD, CONFIG_MB_UART_RXD,
CONFIG_MB_UART_RTS, UART_PIN_NO_CHANGE);
@@ -43,7 +43,8 @@
#define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR \
| MB_EVENT_COILS_WR)
#define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
#define MB_TEST_VALUE 12345.0
#define MB_TEST_VALUE (12345.0)
#define MB_CUST_DATA_MAX_LEN (100)
static const char *TAG = "SLAVE_TEST";
@@ -144,6 +145,24 @@ static void setup_reg_data(void)
input_reg_params.input_data7 = 4.78;
}
// This is a simple custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU request frame from master starting from function code,
// plen - the pointer to length of the frame. The handler body can override the buffer and return the length of data.
// After return from the handler the modbus object will handle the end of transaction according to the exception returned,
// then builds the response frame and send it back to the master. If the whole transaction time including the response
// latency exceeds the configured slave response time set in the master configuration the master will ignore the transaction.
mb_exception_t my_custom_fc_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
{
char *str_append = ":Slave";
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen < (MB_CUST_DATA_MAX_LEN - strlen(str_append))), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame");
frame_ptr[*plen] = '\0';
strcat((char *)&frame_ptr[1], str_append);
*plen = (strlen(str_append) + *plen); // the length of (response + command)
return MB_EX_NONE; // Set the exception code for modbus object appropriately
}
// An example application of Modbus slave. It is based on esp-modbus stack.
// See deviceparams.h file for more information about assigned Modbus parameters.
// These parameters can be accessed from main application and also can be changed
@@ -173,6 +192,19 @@ void app_main(void)
ESP_ERROR_CHECK(mbc_slave_create_serial(&comm_config, &mbc_slave_handle)); // Initialization of Modbus controller
const uint8_t custom_command = 0x41; // The custom command to be sent to slave
// Try to delete the handler for specified command.
esp_err_t err = mbc_delete_handler(mbc_slave_handle, custom_command);
MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_INVALID_STATE), ;, TAG,
"could not delete handler, returned (0x%x).", (int)err);
err = mbc_set_handler(mbc_slave_handle, custom_command, my_custom_fc_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ;, TAG,
"could not set or override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(mbc_slave_handle, custom_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc_handler), ;, TAG,
"could not get handler for command %d, returned (0x%x).", (int)custom_command, (int)err);
// The code below initializes Modbus register area descriptors
// for Modbus Holding Registers, Input Registers, Coils and Discrete Inputs
// Initialization should be done for each supported Modbus register area according to register map.
@@ -243,7 +275,7 @@ void app_main(void)
ESP_ERROR_CHECK(uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));
// Starts of modbus controller and stack
esp_err_t err = mbc_slave_start(mbc_slave_handle);
err = mbc_slave_start(mbc_slave_handle);
#if CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT
// Initialize the new slave identificator structure (example)
+6 -6
View File
@@ -14,8 +14,8 @@ from conftest import ModbusTestDut, Stages
pattern_dict_slave = {Stages.STACK_IPV4: (r'I \([0-9]+\) example_connect: - IPv4 address: ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})'),
Stages.STACK_IPV6: (r'I \([0-9]+\) example_connect: - IPv6 address: (([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})'),
Stages.STACK_INIT: (r'I \(([0-9]+)\) MB_TCP_SLAVE_PORT: (Protocol stack initialized).'),
Stages.STACK_CONNECT: (r'I\s\(([0-9]+)\) MB_TCP_SLAVE_PORT: Socket \(#[0-9]+\), accept client connection from address: '
Stages.STACK_INIT: (r'I \(([0-9]+)\) SLAVE_TEST: (Modbus slave stack initialized)'),
Stages.STACK_CONNECT: (r'I\s\(([0-9]+)\) SLAVE_TEST: Socket \(#[0-9]+\), accept client connection from address: '
r'([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})'),
Stages.STACK_START: (r'I\s\(([0-9]+)\) SLAVE_TEST: (Start modbus test)'),
Stages.STACK_PAR_OK: (r'I\s\(([0-9]+)\) SLAVE_TEST: ([A-Z]+ [A-Z]+) \([a-zA-Z0-9_]+ us\),\s'
@@ -48,16 +48,16 @@ test_configs = [
@pytest.mark.parametrize('config', test_configs, indirect=True)
@pytest.mark.parametrize(
'count, app_path', [
(2, f'{os.path.join(os.path.dirname(__file__), "mb_serial_master")}|{os.path.join(os.path.dirname(__file__), "mb_serial_slave")}')
(2, f'{os.path.join(os.path.dirname(__file__), "mb_serial_slave")}|{os.path.join(os.path.dirname(__file__), "mb_serial_master")}')
],
indirect=True
)
def test_modbus_serial_communication(config: str, dut: Tuple[ModbusTestDut, ModbusTestDut]) -> None:
dut_slave = dut[1]
dut_master = dut[0]
dut_slave = dut[0]
dut_master = dut[1]
logger.info('DUT: %s start.', dut_master.dut_get_name())
logger.info('DUT: %s start.', dut_slave.dut_get_name())
logger.info('DUT: %s start.', dut_master.dut_get_name())
dut_slave.dut_test_start(dictionary=pattern_dict_slave)
dut_master.dut_test_start(dictionary=pattern_dict_master)
+48 -2
View File
@@ -65,6 +65,9 @@
// Options can be used as bit masks or parameter limits
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
#define EACH_ITEM(array, length) \
(typeof(*(array)) *pitem = (array); (pitem < &((array)[length])); pitem++)
#define MB_ID_BYTE0(id) ((uint8_t)(id))
#define MB_ID_BYTE1(id) ((uint8_t)(((uint16_t)(id) >> 8) & 0xFF))
#define MB_ID_BYTE2(id) ((uint8_t)(((uint32_t)(id) >> 16) & 0xFF))
@@ -80,8 +83,7 @@
#define MB_MDNS_INSTANCE(pref) pref"mb_master_tcp"
#define EACH_ITEM(array, length) \
(typeof(*(array)) *pitem = (array); (pitem < &((array)[length])); pitem++)
#define MB_CUST_DATA_LEN 100 // The length of custom command buffer
static const char *TAG = "MASTER_TEST";
@@ -268,6 +270,7 @@ char* slave_ip_address_table[MB_DEVICE_COUNT + 1] = {
};
const size_t ip_table_sz = (size_t)(sizeof(slave_ip_address_table) / sizeof(slave_ip_address_table[0]));
static char my_custom_data[MB_CUST_DATA_LEN] = {0}; // custom data buffer to handle slave response
#if CONFIG_MB_SLAVE_IP_FROM_STDIN
@@ -450,6 +453,20 @@ static void master_operation_func(void *arg)
ESP_LOGI(TAG, "Start modbus test...");
char *pcustom_string = "Master";
mb_param_request_t req = {
.slave_addr = MB_DEVICE_ADDR1, // the slave UID to send the request
.command = 0x41, // the custom function code,
.reg_start = 0, // unused,
.reg_size = (strlen(pcustom_string) >> 1) // length of the data to send (registers)
};
// Send the request with custom command (vendor speciic)
err = mbc_master_send_request(master_handle, &req, pcustom_string);
if (err != ESP_OK) {
ESP_LOGE("CUSTOM_DATA", "Send custom request fail.");
}
for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) {
// Read all found characteristics from slave(s)
for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++) {
@@ -658,6 +675,21 @@ static esp_err_t destroy_services(void)
return err;
}
// This is the custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU frame from slave starting from function code,
// plen - the pointer to length of the frame. After return from the handler the modbus object will
// handle the end of transaction according to the exception returned.
mb_exception_t my_custom_fc_handler(void *inst, uint8_t *frame_ptr, uint16_t *plen)
{
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen && *plen < (MB_CUST_DATA_LEN - 1)), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame buffer");
ESP_LOGI(TAG, "Custom handler, Frame ptr: %p, len: %u", frame_ptr, *plen);
strncpy((char *)&my_custom_data[0], (char *)&frame_ptr[1], MB_CUST_DATA_LEN);
ESP_LOG_BUFFER_HEXDUMP("CUSTOM_DATA", &my_custom_data[0], (*plen - 1), ESP_LOG_INFO);
return MB_EX_NONE;
}
// Modbus master initialization
static esp_err_t master_init(mb_communication_info_t *pcomm_info)
{
@@ -670,6 +702,20 @@ static esp_err_t master_init(mb_communication_info_t *pcomm_info)
"mb controller initialization fail, returns(0x%x).",
(int)err);
// Add custom command handler
uint8_t custom_command = 0x41;
// Delete the handler for specified command, if available
err = mbc_delete_handler(master_handle, custom_command);
MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_INVALID_STATE), ESP_ERR_INVALID_STATE, TAG,
"could not override handler, returned (0x%x).", (int)err);
err = mbc_set_handler(master_handle, custom_command, my_custom_fc_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"could not override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(master_handle, custom_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc_handler), ESP_ERR_INVALID_STATE, TAG,
"could not get handler for command %d, returned (0x%x).", (int)custom_command, (int)err);
err = mbc_master_set_descriptor(master_handle, &device_parameters[0], num_device_parameters);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -13,7 +13,7 @@ CONFIG_FMB_MASTER_DELAY_MS_CONVERT=300
CONFIG_FMB_TCP_UID_ENABLED=n
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
CONFIG_MB_SLAVE_IP_FROM_STDIN=y
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y # intentionally keep it here to change when needed
CONFIG_FMB_EXT_TYPE_SUPPORT=y
CONFIG_EXAMPLE_CONNECT_IPV6=n
+1 -1
View File
@@ -7,7 +7,7 @@ CONFIG_FMB_COMM_MODE_RTU_EN=n
CONFIG_FMB_COMM_MODE_ASCII_EN=n
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=3000
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=300
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y # intentionally keep it here to change when needed
CONFIG_FMB_TCP_UID_ENABLED=n
CONFIG_MB_SLAVE_IP_FROM_STDIN=y
CONFIG_EXAMPLE_CONNECT_IPV6=n
+42 -5
View File
@@ -4,8 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
// FreeModbus Slave Example ESP32
#include <stdio.h>
#include "esp_err.h"
#include "sdkconfig.h"
@@ -43,8 +41,8 @@
#define MB_REG_HOLDING_START_AREA2_SIZE ((size_t)((HOLD_OFFSET(holding_area2_end) - HOLD_OFFSET(holding_u8_a)) << 1))
#define MB_PAR_INFO_GET_TOUT (10) // Timeout for get parameter info
#define MB_CHAN_DATA_MAX_VAL (10)
#define MB_CHAN_DATA_OFFSET (1.1f)
#define MB_CHAN_DATA_MAX_VAL (60)
#define MB_CHAN_DATA_OFFSET (10.1f)
#define MB_READ_MASK (MB_EVENT_INPUT_REG_RD \
| MB_EVENT_HOLDING_REG_RD \
@@ -55,6 +53,7 @@
#define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
#define MB_TEST_VALUE (12345.0)
#define MB_SLAVE_ADDR (CONFIG_MB_SLAVE_ADDR)
#define MB_CUST_DATA_MAX_LEN (100)
static const char *TAG = "SLAVE_TEST";
@@ -266,10 +265,28 @@ static esp_err_t destroy_services(void)
return err;
}
// This is a simple custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU request frame from master starting from function code,
// plen - the pointer to length of the frame. The handler body can override the buffer and return the length of data.
// After return from the handler the modbus object will handle the end of transaction according to the exception returned,
// then builds the response frame and send it back to the master. If the whole transaction time including the response
// latency exceeds the configured slave response time set in the master configuration the master will ignore the transaction.
mb_exception_t my_custom_fc_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
{
char *str_append = ":Slave";
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen < (MB_CUST_DATA_MAX_LEN - strlen(str_append))), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame");
frame_ptr[*plen] = '\0';
strcat((char *)&frame_ptr[1], str_append);
*plen = (strlen(str_append) + *plen); // the length of (response + command)
return MB_EX_NONE; // Set the exception code for modbus object appropriately
}
// Modbus slave initialization
static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
{
mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
mb_register_area_descriptor_t reg_area = {0}; // Modbus register area descriptor structure
// Initialization of Modbus controller
esp_err_t err = mbc_slave_create_tcp(pcomm_info, &slave_handle);
@@ -277,6 +294,19 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
TAG,
"mb controller create fail.");
uint8_t custom_command = 0x41;
// Delete the handler for specified command, if available.
err = mbc_delete_handler(slave_handle, custom_command);
MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_INVALID_STATE), ESP_ERR_INVALID_STATE, TAG,
"could not reset handler, returned (0x%x).", (int)err);
err = mbc_set_handler(slave_handle, custom_command, my_custom_fc_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"could not set or override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(slave_handle, custom_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc_handler), ESP_ERR_INVALID_STATE, TAG,
"could not get handler for command %d, returned (0x%x).", (int)custom_command, (int)err);
// The code below initializes Modbus register area descriptors
// for Modbus Holding Registers, Input Registers, Coils and Discrete Inputs
// Initialization should be done for each supported Modbus register area according to register map.
@@ -287,6 +317,7 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol
reg_area.address = (void*)&holding_reg_params.holding_data0; // Set pointer to storage instance
reg_area.size = (MB_REG_HOLDING_START_AREA1 - MB_REG_HOLDING_START_AREA0) << 1; // Set the size of register storage instance
reg_area.access = MB_ACCESS_RW;
err = mbc_slave_set_descriptor(slave_handle, reg_area);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -297,6 +328,7 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
reg_area.start_offset = MB_REG_HOLDING_START_AREA1; // Offset of register area in Modbus protocol
reg_area.address = (void*)&holding_reg_params.holding_data4; // Set pointer to storage instance
reg_area.size = sizeof(float) << 2; // Set the size of register storage instance
reg_area.access = MB_ACCESS_RW;
err = mbc_slave_set_descriptor(slave_handle, reg_area);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -309,6 +341,7 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
reg_area.start_offset = MB_REG_HOLDING_START_AREA2;
reg_area.address = (void*)&holding_reg_params.holding_u8_a;
reg_area.size = MB_REG_HOLDING_START_AREA2_SIZE;
reg_area.access = MB_ACCESS_RW;
err = mbc_slave_set_descriptor(slave_handle, reg_area);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -321,6 +354,7 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
reg_area.start_offset = MB_REG_INPUT_START_AREA0;
reg_area.address = (void*)&input_reg_params.input_data0;
reg_area.size = sizeof(float) << 2;
reg_area.access = MB_ACCESS_RW;
err = mbc_slave_set_descriptor(slave_handle, reg_area);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -330,6 +364,7 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
reg_area.start_offset = MB_REG_INPUT_START_AREA1;
reg_area.address = (void*)&input_reg_params.input_data4;
reg_area.size = sizeof(float) << 2;
reg_area.access = MB_ACCESS_RW;
err = mbc_slave_set_descriptor(slave_handle, reg_area);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -341,6 +376,7 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
reg_area.start_offset = MB_REG_COILS_START;
reg_area.address = (void*)&coil_reg_params;
reg_area.size = sizeof(coil_reg_params);
reg_area.access = MB_ACCESS_RW;
err = mbc_slave_set_descriptor(slave_handle, reg_area);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -352,6 +388,7 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
reg_area.start_offset = MB_REG_DISCRETE_INPUT_START;
reg_area.address = (void*)&discrete_reg_params;
reg_area.size = sizeof(discrete_reg_params);
reg_area.access = MB_ACCESS_RW;
err = mbc_slave_set_descriptor(slave_handle, reg_area);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
TAG,
@@ -14,7 +14,7 @@ CONFIG_FMB_EXT_TYPE_SUPPORT=y
CONFIG_FMB_TCP_UID_ENABLED=n
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
CONFIG_MB_SLAVE_ADDR=1
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y # intentionally keep it here to change when needed!
CONFIG_EXAMPLE_CONNECT_IPV6=n
CONFIG_EXAMPLE_CONNECT_WIFI=n
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
+1 -1
View File
@@ -8,7 +8,7 @@ CONFIG_FMB_COMM_MODE_ASCII_EN=n
CONFIG_FMB_EXT_TYPE_SUPPORT=y
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=3000
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=300
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y # intentionally keep it here to change when needed!
CONFIG_FMB_TCP_UID_ENABLED=n
CONFIG_MB_SLAVE_ADDR=1
CONFIG_EXAMPLE_CONNECT_IPV6=n
+6 -8
View File
@@ -14,7 +14,7 @@ from conftest import ModbusTestDut, Stages
pattern_dict_slave = {Stages.STACK_IPV4: (r'I \([0-9]+\) example_[a-z]+: - IPv4 address: ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})'),
Stages.STACK_IPV6: (r'I \([0-9]+\) example_[a-z]+: - IPv6 address: (([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})'),
Stages.STACK_INIT: (r'I \(([0-9]+)\) MB_TCP_SLAVE_PORT: (Protocol stack initialized).'),
Stages.STACK_INIT: (r'I \(([0-9]+)\) SLAVE_TEST: (Modbus slave stack initialized)'),
Stages.STACK_CONNECT: (r'I\s\(([0-9]+)\) MB_TCP_SLAVE_PORT: Socket \(#[0-9]+\), accept client connection from address: '
r'([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})'),
Stages.STACK_START: (r'I\s\(([0-9]+)\) SLAVE_TEST: (Start modbus test)'),
@@ -36,11 +36,9 @@ pattern_dict_master = {Stages.STACK_IPV4: (r'I \([0-9]+\) example_[a-z]+: - IPv4
LOG_LEVEL = logging.DEBUG
LOGGER_NAME = 'modbus_test'
CONFORMANCE_TEST_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../tools/robot'))
logger = logging.getLogger(LOGGER_NAME)
test_configs = [
'wifi',
'ethernet'
]
@@ -49,23 +47,23 @@ test_configs = [
@pytest.mark.parametrize('config', test_configs, indirect=True)
@pytest.mark.parametrize(
'count, app_path', [
(2, f'{os.path.join(os.path.dirname(__file__), "mb_tcp_master")}|{os.path.join(os.path.dirname(__file__), "mb_tcp_slave")}')
(2, f'{os.path.join(os.path.dirname(__file__), "mb_tcp_slave")}|{os.path.join(os.path.dirname(__file__), "mb_tcp_master")}')
],
indirect=True
)
def test_modbus_tcp_communication(dut: Tuple[ModbusTestDut, ModbusTestDut]) -> None:
dut_slave = dut[1]
dut_master = dut[0]
dut_slave = dut[0]
dut_master = dut[1]
logger.info('DUT: %s start.', dut_master.dut_get_name())
logger.info('DUT: %s start.', dut_slave.dut_get_name())
logger.info('DUT: %s start.', dut_master.dut_get_name())
dut_slave_ip_address = dut_slave.dut_get_ip()
dut_master.dut_send_ip(dut_slave_ip_address)
dut_slave.dut_test_start(dictionary=pattern_dict_slave)
dut_master.dut_test_start(dictionary=pattern_dict_master)
dut_slave.dut_check_errors()
dut_master.dut_check_errors()