diff --git a/components/freemodbus/common/esp_modbus_master.c b/components/freemodbus/common/esp_modbus_master.c index 8ff474b520..e3015818f9 100644 --- a/components/freemodbus/common/esp_modbus_master.c +++ b/components/freemodbus/common/esp_modbus_master.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,8 @@ #include "esp_modbus_master.h" // for public interface defines #include "esp_modbus_callbacks.h" // for callback functions +static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_MASTER"; + // This file implements public API for Modbus master controller. // These functions are wrappers for interface functions of the controller static mb_master_interface_t* master_interface_ptr = NULL; diff --git a/components/freemodbus/common/esp_modbus_slave.c b/components/freemodbus/common/esp_modbus_slave.c index c07a28ae30..ba5c29b70c 100644 --- a/components/freemodbus/common/esp_modbus_slave.c +++ b/components/freemodbus/common/esp_modbus_slave.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,6 +35,7 @@ static uint8_t mb_slave_id[] = { MB_ID_BYTE0(MB_CONTROLLER_SLAVE_ID), // Common interface pointer for slave port static mb_slave_interface_t* slave_interface_ptr = NULL; +static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_SLAVE"; // Searches the register in the area specified by type, returns descriptor if found, else NULL static mb_descr_entry_t* mbc_slave_find_reg_descriptor(mb_param_type_t type, uint16_t addr, size_t regs) @@ -251,11 +252,11 @@ static esp_err_t mbc_slave_send_param_info(mb_event_group_t par_type, uint16_t m par_info.mb_offset = mb_offset; BaseType_t status = xQueueSend(mbs_opts->mbs_notification_queue_handle, &par_info, MB_PAR_INFO_TOUT); if (pdTRUE == status) { - ESP_LOGD(MB_SLAVE_TAG, "Queue send parameter info (type, address, size): %d, 0x%.4x, %d", + ESP_LOGD(TAG, "Queue send parameter info (type, address, size): %d, 0x%.4x, %d", par_type, (uint32_t)par_address, par_size); error = ESP_OK; } else if (errQUEUE_FULL == status) { - ESP_LOGD(MB_SLAVE_TAG, "Parameter queue is overflowed."); + ESP_LOGD(TAG, "Parameter queue is overflowed."); } return error; } @@ -268,7 +269,7 @@ static esp_err_t mbc_slave_send_param_access_notification(mb_event_group_t event esp_err_t err = ESP_FAIL; mb_event_group_t bits = (mb_event_group_t)xEventGroupSetBits(mbs_opts->mbs_event_group, (EventBits_t)event); if (bits & event) { - ESP_LOGD(MB_SLAVE_TAG, "The MB_REG_CHANGE_EVENT = 0x%.2x is set.", (uint8_t)event); + ESP_LOGD(TAG, "The MB_REG_CHANGE_EVENT = 0x%.2x is set.", (uint8_t)event); err = ESP_OK; } return err; diff --git a/components/freemodbus/common/include/esp_modbus_common.h b/components/freemodbus/common/include/esp_modbus_common.h index 9c00d49401..46822b8336 100644 --- a/components/freemodbus/common/include/esp_modbus_common.h +++ b/components/freemodbus/common/include/esp_modbus_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,24 @@ extern "C" { #endif +#if __has_include("esp_check.h") +#include "esp_check.h" + +#define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) ESP_RETURN_ON_FALSE(a, err_code, tag, format __VA_OPT__(,) __VA_ARGS__) + +#else + +// if cannot include esp_check then use custom check macro + +#define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) do { \ + if (!(a)) { \ + MB_LOGE(tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__); \ + return err_code; \ + } \ +} while(0) + +#endif + #define MB_CONTROLLER_STACK_SIZE (CONFIG_FMB_CONTROLLER_STACK_SIZE) // Stack size for Modbus controller #define MB_CONTROLLER_PRIORITY (CONFIG_FMB_PORT_TASK_PRIO - 1) // priority of MB controller task diff --git a/components/freemodbus/common/include/esp_modbus_master.h b/components/freemodbus/common/include/esp_modbus_master.h index 9f4bd4735a..9b874a0b3a 100644 --- a/components/freemodbus/common/include/esp_modbus_master.h +++ b/components/freemodbus/common/include/esp_modbus_master.h @@ -15,6 +15,12 @@ extern "C" { #endif +#define MB_MASTER_CHECK(a, err_code, format, ...) MB_RETURN_ON_FALSE(a, err_code, TAG, format __VA_OPT__(,) __VA_ARGS__) + +#define MB_MASTER_ASSERT(con) do { \ + if (!(con)) { ESP_LOGE(TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ + } while (0) + /*! * \brief Modbus descriptor table parameter type defines. */ diff --git a/components/freemodbus/common/include/esp_modbus_slave.h b/components/freemodbus/common/include/esp_modbus_slave.h index 8e958c4fd9..962dbdaf41 100644 --- a/components/freemodbus/common/include/esp_modbus_slave.h +++ b/components/freemodbus/common/include/esp_modbus_slave.h @@ -18,6 +18,12 @@ extern "C" { #endif +#define MB_SLAVE_CHECK(a, err_code, format, ...) MB_RETURN_ON_FALSE(a, err_code, TAG, format __VA_OPT__(,) __VA_ARGS__) + +#define MB_SLAVE_ASSERT(con) do { \ + if (!(con)) { ESP_LOGE(TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ + } while (0) + /** * @brief Parameter access event information type */ diff --git a/components/freemodbus/common/mbc_master.h b/components/freemodbus/common/mbc_master.h index f0d0d37f11..4ffe4ffcec 100644 --- a/components/freemodbus/common/mbc_master.h +++ b/components/freemodbus/common/mbc_master.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ #ifndef _MB_CONTROLLER_MASTER_H #define _MB_CONTROLLER_MASTER_H +#include // for list #include "freertos/FreeRTOS.h" // for task creation and queue access #include "freertos/task.h" // for task api access #include "freertos/event_groups.h" // for event groups @@ -20,18 +21,6 @@ /* ----------------------- Defines ------------------------------------------*/ -#define MB_MASTER_TAG "MB_CONTROLLER_MASTER" - -#define MB_MASTER_CHECK(a, ret_val, str, ...) \ - if (!(a)) { \ - ESP_LOGE(MB_MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - return (ret_val); \ - } - -#define MB_MASTER_ASSERT(con) do { \ - if (!(con)) { ESP_LOGE(MB_MASTER_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ - } while (0) - /** * @brief Request mode for parameter to use in data dictionary */ @@ -51,6 +40,19 @@ typedef struct { uart_parity_t parity; /*!< Modbus UART parity settings */ } mb_master_comm_info_t; +#if MB_MASTER_TCP_ENABLED +/** + * @brief Modbus slave addr list item for the master + */ +typedef struct mb_slave_addr_entry_s{ + uint16_t index; /*!< Index of the slave address */ + const char* ip_address; /*!< IP address string of the slave */ + uint8_t slave_addr; /*!< Short slave address */ + void* p_data; /*!< pointer to data structure */ + LIST_ENTRY(mb_slave_addr_entry_s) entries; /*!< The slave address entry */ +} mb_slave_addr_entry_t; +#endif + /** * @brief Modbus controller handler structure */ @@ -63,6 +65,10 @@ typedef struct { EventGroupHandle_t mbm_event_group; /*!< Modbus controller event group */ const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */ size_t mbm_param_descriptor_size; /*!< Modbus controller parameter description table size*/ +#if MB_MASTER_TCP_ENABLED + LIST_HEAD(mbm_slave_addr_info_, mb_slave_addr_entry_s) mbm_slave_list; /*!< Slave address information list */ + uint16_t mbm_slave_list_count; +#endif } mb_master_options_t; typedef esp_err_t (*iface_get_cid_info)(uint16_t, const mb_parameter_descriptor_t**); /*!< Interface get_cid_info method */ diff --git a/components/freemodbus/common/mbc_slave.h b/components/freemodbus/common/mbc_slave.h index b7dd4bdc4c..5b54038d1d 100644 --- a/components/freemodbus/common/mbc_slave.h +++ b/components/freemodbus/common/mbc_slave.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,18 +23,6 @@ #define MB_CONTROLLER_NOTIFY_QUEUE_SIZE (CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE) // Number of messages in parameter notification queue #define MB_CONTROLLER_NOTIFY_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT)) // notification timeout -#define MB_SLAVE_TAG "MB_CONTROLLER_SLAVE" - -#define MB_SLAVE_CHECK(a, ret_val, str, ...) \ - if (!(a)) { \ - ESP_LOGE(MB_SLAVE_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - return (ret_val); \ - } - -#define MB_SLAVE_ASSERT(con) do { \ - if (!(con)) { ESP_LOGE(MB_SLAVE_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ - } while (0) - /** * @brief Device communication parameters for master */ diff --git a/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c b/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c index a41e572ccb..3a3f2daa7c 100644 --- a/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c +++ b/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,6 +31,7 @@ extern BOOL xMBMasterPortSerialTxPoll(void); static mb_master_interface_t* mbm_interface_ptr = NULL; //&default_interface_inst; +static const char *TAG = "MB_CONTROLLER_MASTER"; // Modbus event processing task static void modbus_master_task(void *pvParameters) @@ -229,7 +230,7 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi (USHORT)mb_size, (LONG) MB_RESPONSE_TICS ); break; default: - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect function in request (%u) ", + ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", __FUNCTION__, mb_command); mb_error = MB_MRE_NO_REG; break; @@ -260,7 +261,7 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi break; default: - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect return code (%x) ", + ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error); error = ESP_FAIL; break; @@ -315,12 +316,12 @@ static uint8_t mbc_serial_master_get_command(mb_param_type_t param_type, mb_para if (mode != MB_PARAM_WRITE) { command = MB_FUNC_READ_DISCRETE_INPUTS; } else { - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect mode (%u)", + ESP_LOGE(TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode); } break; default: - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u)", + ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type); break; } @@ -392,16 +393,16 @@ static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name, // Send request to read characteristic data error = mbc_serial_master_send_request(&request, value_ptr); if (error == ESP_OK) { - ESP_LOGD(MB_MASTER_TAG, "%s: Good response for get cid(%u) = %s", + ESP_LOGD(TAG, "%s: Good response for get cid(%u) = %s", __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); } else { - ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to get cid(%u) = %s", + ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s", __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); } // Set the type of parameter found in the table *type = reg_info.param_type; } else { - ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", + ESP_LOGE(TAG, "%s: The cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); error = ESP_ERR_INVALID_ARG; } @@ -427,16 +428,16 @@ static esp_err_t mbc_serial_master_set_parameter(uint16_t cid, char* name, // Send request to write characteristic data error = mbc_serial_master_send_request(&request, value_ptr); if (error == ESP_OK) { - ESP_LOGD(MB_MASTER_TAG, "%s: Good response for set cid(%u) = %s", + ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s", __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); } else { - ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to set cid(%u) = %s", + ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s", __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); } // Set the type of parameter found in the table *type = reg_info.param_type; } else { - ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.", + ESP_LOGE(TAG, "%s: The requested cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); error = ESP_ERR_INVALID_ARG; } diff --git a/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c b/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c index 4f3dfaff60..cae13616cd 100644 --- a/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c +++ b/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,7 @@ // Shared pointer to interface structure static mb_slave_interface_t* mbs_interface_ptr = NULL; +static const char *TAG = "MB_CONTROLLER_SLAVE"; // Modbus task function static void modbus_slave_task(void *pvParameters) diff --git a/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c index 132c148f79..6209761f4d 100644 --- a/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c +++ b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include // for calculation of time stamp in milliseconds #include "esp_log.h" // for log_write #include // for memcpy +#include // for list #include "freertos/FreeRTOS.h" // for task creation and queue access #include "freertos/task.h" // for task api access #include "freertos/event_groups.h" // for event groups @@ -33,6 +34,59 @@ #define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000) static mb_master_interface_t* mbm_interface_ptr = NULL; +static const char *TAG = "MB_CONTROLLER_MASTER"; + +// Searches the slave address in the address info list and returns address info if found, else NULL +static mb_slave_addr_entry_t* mbc_tcp_master_find_slave_addr(uint8_t slave_addr) +{ + mb_slave_addr_entry_t* it; + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + + if (LIST_EMPTY(&mbm_opts->mbm_slave_list)) { + return NULL; + } + LIST_FOREACH(it, &mbm_opts->mbm_slave_list, entries) { + if (slave_addr == it->slave_addr) { + return it; + } + } + return NULL; +} + +static esp_err_t mbc_tcp_master_add_slave(uint16_t index, uint8_t slave_addr, const char* ip_addr) +{ + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + // Initialize interface properties + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + + mb_slave_addr_entry_t* new_slave_entry = (mb_slave_addr_entry_t*) heap_caps_malloc(sizeof(mb_slave_addr_entry_t), + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + MB_MASTER_CHECK((new_slave_entry != NULL), ESP_ERR_NO_MEM, "mb can not allocate memory for slave entry."); + new_slave_entry->index = index; + new_slave_entry->ip_address = ip_addr; + new_slave_entry->slave_addr = slave_addr; + new_slave_entry->p_data = NULL; + LIST_INSERT_HEAD(&mbm_opts->mbm_slave_list, new_slave_entry, entries); + MB_MASTER_CHECK((mbm_opts->mbm_slave_list_count < (MB_TCP_PORT_MAX_CONN - 1)), + ESP_ERR_INVALID_STATE, "mb max number of slaves < %d.", MB_TCP_PORT_MAX_CONN); + mbm_opts->mbm_slave_list_count++; + return ESP_OK; +} + +static void mbc_tcp_master_free_slave_list(void) +{ + mb_slave_addr_entry_t* it; + MB_MASTER_ASSERT(mbm_interface_ptr != NULL); + + // Initialize interface properties + mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; + + LIST_FOREACH(it, &mbm_opts->mbm_slave_list, entries) { + LIST_REMOVE(it, entries); + mbm_opts->mbm_slave_list_count--; + free(it); + } +} // Modbus event processing task static void modbus_tcp_master_task(void *pvParameters) @@ -104,21 +158,21 @@ static esp_err_t mbc_tcp_master_start(void) vMBTCPPortMasterSetNetOpt(comm_info->ip_netif_ptr, ip_ver, proto); vMBTCPPortMasterTaskStart(); - // Add slave IP address for each slave to initialise connection - for (int idx = 0; *comm_ip_table != NULL; idx++, comm_ip_table++) - { - result = (BOOL)xMBTCPPortMasterAddSlaveIp(*comm_ip_table); + // Add slave IP address for each slave to initialize connection + mb_slave_addr_entry_t *p_slave_info; + + LIST_FOREACH(p_slave_info, &mbm_opts->mbm_slave_list, entries) { + result = (BOOL)xMBTCPPortMasterAddSlaveIp(p_slave_info->index, p_slave_info->ip_address, p_slave_info->slave_addr); MB_MASTER_CHECK(result, ESP_ERR_INVALID_STATE, "mb stack add slave IP failed: %s.", *comm_ip_table); } - // Init polling event handlers and wait before start polling - xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED, 1); + + // Add end of list condition + (void)xMBTCPPortMasterAddSlaveIp(0xFF, NULL, 0xFF); status = eMBMasterEnable(); MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status); - // Send end of list condition to start connection phase - (void)xMBTCPPortMasterAddSlaveIp(NULL); // Wait for connection done event bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, @@ -143,13 +197,14 @@ static esp_err_t mbc_tcp_master_destroy(void) mb_error = eMBMasterClose(); MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack close failure returned (0x%x).", (uint32_t)mb_error); -// Stop polling by clearing correspondent bit in the event group + // Stop polling by clearing correspondent bit in the event group xEventGroupClearBits(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED); (void)vTaskDelete(mbm_opts->mbm_task_handle); mbm_opts->mbm_task_handle = NULL; (void)vEventGroupDelete(mbm_opts->mbm_event_group); mbm_opts->mbm_event_group = NULL; + mbc_tcp_master_free_slave_list(); free(mbm_interface_ptr); // free the memory allocated for options vMBPortSetMode((UCHAR)MB_PORT_INACTIVE); mbm_interface_ptr = NULL; @@ -169,15 +224,25 @@ static esp_err_t mbc_tcp_master_set_descriptor(const mb_parameter_descriptor_t* MB_MASTER_CHECK((comm_ip_table != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); const mb_parameter_descriptor_t *reg_ptr = descriptor; + uint16_t slave_cnt = 0; + mb_slave_addr_entry_t* p_slave = NULL; + // Go through all items in the table to check all Modbus registers - for (uint16_t counter = 0; counter < (num_elements); counter++, reg_ptr++) + for (int idx = 0; idx < (num_elements); idx++, reg_ptr++) { - MB_MASTER_CHECK((comm_ip_table[reg_ptr->mb_slave_addr - 1] != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); // Below is the code to check consistency of the table format and required fields. - MB_MASTER_CHECK((reg_ptr->cid == counter), ESP_ERR_INVALID_ARG, "cid: %d, mb descriptor cid field is incorrect.", reg_ptr->cid); - MB_MASTER_CHECK((reg_ptr->param_key != NULL), ESP_ERR_INVALID_ARG, "cid: %d, mb descriptor param key is incorrect.", reg_ptr->cid); - MB_MASTER_CHECK((reg_ptr->mb_size > 0), ESP_ERR_INVALID_ARG, "cid: %d, mb descriptor param size is incorrect.", reg_ptr->cid); - MB_MASTER_CHECK(((reg_ptr->mb_size << 1) >= reg_ptr->param_size), ESP_ERR_INVALID_ARG, "cid: %d, mb descriptor param size is incorrect.", reg_ptr->cid); + MB_MASTER_CHECK((reg_ptr->cid == idx), ESP_ERR_INVALID_ARG, "mb descriptor cid field is incorrect."); + MB_MASTER_CHECK((reg_ptr->param_key != NULL), ESP_ERR_INVALID_ARG, "mb descriptor param key is incorrect."); + MB_MASTER_CHECK((reg_ptr->mb_size > 0), ESP_ERR_INVALID_ARG, "mb descriptor param size is incorrect."); + // Is the slave already in the list? + p_slave = mbc_tcp_master_find_slave_addr(reg_ptr->mb_slave_addr); + // Add it to slave list if not there. + if (!p_slave) { + // Is the IP address correctly defined for the slave? + MB_MASTER_CHECK((comm_ip_table[slave_cnt]), ESP_ERR_INVALID_STATE, "mb missing IP address for cid #%d.", reg_ptr->cid); + // Add slave to the list + MB_MASTER_ASSERT(mbc_tcp_master_add_slave(idx, reg_ptr->mb_slave_addr, comm_ip_table[slave_cnt++]) == ESP_OK); + } } mbm_opts->mbm_param_descriptor_table = descriptor; mbm_opts->mbm_param_descriptor_size = num_elements; @@ -249,7 +314,7 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void* (USHORT)mb_size, (LONG) MB_RESPONSE_TIMEOUT ); break; default: - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect function in request (%u) ", + ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", __FUNCTION__, mb_command); mb_error = MB_MRE_NO_REG; break; @@ -280,7 +345,7 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void* break; default: - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error); + ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error); error = ESP_FAIL; break; } @@ -324,11 +389,11 @@ static uint8_t mbc_tcp_master_get_command(mb_param_type_t param_type, mb_param_m if (mode != MB_PARAM_WRITE) { command = MB_FUNC_READ_DISCRETE_INPUTS; } else { - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode); + ESP_LOGE(TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode); } break; default: - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type); + ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type); break; } return command; @@ -359,7 +424,7 @@ static esp_err_t mbc_tcp_master_set_param_data(void* dest, void* src, mb_descr_t memcpy((void*)dest, (void*)src, (size_t)param_size); break; default: - ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u).", + ESP_LOGE(TAG, "%s: Incorrect param type (%u).", __FUNCTION__, (uint16_t)param_type); err = ESP_ERR_NOT_SUPPORTED; break; @@ -431,15 +496,15 @@ static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t* error = mbc_tcp_master_set_param_data((void*)value, (void*)pdata, reg_info.param_type, reg_info.param_size); if (error != ESP_OK) { - ESP_LOGE(MB_MASTER_TAG, "fail to set parameter data."); + ESP_LOGE(TAG, "fail to set parameter data."); error = ESP_ERR_INVALID_STATE; } else { - ESP_LOGD(MB_MASTER_TAG, "%s: Good response for get cid(%u) = %s", + ESP_LOGD(TAG, "%s: Good response for get cid(%u) = %s", __FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error)); } } } else { - ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to get cid(%u) = %s", + ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s", __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); error = ESP_ERR_INVALID_RESPONSE; } @@ -447,7 +512,7 @@ static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t* // Set the type of parameter found in the table *type = reg_info.param_type; } else { - ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", + ESP_LOGE(TAG, "%s: The cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); error = ESP_ERR_INVALID_ARG; } @@ -476,24 +541,24 @@ static esp_err_t mbc_tcp_master_set_parameter(uint16_t cid, char* name, uint8_t* error = mbc_tcp_master_set_param_data((void*)pdata, (void*)value, reg_info.param_type, reg_info.param_size); if (error != ESP_OK) { - ESP_LOGE(MB_MASTER_TAG, "fail to set parameter data."); + ESP_LOGE(TAG, "fail to set parameter data."); free(pdata); return ESP_ERR_INVALID_STATE; } // Send request to write characteristic data error = mbc_tcp_master_send_request(&request, pdata); if (error == ESP_OK) { - ESP_LOGD(MB_MASTER_TAG, "%s: Good response for set cid(%u) = %s", + ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s", __FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error)); } else { - ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to set cid(%u) = %s", + ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s", __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); } free(pdata); // Set the type of parameter found in the table *type = reg_info.param_type; } else { - ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.", + ESP_LOGE(TAG, "%s: The requested cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); error = ESP_ERR_INVALID_ARG; } @@ -721,6 +786,9 @@ esp_err_t mbc_tcp_master_create(void** handler) } MB_MASTER_ASSERT(mbm_opts->mbm_task_handle != NULL); // The task is created but handle is incorrect + LIST_INIT(&mbm_opts->mbm_slave_list); // Init slave address list + mbm_opts->mbm_slave_list_count = 0; + // Initialize public interface methods of the interface mbm_interface_ptr->init = mbc_tcp_master_create; mbm_interface_ptr->destroy = mbc_tcp_master_destroy; diff --git a/components/freemodbus/tcp_master/port/port_tcp_master.c b/components/freemodbus/tcp_master/port/port_tcp_master.c index 11f28ce6d9..14ff0248a3 100644 --- a/components/freemodbus/tcp_master/port/port_tcp_master.c +++ b/components/freemodbus/tcp_master/port/port_tcp_master.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-3-Clause * - * SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD */ /* * FreeModbus Libary: ESP32 TCP Port @@ -60,7 +60,6 @@ #define MB_TCP_CONNECTION_TIMEOUT_MS ( 20 ) // Connection timeout in mS #define MB_TCP_RECONNECT_TIMEOUT ( 5000000 ) // Connection timeout in uS -#define MB_TCP_MASTER_PORT_TAG "MB_TCP_MASTER_PORT" #define MB_EVENT_REQ_DONE_MASK ( EV_MASTER_PROCESS_SUCCESS | \ EV_MASTER_ERROR_RESPOND_TIMEOUT | \ EV_MASTER_ERROR_RECEIVE_DATA | \ @@ -78,6 +77,7 @@ void vMBPortEventClose( void ); /* ----------------------- Static variables ---------------------------------*/ +static const char *TAG = "MB_TCP_MASTER_PORT"; static MbPortConfig_t xMbPortConfig; static EventGroupHandle_t xMasterEventHandle = NULL; static SemaphoreHandle_t xShutdownSemaphore = NULL; @@ -108,7 +108,7 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) xMbPortConfig.pxMbSlaveInfo = calloc(MB_TCP_PORT_MAX_CONN, sizeof(MbSlaveInfo_t*)); if (!xMbPortConfig.pxMbSlaveInfo) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP slave info alloc failure."); + ESP_LOGE(TAG, "TCP slave info alloc failure."); return FALSE; } for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xMbPortConfig.pxMbSlaveInfo[idx] = NULL, idx++); @@ -117,12 +117,13 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) xMbPortConfig.usPort = usTCPPort; xMbPortConfig.usMbSlaveInfoCount = 0; xMbPortConfig.ucCurSlaveIndex = 1; + xMbPortConfig.pxMbSlaveCurrInfo = NULL; - xMbPortConfig.xConnectQueue = xQueueCreate(2, sizeof(CHAR*)); + xMbPortConfig.xConnectQueue = xQueueCreate(2, sizeof(MbSlaveAddrInfo_t)); if (xMbPortConfig.xConnectQueue == 0) { // Queue was not created and must not be used. - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master queue creation failure."); + ESP_LOGE(TAG, "TCP master queue creation failure."); return FALSE; } @@ -136,10 +137,10 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) MB_PORT_TASK_AFFINITY); if (xErr != pdTRUE) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master task creation failure."); + ESP_LOGE(TAG, "TCP master task creation failure."); (void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); } else { - ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "TCP master stack initialized."); + ESP_LOGI(TAG, "TCP master stack initialized."); bOkay = TRUE; } @@ -147,9 +148,30 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) return bOkay; } +static MbSlaveInfo_t* vMBTCPPortMasterFindSlaveInfo(UCHAR ucSlaveAddr) +{ + int xIndex; + BOOL xFound = false; + for (xIndex = 0; xIndex < xMbPortConfig.usMbSlaveInfoCount; xIndex++) { + if (xMbPortConfig.pxMbSlaveInfo[xIndex]->ucSlaveAddr == ucSlaveAddr) { + xMbPortConfig.pxMbSlaveCurrInfo = xMbPortConfig.pxMbSlaveInfo[xIndex]; + xFound = TRUE; + xMbPortConfig.ucCurSlaveIndex = xIndex; + } + } + if (!xFound) { + xMbPortConfig.pxMbSlaveCurrInfo = NULL; + ESP_LOGE(TAG, "Slave info for short address %d not found.", ucSlaveAddr); + } + return xMbPortConfig.pxMbSlaveCurrInfo; +} + static MbSlaveInfo_t* vMBTCPPortMasterGetCurrInfo(void) { - return xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.ucCurSlaveIndex - 1]; + if (!xMbPortConfig.pxMbSlaveCurrInfo) { + ESP_LOGE(TAG, "Incorrect current slave info."); + } + return xMbPortConfig.pxMbSlaveCurrInfo; } // Start Modbus event state machine @@ -160,10 +182,10 @@ static void vMBTCPPortMasterStartPoll(void) EventBits_t xFlags = xEventGroupSetBits(xMasterEventHandle, (EventBits_t)xMasterEvent); if (!(xFlags & xMasterEvent)) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start TCP stack."); + ESP_LOGE(TAG, "Fail to start TCP stack."); } } else { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start polling. Incorrect event handle..."); + ESP_LOGE(TAG, "Fail to start polling. Incorrect event handle..."); } } @@ -175,10 +197,10 @@ static void vMBTCPPortMasterStopPoll(void) EventBits_t xFlags = xEventGroupClearBits(xMasterEventHandle, (EventBits_t)xMasterEvent); if (!(xFlags & xMasterEvent)) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling."); + ESP_LOGE(TAG, "Fail to stop polling."); } } else { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling. Incorrect event handle..."); + ESP_LOGE(TAG, "Fail to stop polling. Incorrect event handle..."); } } @@ -209,11 +231,11 @@ static BOOL xMBTCPPortMasterCloseConnection(MbSlaveInfo_t* pxInfo) return FALSE; } if (pxInfo->xSockId == -1) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Wrong socket info or disconnected socket: %d, skip.", pxInfo->xSockId); + ESP_LOGE(TAG, "Wrong socket info or disconnected socket: %d, skip.", pxInfo->xSockId); return FALSE; } if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Shutdown failed sock %d, errno=%d", pxInfo->xSockId, errno); + ESP_LOGV(TAG, "Shutdown failed sock %d, errno=%d", pxInfo->xSockId, errno); } close(pxInfo->xSockId); pxInfo->xSockId = -1; @@ -283,12 +305,12 @@ static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHOR continue; } else if (errno == ENOTCONN) { // Socket connection closed - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection closed.", + ESP_LOGE(TAG, "Socket(#%d)(%s) connection closed.", pxInfo->xSockId, pxInfo->pcIpAddr); return ERR_CONN; } else { // Other error occurred during receiving - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) receive error, length=%d, errno=%d", + ESP_LOGE(TAG, "Socket(#%d)(%s) receive error, length=%d, errno=%d", pxInfo->xSockId, pxInfo->pcIpAddr, xLength, errno); return -1; } @@ -319,7 +341,7 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) pxInfo->xRcvErr = xRet; return xRet; } else if (xRet != MB_TCP_UID) { - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), Fail to read modbus header. ret=%d", + ESP_LOGD(TAG, "Socket (#%d)(%s), Fail to read modbus header. ret=%d", pxInfo->xSockId, pxInfo->pcIpAddr, xRet); pxInfo->xRcvErr = ERR_VAL; return ERR_VAL; @@ -333,7 +355,7 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) return xRet; } else if (xRet != xLength) { // Received incorrect or fragmented packet. - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) incorrect packet, length=%d, TID=0x%02x, errno=%d(%s)", + ESP_LOGD(TAG, "Socket(#%d)(%s) incorrect packet, length=%d, TID=0x%02x, errno=%d(%s)", pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, usTidRcv, errno, strerror(errno)); pxInfo->xRcvErr = ERR_VAL; @@ -343,13 +365,13 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) // Check transaction identifier field in the incoming packet. if ((pxInfo->usTidCnt - 1) != usTidRcv) { - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), incorrect TID(0x%02x)!=(0x%02x) received, discard data.", + ESP_LOGD(TAG, "Socket (#%d)(%s), incorrect TID(0x%02x)!=(0x%02x) received, discard data.", pxInfo->xSockId, pxInfo->pcIpAddr, usTidRcv, (pxInfo->usTidCnt - 1)); pxInfo->xRcvErr = ERR_BUF; return ERR_BUF; } pxInfo->usRcvPos += xRet + MB_TCP_UID; - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) get data, length=%d, TID=0x%02x, errno=%d(%s)", + ESP_LOGD(TAG, "Socket(#%d)(%s) get data, length=%d, TID=0x%02x, errno=%d(%s)", pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, usTidRcv, errno, strerror(errno)); pxInfo->xRcvErr = ERR_OK; @@ -366,7 +388,7 @@ static err_t xMBTCPPortMasterSetNonBlocking(MbSlaveInfo_t* pxInfo) // Set non blocking attribute for socket ULONG ulFlags = fcntl(pxInfo->xSockId, F_GETFL); if (fcntl(pxInfo->xSockId, F_SETFL, ulFlags | O_NONBLOCK) == -1) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), fcntl() call error=%d", + ESP_LOGE(TAG, "Socket(#%d)(%s), fcntl() call error=%d", pxInfo->xSockId, pxInfo->pcIpAddr, errno); return ERR_WOULDBLOCK; } @@ -399,12 +421,12 @@ static err_t xMBTCPPortMasterCheckAlive(MbSlaveInfo_t* pxInfo, ULONG xTimeoutMs) if (errno == EINPROGRESS) { xErr = ERR_INPROGRESS; } else { - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connection, select write err(errno) = %d(%d)."), + ESP_LOGV(TAG, MB_SLAVE_FMT(" connection, select write err(errno) = %d(%d)."), pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); xErr = ERR_CONN; } } else if (xErr == 0) { - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).", + ESP_LOGV(TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).", pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); return ERR_INPROGRESS; } else { @@ -413,11 +435,11 @@ static err_t xMBTCPPortMasterCheckAlive(MbSlaveInfo_t* pxInfo, ULONG xTimeoutMs) // Check socket error xErr = getsockopt(pxInfo->xSockId, SOL_SOCKET, SO_ERROR, (void*)&xOptErr, (socklen_t*)&ulOptLen); if (xOptErr != 0) { - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), sock error occurred (%d).", + ESP_LOGD(TAG, "Socket(#%d)(%s), sock error occurred (%d).", pxInfo->xSockId, pxInfo->pcIpAddr, xOptErr); return ERR_CONN; } - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), is alive.", + ESP_LOGV(TAG, "Socket(#%d)(%s), is alive.", pxInfo->xSockId, pxInfo->pcIpAddr); return ERR_OK; } @@ -447,7 +469,7 @@ static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAd int xRet = getaddrinfo(pcHostStr, NULL, &xHint, &pxAddrList); if (xRet != 0) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect host name or IP: %s", pcHostStr); + ESP_LOGE(TAG, "Incorrect host name or IP: %s", pcHostStr); return FALSE; } if (pxAddrList->ai_family == AF_INET) { @@ -465,20 +487,24 @@ static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAd if (pxHostAddr) { *pxHostAddr = xTargetAddr; } - ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Host[IP]: \"%s\"[%s]", pxAddrList->ai_canonname, pcStr); + ESP_LOGI(TAG, "Host[IP]: \"%s\"[%s]", pxAddrList->ai_canonname, pcStr); freeaddrinfo(pxAddrList); return TRUE; } -BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr) +BOOL xMBTCPPortMasterAddSlaveIp(const USHORT usIndex, const CHAR* pcIpStr, UCHAR ucSlaveAddress) { BOOL xRes = FALSE; + MbSlaveAddrInfo_t xSlaveAddrInfo = { 0 }; MB_PORT_CHECK(xMbPortConfig.xConnectQueue != NULL, FALSE, "Wrong slave IP address to add."); - if (pcIpStr) { + if (pcIpStr && (usIndex != 0xFF)) { xRes = xMBTCPPortMasterCheckHost(pcIpStr, NULL); } if (xRes || !pcIpStr) { - BaseType_t xStatus = xQueueSend(xMbPortConfig.xConnectQueue, (const void*)&pcIpStr, 100); + xSlaveAddrInfo.pcIPAddr = pcIpStr; + xSlaveAddrInfo.usIndex = usIndex; + xSlaveAddrInfo.ucSlaveAddr = ucSlaveAddress; + BaseType_t xStatus = xQueueSend(xMbPortConfig.xConnectQueue, (void*)&xSlaveAddrInfo, 100); MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "FAIL to add slave IP address: [%s].", pcIpStr); } return xRes; @@ -516,7 +542,7 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) int xRet = getaddrinfo(pxInfo->pcIpAddr, pcStr, &xHint, &pxAddrList); free(pcStr); if (xRet != 0) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Cannot resolve host: %s", pxInfo->pcIpAddr); + ESP_LOGE(TAG, "Cannot resolve host: %s", pxInfo->pcIpAddr); return ERR_CONN; } @@ -539,12 +565,12 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) if (pxInfo->xSockId <= 0) { pxInfo->xSockId = socket(pxCurAddr->ai_family, pxCurAddr->ai_socktype, pxCurAddr->ai_protocol); if (pxInfo->xSockId < 0) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Unable to create socket: #%d, errno %d", pxInfo->xSockId, errno); + ESP_LOGE(TAG, "Unable to create socket: #%d, errno %d", pxInfo->xSockId, errno); xErr = ERR_IF; continue; } } else { - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s) created.", pxInfo->xSockId, cStr); + ESP_LOGV(TAG, "Socket (#%d)(%s) created.", pxInfo->xSockId, cStr); } // Set non blocking attribute for socket @@ -555,7 +581,7 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) xErr = connect(pxInfo->xSockId, (struct sockaddr*)pxCurAddr->ai_addr, pxCurAddr->ai_addrlen); if ((xErr < 0) && (errno == EINPROGRESS || errno == EALREADY)) { // The unblocking connect is pending (check status later) or already connected - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).", + ESP_LOGV(TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).", pxInfo->xSockId, cStr, errno, strerror(errno)); // Set keep alive flag in socket options @@ -568,12 +594,12 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) continue; } else if (xErr != ERR_OK) { // Other error occurred during connection - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" unable to connect, error=%d, errno %d (%s)"), + ESP_LOGV(TAG, MB_SLAVE_FMT(" unable to connect, error=%d, errno %d (%s)"), pxInfo->xIndex, pxInfo->xSockId, cStr, xErr, errno, strerror(errno)); xMBTCPPortMasterCloseConnection(pxInfo); xErr = ERR_CONN; } else { - ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", successfully connected."), + ESP_LOGI(TAG, MB_SLAVE_FMT(", successfully connected."), pxInfo->xIndex, pxInfo->xSockId, cStr); continue; } @@ -615,7 +641,7 @@ static int xMBTCPPortMasterCheckConnState(fd_set* pxFdSet) xErr = xMBTCPPortMasterCheckAlive(pxInfo, 0); if ((xErr < 0) && (((xTime - pxInfo->xRecvTimeStamp) > MB_TCP_RECONNECT_TIMEOUT) || ((xTime - pxInfo->xSendTimeStamp) > MB_TCP_RECONNECT_TIMEOUT))) { - ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", slave is down, off_time[r][w](us) = [%ju][%ju]."), + ESP_LOGI(TAG, MB_SLAVE_FMT(", slave is down, off_time[r][w](us) = [%ju][%ju]."), pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, @@ -637,9 +663,9 @@ static void xMBTCPPortMasterFsmSetError(eMBMasterErrorEventType xErrType, eMBMas static void vMBTCPPortMasterTask(void *pvParameters) { - CHAR* pcAddrStr = NULL; MbSlaveInfo_t* pxInfo; MbSlaveInfo_t* pxCurrInfo; + fd_set xConnSet; fd_set xReadSet; int xMaxSd = 0; @@ -649,51 +675,53 @@ static void vMBTCPPortMasterTask(void *pvParameters) // Register each slave in the connection info structure while (1) { - BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); - xMBTCPPortMasterCheckShutdown(); + MbSlaveAddrInfo_t xSlaveAddrInfo = { 0 }; + BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&xSlaveAddrInfo, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); + xMBTCPPortMasterCheckShutdown(); if (xStatus != pdTRUE) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to register slave IP."); + ESP_LOGE(TAG, "Fail to register slave IP."); } else { - if (pcAddrStr == NULL && xMbPortConfig.usMbSlaveInfoCount) { + if (xSlaveAddrInfo.pcIPAddr == NULL && xMbPortConfig.usMbSlaveInfoCount && xSlaveAddrInfo.usIndex == 0xFF) { break; } if (xMbPortConfig.usMbSlaveInfoCount > MB_TCP_PORT_MAX_CONN) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Exceeds maximum connections limit=%d.", MB_TCP_PORT_MAX_CONN); + ESP_LOGE(TAG, "Exceeds maximum connections limit=%d.", MB_TCP_PORT_MAX_CONN); break; } pxInfo = calloc(1, sizeof(MbSlaveInfo_t)); if (!pxInfo) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), info structure allocation fail.", + ESP_LOGE(TAG, "Slave(#%d), info structure allocation fail.", xMbPortConfig.usMbSlaveInfoCount); free(pxInfo); break; } pxInfo->pucRcvBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); if (!pxInfo->pucRcvBuf) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), receive buffer allocation fail.", + ESP_LOGE(TAG, "Slave(#%d), receive buffer allocation fail.", xMbPortConfig.usMbSlaveInfoCount); free(pxInfo->pucRcvBuf); break; } pxInfo->usRcvPos = 0; - pxInfo->pcIpAddr = pcAddrStr; + pxInfo->pcIpAddr = xSlaveAddrInfo.pcIPAddr; pxInfo->xSockId = -1; pxInfo->xError = -1; pxInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); pxInfo->xMbProto = MB_PROTO_TCP; - pxInfo->xIndex = xMbPortConfig.usMbSlaveInfoCount; + pxInfo->ucSlaveAddr = xSlaveAddrInfo.ucSlaveAddr; + pxInfo->xIndex = xSlaveAddrInfo.usIndex; pxInfo->usTidCnt = (USHORT)(xMbPortConfig.usMbSlaveInfoCount << 8U); // Register slave xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.usMbSlaveInfoCount++] = pxInfo; - ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Add slave IP: %s", pcAddrStr); + ESP_LOGI(TAG, "Add slave IP: %s", xSlaveAddrInfo.pcIPAddr); } } // Main connection cycle while (1) { - ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connecting to slaves..."); + ESP_LOGI(TAG, "Connecting to slaves..."); xTime = xMBTCPGetTimeStamp(); usSlaveConnCnt = 0; CHAR ucDot = '.'; @@ -706,7 +734,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) pxInfo = xMbPortConfig.pxMbSlaveInfo[ucCnt]; // if slave descriptor is NULL then it is end of list or connection closed. if (!pxInfo) { - ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Index: %d is not initialized, skip.", ucCnt); + ESP_LOGV(TAG, "Index: %d is not initialized, skip.", ucCnt); if (xMbPortConfig.usMbSlaveInfoCount) { continue; } @@ -721,12 +749,12 @@ static void vMBTCPPortMasterTask(void *pvParameters) // In case of connection errors remove the socket from set if (FD_ISSET(pxInfo->xSockId, &xConnSet)) { FD_CLR(pxInfo->xSockId, &xConnSet); - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connect failed, error = %d."), + ESP_LOGE(TAG, MB_SLAVE_FMT(" connect failed, error = %d."), pxInfo->xIndex, pxInfo->xSockId, (char*)pxInfo->pcIpAddr, xErr); - if (usSlaveConnCnt) { - usSlaveConnCnt--; - } + if (usSlaveConnCnt) { + usSlaveConnCnt--; + } } break; case ERR_OK: @@ -735,7 +763,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) FD_SET(pxInfo->xSockId, &xConnSet); usSlaveConnCnt++; xMaxSd = (pxInfo->xSockId > xMaxSd) ? pxInfo->xSockId : xMaxSd; - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", connected %d slave(s), error = %d."), + ESP_LOGD(TAG, MB_SLAVE_FMT(", connected %d slave(s), error = %d."), pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, usSlaveConnCnt, xErr); @@ -745,7 +773,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) } break; default: - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", unexpected error = %d."), + ESP_LOGE(TAG, MB_SLAVE_FMT(", unexpected error = %d."), pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xErr); @@ -757,7 +785,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) xMBTCPPortMasterCheckShutdown(); } } - ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connected %d slaves, start polling...", usSlaveConnCnt); + ESP_LOGI(TAG, "Connected %d slaves, start polling...", usSlaveConnCnt); vMBTCPPortMasterStartPoll(); // Send event to start stack @@ -768,26 +796,26 @@ static void vMBTCPPortMasterTask(void *pvParameters) xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_TRANSMIT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); // Synchronize state machine with send packet event if (xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_SENT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS))) { - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "FSM Synchronized with sent event."); + ESP_LOGD(TAG, "FSM Synchronized with sent event."); } // Get slave info for the current slave. pxCurrInfo = vMBTCPPortMasterGetCurrInfo(); if (!pxCurrInfo) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect connection options for slave index: %d.", + ESP_LOGE(TAG, "Incorrect connection options for slave index: %d.", xMbPortConfig.ucCurSlaveIndex); vMBTCPPortMasterStopPoll(); xMBTCPPortMasterCheckShutdown(); break; // incorrect slave descriptor, reconnect. } xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Set select timeout, left time: %ju ms.", + ESP_LOGD(TAG, "Set select timeout, left time: %ju ms.", xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); // Wait respond from current slave during respond timeout int xRes = vMBTCPPortMasterRxCheck(pxCurrInfo->xSockId, &xReadSet, xTime); if (xRes == ERR_TIMEOUT) { // No respond from current slave, process timeout. // Need to drop response later if it is received after timeout. - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Select timeout, left time: %ju ms.", + ESP_LOGD(TAG, "Select timeout, left time: %ju ms.", xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); // Wait completion of last transaction @@ -796,7 +824,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) continue; } else if (xRes < 0) { // Select error (slave connection or r/w failure). - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", socket select error. Slave disconnected?"), + ESP_LOGD(TAG, MB_SLAVE_FMT(", socket select error. Slave disconnected?"), pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); // Wait completion of last transaction @@ -820,19 +848,19 @@ static void vMBTCPPortMasterTask(void *pvParameters) if (xRet > 0) { // Response received correctly, send an event to stack xMBTCPPortMasterFsmSetError(EV_ERROR_INIT, EV_MASTER_FRAME_RECEIVED); - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame received."), + ESP_LOGD(TAG, MB_SLAVE_FMT(", frame received."), pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); } else if ((xRet == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) { // Timeout occurred when receiving frame, process respond timeout - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame read timeout."), + ESP_LOGD(TAG, MB_SLAVE_FMT(", frame read timeout."), pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); } else if (xRet == ERR_BUF) { // After retries a response with incorrect TID received, process failure. xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS); - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame error."), + ESP_LOGD(TAG, MB_SLAVE_FMT(", frame error."), pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); } else { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", critical error=%d."), + ESP_LOGE(TAG, MB_SLAVE_FMT(", critical error=%d."), pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xRet); // Stop polling process vMBTCPPortMasterStopPoll(); @@ -842,14 +870,14 @@ static void vMBTCPPortMasterTask(void *pvParameters) break; } xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Slave #%d, data processing left time %ju [ms].", pxCurrInfo->xIndex, xTime); + ESP_LOGD(TAG, "Slave #%d, data processing left time %ju [ms].", pxCurrInfo->xIndex, xTime); // Wait completion of Modbus frame processing before start of new transaction. if (xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime))) { - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", data processing completed."), + ESP_LOGD(TAG, MB_SLAVE_FMT(", data processing completed."), pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); } xTime = xMBTCPGetTimeStamp() - pxCurrInfo->xSendTimeStamp; - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", processing time[us] = %ju."), + ESP_LOGD(TAG, MB_SLAVE_FMT(", processing time[us] = %ju."), pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xTime); } } @@ -886,7 +914,7 @@ vMBMasterTCPPortClose(void) xShutdownSemaphore = xSemaphoreCreateBinary(); // if no semaphore (alloc issues) or couldn't acquire it, just delete the task if (xShutdownSemaphore == NULL || xSemaphoreTake(xShutdownSemaphore, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)) != pdTRUE) { - ESP_LOGW(MB_TCP_MASTER_PORT_TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task."); + ESP_LOGW(TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task."); vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); } if (xShutdownSemaphore) { @@ -924,13 +952,13 @@ int xMBMasterTCPPortWritePoll(MbSlaveInfo_t* pxInfo, const UCHAR * pucMBTCPFrame int xRes = (int)xMBTCPPortMasterCheckAlive(pxInfo, xTimeout); if ((xRes < 0) && (xRes != ERR_INPROGRESS)) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", is not writable, error: %d, errno %d"), + ESP_LOGE(TAG, MB_SLAVE_FMT(", is not writable, error: %d, errno %d"), pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); return xRes; } xRes = send(pxInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); if (xRes < 0) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data error: %d, errno %d"), + ESP_LOGE(TAG, MB_SLAVE_FMT(", send data error: %d, errno %d"), pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); } return xRes; @@ -940,36 +968,41 @@ BOOL xMBMasterTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) { BOOL bFrameSent = FALSE; - xMbPortConfig.ucCurSlaveIndex = ucMBMasterGetDestAddress(); - MbSlaveInfo_t* pxInfo = vMBTCPPortMasterGetCurrInfo(); + USHORT ucCurSlaveIndex = ucMBMasterGetDestAddress(); + MbSlaveInfo_t* pxInfo = vMBTCPPortMasterFindSlaveInfo(ucCurSlaveIndex); - // If socket active then send data - if (pxInfo->xSockId > -1) { - // Apply TID field to the frame before send - pucMBTCPFrame[MB_TCP_TID] = (UCHAR)(pxInfo->usTidCnt >> 8U); - pucMBTCPFrame[MB_TCP_TID + 1] = (UCHAR)(pxInfo->usTidCnt & 0xFF); - int xRes = xMBMasterTCPPortWritePoll(pxInfo, pucMBTCPFrame, usTCPLength, MB_TCP_SEND_TIMEOUT_MS); - if (xRes < 0) { - ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data failure, err(errno) = %d(%d)."), - pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); - bFrameSent = FALSE; - pxInfo->xError = xRes; - } else { - bFrameSent = TRUE; - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data successful: TID=0x%02x, %d (bytes), errno %d"), - pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usTidCnt, xRes, errno); - pxInfo->xError = 0; - pxInfo->usRcvPos = 0; - if (pxInfo->usTidCnt < (USHRT_MAX - 1)) { - pxInfo->usTidCnt++; - } else { - pxInfo->usTidCnt = (USHORT)(pxInfo->xIndex << 8U); - } - } - pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); - } else { - ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send to died slave, error = %d"), + // If the slave is correct and active then send data + // otherwise treat slave as died and skip + if (pxInfo != NULL) { + if (pxInfo->xSockId < 0) { + ESP_LOGD(TAG, MB_SLAVE_FMT(", send to died slave, error = %d"), pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->xError); + } else { + // Apply TID field to the frame before send + pucMBTCPFrame[MB_TCP_TID] = (UCHAR)(pxInfo->usTidCnt >> 8U); + pucMBTCPFrame[MB_TCP_TID + 1] = (UCHAR)(pxInfo->usTidCnt & 0xFF); + int xRes = xMBMasterTCPPortWritePoll(pxInfo, pucMBTCPFrame, usTCPLength, MB_TCP_SEND_TIMEOUT_MS); + if (xRes < 0) { + ESP_LOGE(TAG, MB_SLAVE_FMT(", send data failure, err(errno) = %d(%d)."), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); + bFrameSent = FALSE; + pxInfo->xError = xRes; + } else { + bFrameSent = TRUE; + ESP_LOGD(TAG, MB_SLAVE_FMT(", send data successful: TID=0x%02x, %d (bytes), errno %d"), + pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usTidCnt, xRes, errno); + pxInfo->xError = 0; + pxInfo->usRcvPos = 0; + if (pxInfo->usTidCnt < (USHRT_MAX - 1)) { + pxInfo->usTidCnt++; + } else { + pxInfo->usTidCnt = (USHORT)(pxInfo->xIndex << 8U); + } + } + pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); + } + } else { + ESP_LOGD(TAG, "Send data to died slave, address = %d", ucCurSlaveIndex); } vMBMasterPortTimersRespondTimeoutEnable(); xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); diff --git a/components/freemodbus/tcp_master/port/port_tcp_master.h b/components/freemodbus/tcp_master/port/port_tcp_master.h index c7f9f28377..2229ddf66e 100644 --- a/components/freemodbus/tcp_master/port/port_tcp_master.h +++ b/components/freemodbus/tcp_master/port/port_tcp_master.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-3-Clause * - * SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD */ /* * FreeModbus Libary: ESP32 TCP Port @@ -67,6 +67,7 @@ typedef struct { int xError; /*!< Socket error */ int xRcvErr; /*!< Socket receive error */ const char* pcIpAddr; /*!< TCP/UDP IP address */ + UCHAR ucSlaveAddr; /*!< Slave short address */ UCHAR* pucRcvBuf; /*!< Receive buffer pointer */ USHORT usRcvPos; /*!< Receive buffer position */ int pcPort; /*!< TCP/UDP port number */ @@ -77,28 +78,37 @@ typedef struct { } MbSlaveInfo_t; typedef struct { - TaskHandle_t xMbTcpTaskHandle; /*!< Master TCP/UDP handling task handle */ - QueueHandle_t xConnectQueue; /*!< Master connection queue */ - USHORT usPort; /*!< Master TCP/UDP port number */ - USHORT usMbSlaveInfoCount; /*!< Master count of connected slaves */ - USHORT ucCurSlaveIndex; /*!< Master current processing slave index */ - eMBPortIpVer eMbIpVer; /*!< Master IP version */ - eMBPortProto eMbProto; /*!< Master protocol type */ - void* pvNetIface; /*!< Master netif interface pointer */ - MbSlaveInfo_t** pxMbSlaveInfo; /*!< Master information structure for each connected slave */ + TaskHandle_t xMbTcpTaskHandle; /*!< Master TCP/UDP handling task handle */ + QueueHandle_t xConnectQueue; /*!< Master connection queue */ + USHORT usPort; /*!< Master TCP/UDP port number */ + USHORT usMbSlaveInfoCount; /*!< Master count of connected slaves */ + USHORT ucCurSlaveIndex; /*!< Master current processing slave index */ + eMBPortIpVer eMbIpVer; /*!< Master IP version */ + eMBPortProto eMbProto; /*!< Master protocol type */ + void* pvNetIface; /*!< Master netif interface pointer */ + MbSlaveInfo_t** pxMbSlaveInfo; /*!< Master information structure for each connected slave */ + MbSlaveInfo_t* pxMbSlaveCurrInfo; /*!< Master current slave information */ } MbPortConfig_t; +typedef struct { + USHORT usIndex; /*!< index of the address info */ + const char* pcIPAddr; /*!< represents the IP address of the slave */ + UCHAR ucSlaveAddr; /*!< slave unit ID (UID) field for MBAP frame */ +} MbSlaveAddrInfo_t; + /* ----------------------- Function prototypes ------------------------------*/ // The functions below are used by Modbus controller interface to configure Modbus port. /** * Registers slave IP address * + * @param usIndex index of element in the configuration * @param pcIpStr IP address to register + * @param ucSlaveAddress slave element index * * @return TRUE if address registered successfully, else FALSE */ -BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr); +BOOL xMBTCPPortMasterAddSlaveIp(const USHORT usIndex, const CHAR* pcIpStr, UCHAR ucSlaveAddress); /** * Keeps FSM event handle and mask then wait for Master stack to start diff --git a/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c index 240a69ff6a..9dbd782e6e 100644 --- a/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c +++ b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ // Shared pointer to interface structure static mb_slave_interface_t* mbs_interface_ptr = NULL; +static const char *TAG = "MB_CONTROLLER_SLAVE"; // Modbus task function static void modbus_tcp_slave_task(void *pvParameters) diff --git a/components/freemodbus/tcp_slave/port/port_tcp_slave.c b/components/freemodbus/tcp_slave/port/port_tcp_slave.c index fe1a27af14..317e2c9334 100644 --- a/components/freemodbus/tcp_slave/port/port_tcp_slave.c +++ b/components/freemodbus/tcp_slave/port/port_tcp_slave.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-3-Clause * - * SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD */ /* * FreeModbus Libary: ESP32 TCP Port @@ -62,13 +62,13 @@ /* ----------------------- Defines -----------------------------------------*/ #define MB_TCP_DISCONNECT_TIMEOUT ( CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000000 ) // disconnect timeout in uS #define MB_TCP_RESP_TIMEOUT_MS ( MB_MASTER_TIMEOUT_MS_RESPOND - 2 ) // slave response time limit -#define MB_TCP_SLAVE_PORT_TAG "MB_TCP_SLAVE_PORT" #define MB_TCP_NET_LISTEN_BACKLOG ( SOMAXCONN ) /* ----------------------- Prototypes ---------------------------------------*/ void vMBPortEventClose( void ); /* ----------------------- Static variables ---------------------------------*/ +static const char *TAG = "MB_TCP_SLAVE_PORT"; static int xListenSock = -1; static SemaphoreHandle_t xShutdownSemaphore = NULL; static MbSlavePortConfig_t xConfig = { 0 }; @@ -131,14 +131,14 @@ xMBTCPPortInit( USHORT usTCPPort ) xConfig.pxMbClientInfo = calloc(MB_TCP_PORT_MAX_CONN + 1, sizeof(MbClientInfo_t*)); if (!xConfig.pxMbClientInfo) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "TCP client info allocation failure."); + ESP_LOGE(TAG, "TCP client info allocation failure."); return FALSE; } for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xConfig.pxMbClientInfo[idx] = NULL, idx++); xConfig.xRespQueueHandle = xMBTCPPortRespQueueCreate(); if (!xConfig.xRespQueueHandle) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response queue allocation failure."); + ESP_LOGE(TAG, "Response queue allocation failure."); return FALSE; } @@ -159,10 +159,10 @@ xMBTCPPortInit( USHORT usTCPPort ) vTaskSuspend(xConfig.xMbTcpTaskHandle); if (xErr != pdTRUE) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Server task creation failure."); + ESP_LOGE(TAG, "Server task creation failure."); vTaskDelete(xConfig.xMbTcpTaskHandle); } else { - ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Protocol stack initialized."); + ESP_LOGI(TAG, "Protocol stack initialized."); bOkay = TRUE; } return bOkay; @@ -197,7 +197,7 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr) // Accept new socket connection if not active xSockId = accept(xListenSockId, (struct sockaddr *)&xSrcAddr, &xSize); if (xSockId < 0) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Unable to accept connection: errno=%d", errno); + ESP_LOGE(TAG, "Unable to accept connection: errno=%d", errno); close(xSockId); } else { // Get the sender's ip address as string @@ -209,7 +209,7 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr) inet6_ntoa_r(((struct sockaddr_in6 *)&xSrcAddr)->sin6_addr, cAddrStr, sizeof(cAddrStr) - 1); } #endif - ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr); + ESP_LOGI(TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr); pcStr = calloc(1, strlen(cAddrStr) + 1); if (pcStr && pcIPAddr) { memcpy(pcStr, cAddrStr, strlen(cAddrStr)); @@ -225,11 +225,11 @@ static BOOL xMBTCPPortCloseConnection(MbClientInfo_t* pxInfo) MB_PORT_CHECK(pxInfo, FALSE, "Client info is NULL."); if (pxInfo->xSockId == -1) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Wrong socket info or disconnected socket: %d.", pxInfo->xSockId); + ESP_LOGE(TAG, "Wrong socket info or disconnected socket: %d.", pxInfo->xSockId); return FALSE; } if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), shutdown failed: errno %d", pxInfo->xSockId, errno); + ESP_LOGE(TAG, "Socket (#%d), shutdown failed: errno %d", pxInfo->xSockId, errno); } close(pxInfo->xSockId); pxInfo->xSockId = -1; @@ -266,7 +266,7 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs) } else if (xRet == 0) { // timeout occurred if ((xStartTimeStamp + xTimeoutMs * 1000) > xMBTCPGetTimeStamp()) { - ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d) Read timeout.", pxClientInfo->xSockId); + ESP_LOGD(TAG, "Socket (#%d) Read timeout.", pxClientInfo->xSockId); xRet = ERR_TIMEOUT; break; } @@ -281,12 +281,12 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs) pxClientInfo->usTCPFrameBytesLeft, MSG_DONTWAIT); if (xLength < 0) { // If an error occurred during receiving - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Receive failed: length=%d, errno=%d", xLength, errno); + ESP_LOGE(TAG, "Receive failed: length=%d, errno=%d", xLength, errno); xRet = (err_t)xLength; break; } else if (xLength == 0) { // Socket connection closed - ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed.", + ESP_LOGD(TAG, "Socket (#%d)(%s), connection closed.", pxClientInfo->xSockId, pxClientInfo->pcIpAddr); xRet = ERR_CLSD; break; @@ -304,14 +304,14 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs) pxClientInfo->usTCPFrameBytesLeft = xLength + MB_TCP_UID - pxClientInfo->usTCPBufPos; } else if (pxClientInfo->usTCPBufPos == (MB_TCP_UID + xLength)) { #if MB_TCP_DEBUG - prvvMBTCPLogFrame(MB_TCP_SLAVE_PORT_TAG, (UCHAR*)&pxClientInfo->pucTCPBuf[0], pxClientInfo->usTCPBufPos); + prvvMBTCPLogFrame(TAG, (UCHAR*)&pxClientInfo->pucTCPBuf[0], pxClientInfo->usTCPBufPos); #endif // Copy TID field from incoming packet pxClientInfo->usTidCnt = MB_TCP_GET_FIELD(pxClientInfo->pucTCPBuf, MB_TCP_TID); xRet = pxClientInfo->usTCPBufPos; break; } else if ((pxClientInfo->usTCPBufPos + xLength) >= MB_TCP_BUF_SIZE) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Incorrect buffer received (%u) bytes.", xLength); + ESP_LOGE(TAG, "Incorrect buffer received (%u) bytes.", xLength); // This should not happen. We can't deal with such a client and // drop the connection for security reasons. xRet = ERR_BUF; @@ -396,7 +396,7 @@ vMBTCPPortBindAddr(const CHAR* pcBindIp) { if (listen(xListenSockFd, MB_TCP_NET_LISTEN_BACKLOG) != 0) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Error occurred during listen: errno=%d", errno); + ESP_LOGE(TAG, "Error occurred during listen: errno=%d", errno); close(xListenSockFd); xListenSockFd = -1; continue; @@ -404,7 +404,7 @@ vMBTCPPortBindAddr(const CHAR* pcBindIp) } // Bind was successful pcStr = (pxCurAddr->ai_canonname == NULL) ? (CHAR*)"\0" : pxCurAddr->ai_canonname; - ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), listener %s on port: %d, errno=%d", + ESP_LOGI(TAG, "Socket (#%d), listener %s on port: %d, errno=%d", xListenSockFd, pcStr, xConfig.usPort, errno); break; } @@ -475,11 +475,11 @@ static void vMBTCPPortServerTask(void *pvParameters) vTaskDelete(NULL); } // error occurred during wait for read - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() errno = %d.", errno); + ESP_LOGE(TAG, "select() errno = %d.", errno); continue; } else if (xErr == 0) { // If timeout happened, something is wrong - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() timeout, errno = %d.", errno); + ESP_LOGE(TAG, "select() timeout, errno = %d.", errno); } // If something happened on the master socket, then its an incoming connection. @@ -495,21 +495,21 @@ static void vMBTCPPortServerTask(void *pvParameters) // if request for new connection but no space left if (pxClientInfo != NULL) { if (xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] == NULL) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection %d, only %d connections supported.", i + 1, MB_TCP_PORT_MAX_CONN); + ESP_LOGE(TAG, "Fail to accept connection %d, only %d connections supported.", i + 1, MB_TCP_PORT_MAX_CONN); } xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] = pxClientInfo; // set last connection info } else { // allocate memory for new client info pxClientInfo = calloc(1, sizeof(MbClientInfo_t)); if (!pxClientInfo) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client info allocation fail."); + ESP_LOGE(TAG, "Client info allocation fail."); vMBTCPPortFreeClientInfo(pxClientInfo); pxClientInfo = NULL; } else { // Accept new client connection pxClientInfo->xSockId = xMBTCPPortAcceptConnection(xListenSock, &pcClientIp); if (pxClientInfo->xSockId < 0) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection for client %d.", (xConfig.usClientCount - 1)); + ESP_LOGE(TAG, "Fail to accept connection for client %d.", (xConfig.usClientCount - 1)); // Accept connection fail, then free client info and continue polling. vMBTCPPortFreeClientInfo(pxClientInfo); pxClientInfo = NULL; @@ -517,7 +517,7 @@ static void vMBTCPPortServerTask(void *pvParameters) } pxClientInfo->pucTCPBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); if (!pxClientInfo->pucTCPBuf) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to allocate buffer for client %d.", (xConfig.usClientCount - 1)); + ESP_LOGE(TAG, "Fail to allocate buffer for client %d.", (xConfig.usClientCount - 1)); vMBTCPPortFreeClientInfo(pxClientInfo); pxClientInfo = NULL; continue; @@ -551,17 +551,17 @@ static void vMBTCPPortServerTask(void *pvParameters) switch(xErr) { case ERR_TIMEOUT: - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), data receive timeout, time[us]: %d, close active connection.", + ESP_LOGE(TAG, "Socket (#%d)(%s), data receive timeout, time[us]: %d, close active connection.", pxClientInfo->xSockId, pxClientInfo->pcIpAddr, (int)(xTimeStamp - pxClientInfo->xRecvTimeStamp)); break; case ERR_CLSD: - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed by peer.", + ESP_LOGE(TAG, "Socket (#%d)(%s), connection closed by peer.", pxClientInfo->xSockId, pxClientInfo->pcIpAddr); break; case ERR_BUF: default: - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), read data error: %d", + ESP_LOGE(TAG, "Socket (#%d)(%s), read data error: %d", pxClientInfo->xSockId, pxClientInfo->pcIpAddr, xErr); break; } @@ -586,26 +586,26 @@ static void vMBTCPPortServerTask(void *pvParameters) // Complete frame received, inform state machine to process frame xMBPortEventPost(EV_FRAME_RECEIVED); - ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), get packet TID=0x%X, %d bytes.", + ESP_LOGD(TAG, "Socket (#%d)(%s), get packet TID=0x%X, %d bytes.", pxClientInfo->xSockId, pxClientInfo->pcIpAddr, pxClientInfo->usTidCnt, xErr); // Wait while response is not processed by stack by timeout UCHAR* pucSentBuffer = vxMBTCPPortRespQueueRecv(xConfig.xRespQueueHandle); if (pucSentBuffer == NULL) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response time exceeds configured %d [ms], ignore packet.", + ESP_LOGE(TAG, "Response time exceeds configured %d [ms], ignore packet.", MB_TCP_RESP_TIMEOUT_MS); } else { USHORT usSentTid = MB_TCP_GET_FIELD(pucSentBuffer, MB_TCP_TID); if (usSentTid != pxClientInfo->usTidCnt) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Sent TID(%x) != Recv TID(%x), ignore packet.", + ESP_LOGE(TAG, "Sent TID(%x) != Recv TID(%x), ignore packet.", usSentTid, pxClientInfo->usTidCnt); } } // Get time stamp of last data update pxClientInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); - ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d), processing time = %d (us).", + ESP_LOGD(TAG, "Client %d, Socket(#%d), processing time = %d (us).", pxClientInfo->xIndex, pxClientInfo->xSockId, (int)(pxClientInfo->xSendTimeStamp - pxClientInfo->xRecvTimeStamp)); } @@ -614,7 +614,7 @@ static void vMBTCPPortServerTask(void *pvParameters) // client is not ready to be read int64_t xTime = xMBTCPGetTimeStamp() - pxClientInfo->xRecvTimeStamp; if (xTime > MB_TCP_DISCONNECT_TIMEOUT) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d) do not answer for %d (us). Drop connection...", + ESP_LOGE(TAG, "Client %d, Socket(#%d) do not answer for %d (us). Drop connection...", pxClientInfo->xIndex, pxClientInfo->xSockId, (int)(xTime)); xMBTCPPortCloseConnection(pxClientInfo); @@ -623,7 +623,7 @@ static void vMBTCPPortServerTask(void *pvParameters) xConfig.pxMbClientInfo[i] = NULL; } } else { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d is disconnected.", i); + ESP_LOGE(TAG, "Client %d is disconnected.", i); } } } // if ((pxClientInfo != NULL) @@ -645,7 +645,7 @@ vMBTCPPortClose( ) vTaskResume(xConfig.xMbTcpTaskHandle); if (xShutdownSemaphore == NULL || // if no semaphore (alloc issues) or couldn't acquire it, just delete the task xSemaphoreTake(xShutdownSemaphore, 2*pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND)) != pdTRUE) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Task couldn't exit gracefully within timeout -> abruptly deleting the task"); + ESP_LOGE(TAG, "Task couldn't exit gracefully within timeout -> abruptly deleting the task"); vTaskDelete(xConfig.xMbTcpTaskHandle); } if (xShutdownSemaphore) { @@ -707,7 +707,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) // Check if socket writable xErr = select(xConfig.pxCurClientInfo->xSockId + 1, NULL, &xWriteSet, &xErrorSet, &xTimeVal); if ((xErr == -1) || FD_ISSET(xConfig.pxCurClientInfo->xSockId, &xErrorSet)) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d) , send select() error = %d.", + ESP_LOGE(TAG, "Socket(#%d) , send select() error = %d.", xConfig.pxCurClientInfo->xSockId, errno); return FALSE; } @@ -719,7 +719,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) // Write message into socket and disable Nagle's algorithm xErr = send(xConfig.pxCurClientInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); if (xErr < 0) { - ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d), fail to send data, errno = %d", + ESP_LOGE(TAG, "Socket(#%d), fail to send data, errno = %d", xConfig.pxCurClientInfo->xSockId, errno); xConfig.pxCurClientInfo->xError = xErr; } else { @@ -727,7 +727,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); } } else { - ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Port is not active. Release lock."); + ESP_LOGD(TAG, "Port is not active. Release lock."); vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); } return bFrameSent; diff --git a/examples/protocols/modbus/serial/mb_master/main/master.c b/examples/protocols/modbus/serial/mb_master/main/master.c index d7a5f0cf71..a8a32efe22 100644 --- a/examples/protocols/modbus/serial/mb_master/main/master.c +++ b/examples/protocols/modbus/serial/mb_master/main/master.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,14 +30,6 @@ #define POLL_TIMEOUT_MS (1) #define POLL_TIMEOUT_TICS (POLL_TIMEOUT_MS / portTICK_RATE_MS) -#define MASTER_TAG "MASTER_TEST" - -#define MASTER_CHECK(a, ret_val, str, ...) \ - if (!(a)) { \ - ESP_LOGE(MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - return (ret_val); \ - } - // The macro to get offset for parameter in the appropriate structure #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) @@ -49,6 +41,8 @@ // 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 } +static const char *TAG = "MASTER_TEST"; + // Enumeration of modbus device addresses accessed by master device enum { MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here) @@ -127,7 +121,7 @@ static void* master_get_param_data(const mb_parameter_descriptor_t* param_descri break; } } else { - ESP_LOGE(MASTER_TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); + ESP_LOGE(TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); assert(instance_ptr != NULL); } return instance_ptr; @@ -141,7 +135,7 @@ static void master_operation_func(void *arg) bool alarm_state = false; const mb_parameter_descriptor_t* param_descriptor = NULL; - ESP_LOGI(MASTER_TAG, "Start modbus test..."); + ESP_LOGI(TAG, "Start modbus test..."); for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) { // Read all found characteristics from slave(s) @@ -161,7 +155,7 @@ static void master_operation_func(void *arg) err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data_ptr, &type); if (err == ESP_OK) { - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, @@ -173,13 +167,13 @@ static void master_operation_func(void *arg) err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data_ptr, &type); if (err == ESP_OK) { - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, *(uint32_t*)temp_data_ptr); } else { - ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", + ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", param_descriptor->cid, (char*)param_descriptor->param_key, (int)err, @@ -187,7 +181,7 @@ static void master_operation_func(void *arg) } } } else { - ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", + ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", param_descriptor->cid, (char*)param_descriptor->param_key, (int)err, @@ -200,7 +194,7 @@ static void master_operation_func(void *arg) *(float*)temp_data_ptr = value; if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) || (param_descriptor->mb_param_type == MB_PARAM_INPUT)) { - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, @@ -214,7 +208,7 @@ static void master_operation_func(void *arg) } else { uint16_t state = *(uint16_t*)temp_data_ptr; const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF"; - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, @@ -226,7 +220,7 @@ static void master_operation_func(void *arg) } } } else { - ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", + ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", param_descriptor->cid, (char*)param_descriptor->param_key, (int)err, @@ -240,13 +234,13 @@ static void master_operation_func(void *arg) } if (alarm_state) { - ESP_LOGI(MASTER_TAG, "Alarm triggered by cid #%d.", + ESP_LOGI(TAG, "Alarm triggered by cid #%d.", param_descriptor->cid); } else { - ESP_LOGE(MASTER_TAG, "Alarm is not triggered after %d retries.", + ESP_LOGE(TAG, "Alarm is not triggered after %d retries.", MASTER_MAX_RETRY); } - ESP_LOGI(MASTER_TAG, "Destroy master..."); + ESP_LOGI(TAG, "Destroy master..."); ESP_ERROR_CHECK(mbc_master_destroy()); } @@ -267,13 +261,13 @@ static esp_err_t master_init(void) void* master_handler = NULL; esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler); - MASTER_CHECK((master_handler != NULL), ESP_ERR_INVALID_STATE, + MB_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, TAG, "mb controller initialization fail."); - MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb controller initialization fail, returns(0x%x).", (uint32_t)err); err = mbc_master_setup((void*)&comm); - MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb controller setup fail, returns(0x%x).", (uint32_t)err); @@ -282,23 +276,23 @@ static esp_err_t master_init(void) CONFIG_MB_UART_RTS, UART_PIN_NO_CHANGE); err = mbc_master_start(); - MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb controller start fail, returns(0x%x).", (uint32_t)err); - MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err); // Set driver mode to Half Duplex err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX); - MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err); vTaskDelay(5); err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters); - MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb controller set descriptor fail, returns(0x%x).", (uint32_t)err); - ESP_LOGI(MASTER_TAG, "Modbus master stack initialized..."); + ESP_LOGI(TAG, "Modbus master stack initialized..."); return err; } diff --git a/examples/protocols/modbus/serial/mb_slave/main/slave.c b/examples/protocols/modbus/serial/mb_slave/main/slave.c index da9c249a00..e300b63fff 100644 --- a/examples/protocols/modbus/serial/mb_slave/main/slave.c +++ b/examples/protocols/modbus/serial/mb_slave/main/slave.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -42,7 +42,7 @@ | MB_EVENT_COILS_WR) #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK) -static const char *SLAVE_TAG = "SLAVE_TEST"; +static const char *TAG = "SLAVE_TEST"; static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED; @@ -94,7 +94,7 @@ void app_main(void) mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure // Set UART log level - esp_log_level_set(SLAVE_TAG, ESP_LOG_INFO); + esp_log_level_set(TAG, ESP_LOG_INFO); void* mbc_slave_handler = NULL; ESP_ERROR_CHECK(mbc_slave_init(MB_PORT_SERIAL_SLAVE, &mbc_slave_handler)); // Initialization of Modbus controller @@ -168,8 +168,8 @@ void app_main(void) // Set UART driver mode to Half Duplex ESP_ERROR_CHECK(uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX)); - ESP_LOGI(SLAVE_TAG, "Modbus slave stack initialized."); - ESP_LOGI(SLAVE_TAG, "Start modbus test..."); + ESP_LOGI(TAG, "Modbus slave stack initialized."); + ESP_LOGI(TAG, "Start modbus test..."); // The cycle below will be terminated when parameter holdingRegParams.dataChan0 // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. @@ -182,7 +182,7 @@ void app_main(void) if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { // Get parameter information from parameter queue ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", rw_str, (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, @@ -200,7 +200,7 @@ void app_main(void) } } else if (event & MB_EVENT_INPUT_REG_RD) { ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, (uint32_t)reg_info.type, @@ -208,7 +208,7 @@ void app_main(void) (uint32_t)reg_info.size); } else if (event & MB_EVENT_DISCRETE_RD) { ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, (uint32_t)reg_info.type, @@ -216,7 +216,7 @@ void app_main(void) (uint32_t)reg_info.size); } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", rw_str, (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, @@ -227,7 +227,7 @@ void app_main(void) } } // Destroy of Modbus controller on alarm - ESP_LOGI(SLAVE_TAG,"Modbus controller destroyed."); + ESP_LOGI(TAG,"Modbus controller destroyed."); vTaskDelay(100); ESP_ERROR_CHECK(mbc_slave_destroy()); } diff --git a/examples/protocols/modbus/tcp/example_test.py b/examples/protocols/modbus/tcp/example_test.py index e075f5600f..46e4f8a68f 100644 --- a/examples/protocols/modbus/tcp/example_test.py +++ b/examples/protocols/modbus/tcp/example_test.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import logging @@ -72,7 +72,7 @@ class DutTestThread(Thread): super(DutTestThread, self).__init__() def __enter__(self): - logger.debug('Restart %s.' % self.tname) + logger.debug('Restart %s.', self.tname) # Reset DUT first self.dut.reset() # Capture output from the DUT @@ -83,7 +83,7 @@ class DutTestThread(Thread): """ The exit method of context manager """ if exc_type is not None or exc_value is not None: - logger.info('Thread %s rised an exception type: %s, value: %s' % (self.tname, str(exc_type), str(exc_value))) + logger.info('Thread %s rised an exception type: %s, value: %s', self.tname, str(exc_type), str(exc_value)) def run(self): """ The function implements thread functionality @@ -98,7 +98,7 @@ class DutTestThread(Thread): # Check DUT exceptions dut_exceptions = self.dut.get_exceptions() if 'Guru Meditation Error:' in dut_exceptions: - raise Exception('%s generated an exception: %s\n' % (str(self.dut), dut_exceptions)) + raise RuntimeError('%s generated an exception(s): %s\n' % (str(self.dut), dut_exceptions)) # Mark thread has run to completion without any exceptions self.data = self.dut.stop_capture_raw_data(capture_id=self.dut.name) @@ -109,15 +109,17 @@ class DutTestThread(Thread): message = r'.*Waiting IP([0-9]{1,2}) from stdin.*' # Read all data from previous restart to get prompt correctly self.dut.read() - result = self.dut.expect(re.compile(message), TEST_EXPECT_STR_TIMEOUT) + result = self.dut.expect(re.compile(message), timeout=TEST_EXPECT_STR_TIMEOUT) if int(result[0]) != index: - raise Exception('Incorrect index of IP=%d for %s\n' % (int(result[0]), str(self.dut))) - message = 'IP%s=%s' % (result[0], self.ip_addr) - self.dut.write(message, '\r\n', False) - logger.debug('Sent message for %s: %s' % (self.tname, message)) + raise RuntimeError('Incorrect index of IP=%s for %s\n' % (result[0], str(self.dut))) + # Use the same slave IP address for all characteristics during the test + self.dut.write('IP0=' + self.ip_addr, '\n', False) + self.dut.write('IP1=' + self.ip_addr, '\n', False) + self.dut.write('IP2=' + self.ip_addr, '\n', False) + logger.debug('Set IP address=%s for %s', self.ip_addr, self.tname) message = r'.*IP\([0-9]+\) = \[([0-9a-zA-Z\.\:]+)\] set from stdin.*' - result = self.dut.expect(re.compile(message), TEST_EXPECT_STR_TIMEOUT) - logger.debug('Thread %s initialized with slave IP (%s).' % (self.tname, result[0])) + result = self.dut.expect(re.compile(message), timeout=TEST_EXPECT_STR_TIMEOUT) + logger.debug('Thread %s initialized with slave IP=%s.', self.tname, self.ip_addr) def test_start(self, timeout_value): """ The method to initialize and handle test stages @@ -125,37 +127,37 @@ class DutTestThread(Thread): def handle_get_ip4(data): """ Handle get_ip v4 """ - logger.debug('%s[STACK_IPV4]: %s' % (self.tname, str(data))) + logger.debug('%s[STACK_IPV4]: %s', self.tname, str(data)) self.test_stage = STACK_IPV4 def handle_get_ip6(data): """ Handle get_ip v6 """ - logger.debug('%s[STACK_IPV6]: %s' % (self.tname, str(data))) + logger.debug('%s[STACK_IPV6]: %s', self.tname, str(data)) self.test_stage = STACK_IPV6 def handle_init(data): """ Handle init """ - logger.debug('%s[STACK_INIT]: %s' % (self.tname, str(data))) + logger.debug('%s[STACK_INIT]: %s', self.tname, str(data)) self.test_stage = STACK_INIT def handle_connect(data): """ Handle connect """ - logger.debug('%s[STACK_CONNECT]: %s' % (self.tname, str(data))) + logger.debug('%s[STACK_CONNECT]: %s', self.tname, str(data)) self.test_stage = STACK_CONNECT def handle_test_start(data): """ Handle connect """ - logger.debug('%s[STACK_START]: %s' % (self.tname, str(data))) + logger.debug('%s[STACK_START]: %s', self.tname, str(data)) self.test_stage = STACK_START def handle_par_ok(data): """ Handle parameter ok """ - logger.debug('%s[READ_PAR_OK]: %s' % (self.tname, str(data))) + logger.debug('%s[READ_PAR_OK]: %s', self.tname, str(data)) if self.test_stage >= STACK_START: self.param_ok_count += 1 self.test_stage = STACK_PAR_OK @@ -163,14 +165,14 @@ class DutTestThread(Thread): def handle_par_fail(data): """ Handle parameter fail """ - logger.debug('%s[READ_PAR_FAIL]: %s' % (self.tname, str(data))) + logger.debug('%s[READ_PAR_FAIL]: %s', self.tname, str(data)) self.param_fail_count += 1 self.test_stage = STACK_PAR_FAIL def handle_destroy(data): """ Handle destroy """ - logger.debug('%s[DESTROY]: %s' % (self.tname, str(data))) + logger.debug('%s[DESTROY]: %s', self.tname, str(data)) self.test_stage = STACK_DESTROY self.test_finish = True @@ -186,7 +188,7 @@ class DutTestThread(Thread): (re.compile(self.expected[STACK_DESTROY]), handle_destroy), timeout=timeout_value) except DUT.ExpectTimeout: - logger.debug('%s, expect timeout on stage #%d (%s seconds)' % (self.tname, self.test_stage, timeout_value)) + logger.debug('%s, expect timeout on stage #%d (%s seconds)', self.tname, self.test_stage, timeout_value) self.test_finish = True @@ -196,10 +198,10 @@ def test_check_mode(dut=None, mode_str=None, value=None): global logger try: opt = dut.app.get_sdkconfig()[mode_str] - logger.debug('%s {%s} = %s.\n' % (str(dut), mode_str, opt)) + logger.debug('%s {%s} = %s.\n', str(dut), mode_str, opt) return value == opt except Exception: - logger.error('ENV_TEST_FAILURE: %s: Cannot find option %s in sdkconfig.' % (str(dut), mode_str)) + logger.error('ENV_TEST_FAILURE: %s: Cannot find option %s in sdkconfig.', str(dut), mode_str) return False @@ -238,7 +240,7 @@ def test_modbus_communication(env, comm_mode): master_name = TEST_MASTER_TCP else: logger.error('ENV_TEST_FAILURE: IP resolver mode do not match in the master and slave implementation.\n') - raise Exception('ENV_TEST_FAILURE: IP resolver mode do not match in the master and slave implementation.\n') + raise RuntimeError('ENV_TEST_FAILURE: IP resolver mode do not match in the master and slave implementation.\n') address = None if test_check_mode(dut_master, 'CONFIG_MB_SLAVE_IP_FROM_STDIN', 'y'): logger.info('ENV_TEST_INFO: Set slave IP address through STDIN.\n') @@ -252,9 +254,9 @@ def test_modbus_communication(env, comm_mode): if address is not None: print('Found IP slave address: %s' % address[0]) else: - raise Exception('ENV_TEST_FAILURE: Slave IP address is not found in the output. Check network settings.\n') + raise RuntimeError('ENV_TEST_FAILURE: Slave IP address is not found in the output. Check network settings.\n') else: - raise Exception('ENV_TEST_FAILURE: Slave IP resolver is not configured correctly.\n') + raise RuntimeError('ENV_TEST_FAILURE: Slave IP resolver is not configured correctly.\n') # Create thread for each dut with DutTestThread(dut=dut_master, name=master_name, ip_addr=address[0], expect=pattern_dict_master) as dut_master_thread: @@ -268,32 +270,32 @@ def test_modbus_communication(env, comm_mode): dut_slave_thread.join(timeout=TEST_THREAD_JOIN_TIMEOUT) dut_master_thread.join(timeout=TEST_THREAD_JOIN_TIMEOUT) - if dut_slave_thread.isAlive(): - logger.error('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % - (dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) - raise Exception('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % - (dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) + if dut_slave_thread.is_alive(): + logger.error('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n', + dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT) + raise RuntimeError('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % + (dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) - if dut_master_thread.isAlive(): - logger.error('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % - (dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) - raise Exception('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % - (dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) + if dut_master_thread.is_alive(): + logger.error('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n', + dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT) + raise RuntimeError('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % + (dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) - logger.info('TEST_INFO: %s error count = %d, %s error count = %d.\n' % - (dut_master_thread.tname, dut_master_thread.param_fail_count, - dut_slave_thread.tname, dut_slave_thread.param_fail_count)) - logger.info('TEST_INFO: %s ok count = %d, %s ok count = %d.\n' % - (dut_master_thread.tname, dut_master_thread.param_ok_count, - dut_slave_thread.tname, dut_slave_thread.param_ok_count)) + logger.info('TEST_INFO: %s error count = %d, %s error count = %d.\n', + dut_master_thread.tname, dut_master_thread.param_fail_count, + dut_slave_thread.tname, dut_slave_thread.param_fail_count) + logger.info('TEST_INFO: %s ok count = %d, %s ok count = %d.\n', + dut_master_thread.tname, dut_master_thread.param_ok_count, + dut_slave_thread.tname, dut_slave_thread.param_ok_count) if ((dut_master_thread.param_fail_count > TEST_READ_MAX_ERR_COUNT) or (dut_slave_thread.param_fail_count > TEST_READ_MAX_ERR_COUNT) or (dut_slave_thread.param_ok_count == 0) or (dut_master_thread.param_ok_count == 0)): - raise Exception('TEST_FAILURE: %s parameter read error(ok) count = %d(%d), %s parameter read error(ok) count = %d(%d).\n' % - (dut_master_thread.tname, dut_master_thread.param_fail_count, dut_master_thread.param_ok_count, - dut_slave_thread.tname, dut_slave_thread.param_fail_count, dut_slave_thread.param_ok_count)) + raise RuntimeError('TEST_FAILURE: %s parameter read error(ok) count = %d(%d), %s parameter read error(ok) count = %d(%d).\n' % + (dut_master_thread.tname, dut_master_thread.param_fail_count, dut_master_thread.param_ok_count, + dut_slave_thread.tname, dut_slave_thread.param_fail_count, dut_slave_thread.param_ok_count)) logger.info('TEST_SUCCESS: The Modbus parameter test is completed successfully.\n') finally: diff --git a/examples/protocols/modbus/tcp/mb_tcp_master/main/tcp_master.c b/examples/protocols/modbus/tcp/mb_tcp_master/main/tcp_master.c index 688acf6260..a9c858f949 100644 --- a/examples/protocols/modbus/tcp/mb_tcp_master/main/tcp_master.c +++ b/examples/protocols/modbus/tcp/mb_tcp_master/main/tcp_master.c @@ -1,14 +1,14 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ // FreeModbus Master Example ESP32 -#include "string.h" +#include +#include #include "esp_log.h" -#include "esp_check.h" #include "esp_system.h" #include "esp_wifi.h" #include "esp_event.h" @@ -39,8 +39,6 @@ #define POLL_TIMEOUT_TICS (POLL_TIMEOUT_MS / portTICK_RATE_MS) #define MB_MDNS_PORT (502) -#define MASTER_TAG "MASTER_TEST" - // The macro to get offset for parameter in the appropriate structure #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) @@ -65,12 +63,14 @@ #endif #define MB_MDNS_INSTANCE(pref) pref"mb_master_tcp" +static const char *TAG = "MASTER_TEST"; // Enumeration of modbus device addresses accessed by master device // Each address in the table is a index of TCP slave ip address in mb_communication_info_t::tcp_ip_addr table enum { MB_DEVICE_ADDR1 = 1, // Slave address 1 - MB_DEVICE_COUNT + MB_DEVICE_ADDR2 = 200, + MB_DEVICE_ADDR3 = 35 }; // Enumeration of all supported CIDs for device (used in parameter definition table) @@ -104,11 +104,11 @@ const mb_parameter_descriptor_t device_parameters[] = { HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, { 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 }, - { CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2, 2, + { CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR2, MB_PARAM_HOLDING, 2, 2, HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, - { CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2, + { CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 4, 2, INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, - { CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 4, 2, + { CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR3, MB_PARAM_HOLDING, 4, 2, HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, { CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 8, 100, HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, 200, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, @@ -119,20 +119,26 @@ 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])); +const uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0])); // This table represents slave IP addresses that correspond to the short address field of the slave in device_parameters structure // Modbus TCP stack shall use these addresses to be able to connect and read parameters from slave -char* slave_ip_address_table[MB_DEVICE_COUNT] = { +char* slave_ip_address_table[] = { #if CONFIG_MB_SLAVE_IP_FROM_STDIN "FROM_STDIN", // Address corresponds to MB_DEVICE_ADDR1 and set to predefined value by user - NULL + "FROM_STDIN", // Corresponds to characteristic MB_DEVICE_ADDR2 + "FROM_STDIN", // Corresponds to characteristic MB_DEVICE_ADDR3 + NULL // End of table condition (must be included) #elif CONFIG_MB_MDNS_IP_RESOLVER + NULL, + NULL, NULL, NULL #endif }; +const size_t ip_table_sz = (size_t)(sizeof(slave_ip_address_table) / sizeof(slave_ip_address_table[0])); + #if CONFIG_MB_SLAVE_IP_FROM_STDIN // Scan IP address according to IPV settings @@ -183,8 +189,8 @@ static int master_get_slave_ip_stdin(char** addr_table) fputc('\n', stdout); ip_str = master_scan_addr(&index, buf); if (ip_str != NULL) { - ESP_LOGI(MASTER_TAG, "IP(%d) = [%s] set from stdin.", ip_cnt, ip_str); - if ((ip_cnt >= MB_DEVICE_COUNT) || (index != ip_cnt)) { + ESP_LOGI(TAG, "IP(%d) = [%s] set from stdin.", ip_cnt, ip_str); + if ((ip_cnt >= ip_table_sz) || (index != ip_cnt)) { addr_table[ip_cnt] = NULL; break; } @@ -196,10 +202,10 @@ static int master_get_slave_ip_stdin(char** addr_table) } } else { if (addr_table[ip_cnt]) { - ESP_LOGI(MASTER_TAG, "Leave IP(%d) = [%s] set manually.", ip_cnt, addr_table[ip_cnt]); + ESP_LOGI(TAG, "Leave IP(%d) = [%s] set manually.", ip_cnt, addr_table[ip_cnt]); ip_cnt++; } else { - ESP_LOGI(MASTER_TAG, "IP(%d) is not set in the table.", ip_cnt); + ESP_LOGI(TAG, "IP(%d) is not set in the table.", ip_cnt); break; } } @@ -209,6 +215,16 @@ static int master_get_slave_ip_stdin(char** addr_table) #elif CONFIG_MB_MDNS_IP_RESOLVER +typedef struct slave_addr_entry_s { + uint16_t index; + char* ip_address; + uint8_t slave_addr; + void* p_data; + LIST_ENTRY(slave_addr_entry_s) entries; +} slave_addr_entry_t; + +LIST_HEAD(slave_addr_, slave_addr_entry_s) slave_addr_list = LIST_HEAD_INITIALIZER(slave_addr_list); + // convert MAC from binary format to string static inline char* gen_mac_str(const uint8_t* mac, char* pref, char* mac_str) { @@ -232,7 +248,7 @@ static void master_start_mdns_service() ESP_ERROR_CHECK(mdns_init()); // set mDNS hostname (required if you want to advertise services) ESP_ERROR_CHECK(mdns_hostname_set(hostname)); - ESP_LOGI(MASTER_TAG, "mdns hostname set to: [%s]", hostname); + ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); // set default mDNS instance name ESP_ERROR_CHECK(mdns_instance_name_set(MB_MDNS_INSTANCE("esp32_"))); @@ -273,15 +289,21 @@ static char* master_get_slave_ip_str(mdns_ip_addr_t* address, mb_tcp_addr_type_t return slave_ip_str; } -static esp_err_t master_resolve_slave(const char* name, mdns_result_t* result, char** resolved_ip, +static esp_err_t master_resolve_slave(uint8_t short_addr, mdns_result_t* result, char** resolved_ip, mb_tcp_addr_type_t addr_type) { - if (!name || !result) { + if (!short_addr || !result || !resolved_ip) { return ESP_ERR_INVALID_ARG; } mdns_result_t* r = result; int t; char* slave_ip = NULL; + char slave_name[22] = {0}; + + if (sprintf(slave_name, "mb_slave_tcp_%02X", short_addr) < 0) { + ESP_LOGE(TAG, "Fail to create instance name for index: %d", short_addr); + abort(); + } for (; r ; r = r->next) { if ((r->ip_protocol == MDNS_IP_PROTOCOL_V4) && (addr_type == MB_IPV6)) { continue; @@ -290,7 +312,7 @@ static esp_err_t master_resolve_slave(const char* name, mdns_result_t* result, c } // Check host name for Modbus short address and // append it into slave ip address table - if ((strcmp(r->instance_name, name) == 0) && (r->port == CONFIG_FMB_TCP_PORT_DEFAULT)) { + if ((strcmp(r->instance_name, slave_name) == 0) && (r->port == CONFIG_FMB_TCP_PORT_DEFAULT)) { printf(" PTR : %s\n", r->instance_name); if (r->txt_count) { printf(" TXT : [%u] ", r->txt_count); @@ -301,92 +323,124 @@ static esp_err_t master_resolve_slave(const char* name, mdns_result_t* result, c } slave_ip = master_get_slave_ip_str(r->addr, addr_type); if (slave_ip) { - ESP_LOGI(MASTER_TAG, "Resolved slave %s[%s]:%u", r->hostname, slave_ip, r->port); + ESP_LOGI(TAG, "Resolved slave %s[%s]:%u", r->hostname, slave_ip, r->port); *resolved_ip = slave_ip; return ESP_OK; } } } *resolved_ip = NULL; - ESP_LOGD(MASTER_TAG, "Fail to resolve slave: %s", name); + ESP_LOGD(TAG, "Fail to resolve slave: %s", slave_name); return ESP_ERR_NOT_FOUND; } static int master_create_slave_list(mdns_result_t* results, char** addr_table, - mb_tcp_addr_type_t addr_type) + int addr_table_size, mb_tcp_addr_type_t addr_type) { if (!results) { return -1; } - int i, addr, resolved = 0; + int i, slave_addr, cid_resolve_cnt = 0; + int ip_index = 0; const mb_parameter_descriptor_t* pdescr = &device_parameters[0]; char** ip_table = addr_table; - char slave_name[22] = {0}; char* slave_ip = NULL; + slave_addr_entry_t *it; - for (i = 0; (i < num_device_parameters && pdescr); i++, pdescr++) { - addr = pdescr->mb_slave_addr; - if (-1 == sprintf(slave_name, "mb_slave_tcp_%02X", addr)) { - ESP_LOGI(MASTER_TAG, "Fail to create instance name for index: %d", addr); - abort(); + for (i = 0; (i < num_device_parameters && pdescr); i++, pdescr++) + { + slave_addr = pdescr->mb_slave_addr; + + it = NULL; + // Is the slave address already registered? + LIST_FOREACH(it, &slave_addr_list, entries) { + if (slave_addr == it->slave_addr) { + break; + } } - if (!ip_table[addr - 1]) { - esp_err_t err = master_resolve_slave(slave_name, results, &slave_ip, addr_type); + if (!it) { + // Resolve new slave IP address using its short address + esp_err_t err = master_resolve_slave(slave_addr, results, &slave_ip, addr_type); if (err != ESP_OK) { - ESP_LOGE(MASTER_TAG, "Index: %d, sl_addr: %d, name:%s, failed to resolve!", - i, addr, slave_name); + ESP_LOGE(TAG, "Index: %d, sl_addr: %d, failed to resolve!", i, slave_addr); // Set correspond index to NULL indicate host not resolved - ip_table[addr - 1] = NULL; + ip_table[ip_index] = NULL; continue; } - ip_table[addr - 1] = slave_ip; //slave_name; - ESP_LOGI(MASTER_TAG, "Index: %d, sl_addr: %d, name:%s, resolve to IP: [%s]", - i, addr, slave_name, slave_ip); - resolved++; + // Register new slave address information + slave_addr_entry_t* new_slave_entry = (slave_addr_entry_t*) heap_caps_malloc(sizeof(slave_addr_entry_t), + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + MB_RETURN_ON_FALSE((new_slave_entry != NULL), ESP_ERR_NO_MEM, + TAG, "Can not allocate memory for slave entry."); + new_slave_entry->index = i; + new_slave_entry->ip_address = slave_ip; + new_slave_entry->slave_addr = slave_addr; + new_slave_entry->p_data = NULL; + LIST_INSERT_HEAD(&slave_addr_list, new_slave_entry, entries); + ip_table[ip_index] = slave_ip; + ESP_LOGI(TAG, "Index: %d, sl_addr: %d, resolved to IP: [%s]", + i, slave_addr, slave_ip); + cid_resolve_cnt++; + if (ip_index < addr_table_size) { + ip_index++; + } } else { - ESP_LOGI(MASTER_TAG, "Index: %d, sl_addr: %d, name:%s, set to IP: [%s]", - i, addr, slave_name, ip_table[addr - 1]); - resolved++; - } - } - return resolved; -} - -static void master_destroy_slave_list(char** table) -{ - for (int i = 0; ((i < MB_DEVICE_COUNT) && table[i] != NULL); i++) { - if (table[i]) { - free(table[i]); - table[i] = NULL; + ip_table[ip_index] = it ? it->ip_address : ip_table[ip_index]; + ESP_LOGI(TAG, "Index: %d, sl_addr: %d, set to IP: [%s]", + i, slave_addr, ip_table[ip_index]); + cid_resolve_cnt++; } } + ESP_LOGI(TAG, "Resolved %d cids, with %d IP addresses", cid_resolve_cnt, ip_index); + return cid_resolve_cnt; } static int master_query_slave_service(const char * service_name, const char * proto, mb_tcp_addr_type_t addr_type) { - ESP_LOGI(MASTER_TAG, "Query PTR: %s.%s.local", service_name, proto); + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); mdns_result_t* results = NULL; int count = 0; esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); if(err){ - ESP_LOGE(MASTER_TAG, "Query Failed: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return count; } if(!results){ - ESP_LOGW(MASTER_TAG, "No results found!"); + ESP_LOGW(TAG, "No results found!"); return count; } - count = master_create_slave_list(results, slave_ip_address_table, addr_type); + count = master_create_slave_list(results, slave_ip_address_table, ip_table_sz, addr_type); mdns_query_results_free(results); return count; } #endif +static void master_destroy_slave_list(char** table, size_t ip_table_size) +{ +#if CONFIG_MB_MDNS_IP_RESOLVER + slave_addr_entry_t *it; + LIST_FOREACH(it, &slave_addr_list, entries) { + LIST_REMOVE(it, entries); + free(it); + } +#endif + for (int i = 0; ((i < ip_table_size) && table[i] != NULL); i++) { + if (table[i]) { +#if CONFIG_MB_SLAVE_IP_FROM_STDIN + free(table[i]); + table[i] = "FROM_STDIN"; +#elif CONFIG_MB_MDNS_IP_RESOLVER + table[i] = NULL; +#endif + } + } +} + // The function to get pointer to parameter storage (instance) according to parameter description table static void* master_get_param_data(const mb_parameter_descriptor_t* param_descriptor) { @@ -412,7 +466,7 @@ static void* master_get_param_data(const mb_parameter_descriptor_t* param_descri break; } } else { - ESP_LOGE(MASTER_TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); + ESP_LOGE(TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); assert(instance_ptr != NULL); } return instance_ptr; @@ -426,7 +480,7 @@ static void master_operation_func(void *arg) bool alarm_state = false; const mb_parameter_descriptor_t* param_descriptor = NULL; - ESP_LOGI(MASTER_TAG, "Start modbus test..."); + ESP_LOGI(TAG, "Start modbus test..."); for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) { // Read all found characteristics from slave(s) @@ -446,7 +500,7 @@ static void master_operation_func(void *arg) err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data_ptr, &type); if (err == ESP_OK) { - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, @@ -458,13 +512,13 @@ static void master_operation_func(void *arg) err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data_ptr, &type); if (err == ESP_OK) { - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, *(uint32_t*)temp_data_ptr); } else { - ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", + ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", param_descriptor->cid, (char*)param_descriptor->param_key, (int)err, @@ -472,7 +526,7 @@ static void master_operation_func(void *arg) } } } else { - ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", + ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", param_descriptor->cid, (char*)param_descriptor->param_key, (int)err, @@ -485,7 +539,7 @@ static void master_operation_func(void *arg) if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) || (param_descriptor->mb_param_type == MB_PARAM_INPUT)) { value = *(float*)temp_data_ptr; - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, @@ -499,7 +553,7 @@ static void master_operation_func(void *arg) } else { uint8_t state = *(uint8_t*)temp_data_ptr; const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF"; - ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", param_descriptor->cid, (char*)param_descriptor->param_key, (char*)param_descriptor->param_units, @@ -511,7 +565,7 @@ static void master_operation_func(void *arg) } } } else { - ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", + ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", param_descriptor->cid, (char*)param_descriptor->param_key, (int)err, @@ -525,13 +579,13 @@ static void master_operation_func(void *arg) } if (alarm_state) { - ESP_LOGI(MASTER_TAG, "Alarm triggered by cid #%d.", + ESP_LOGI(TAG, "Alarm triggered by cid #%d.", param_descriptor->cid); } else { - ESP_LOGE(MASTER_TAG, "Alarm is not triggered after %d retries.", + ESP_LOGE(TAG, "Alarm is not triggered after %d retries.", MASTER_MAX_RETRY); } - ESP_LOGI(MASTER_TAG, "Destroy master..."); + ESP_LOGI(TAG, "Destroy master..."); vTaskDelay(100); } @@ -542,18 +596,18 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) ESP_ERROR_CHECK(nvs_flash_erase()); result = nvs_flash_init(); } - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "nvs_flash_init fail, returns(0x%x).", (uint32_t)result); result = esp_netif_init(); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_netif_init fail, returns(0x%x).", (uint32_t)result); result = esp_event_loop_create_default(); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_event_loop_create_default fail, returns(0x%x).", (uint32_t)result); #if CONFIG_MB_MDNS_IP_RESOLVER @@ -564,14 +618,14 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) // Read "Establishing Wi-Fi or Ethernet Connection" section in // examples/protocols/README.md for more information about this function. result = example_connect(); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "example_connect fail, returns(0x%x).", (uint32_t)result); #if CONFIG_EXAMPLE_CONNECT_WIFI result = esp_wifi_set_ps(WIFI_PS_NONE); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_wifi_set_ps fail, returns(0x%x).", (uint32_t)result); #endif @@ -581,17 +635,17 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) res = master_query_slave_service("_modbus", "_tcp", ip_addr_type); } if (res < num_device_parameters) { - ESP_LOGE(MASTER_TAG, "Could not resolve one or more slave IP addresses, resolved: %d out of %d.", res, num_device_parameters ); - ESP_LOGE(MASTER_TAG, "Make sure you configured all slaves according to device parameter table and they alive in the network."); + ESP_LOGE(TAG, "Could not resolve one or more slave IP addresses, resolved: %d out of %d.", res, num_device_parameters ); + ESP_LOGE(TAG, "Make sure you configured all slaves according to device parameter table and they alive in the network."); return ESP_ERR_NOT_FOUND; } mdns_free(); #elif CONFIG_MB_SLAVE_IP_FROM_STDIN int ip_cnt = master_get_slave_ip_stdin(slave_ip_address_table); if (ip_cnt) { - ESP_LOGI(MASTER_TAG, "Configured %d IP addresse(s).", ip_cnt); + ESP_LOGI(TAG, "Configured %d IP addresse(s).", ip_cnt); } else { - ESP_LOGE(MASTER_TAG, "Fail to get IP address from stdin. Continue."); + ESP_LOGE(TAG, "Fail to get IP address from stdin. Continue."); return ESP_ERR_NOT_FOUND; } #endif @@ -601,27 +655,26 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) static esp_err_t destroy_services(void) { esp_err_t err = ESP_OK; -#if CONFIG_MB_MDNS_IP_RESOLVER - master_destroy_slave_list(slave_ip_address_table); -#endif + master_destroy_slave_list(slave_ip_address_table, ip_table_sz); + err = example_disconnect(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "example_disconnect fail, returns(0x%x).", (uint32_t)err); err = esp_event_loop_delete_default(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_event_loop_delete_default fail, returns(0x%x).", (uint32_t)err); err = esp_netif_deinit(); - ESP_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, + TAG, "esp_netif_deinit fail, returns(0x%x).", (uint32_t)err); err = nvs_flash_deinit(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "nvs_flash_deinit fail, returns(0x%x).", (uint32_t)err); return err; @@ -633,30 +686,30 @@ static esp_err_t master_init(mb_communication_info_t* comm_info) void* master_handler = NULL; esp_err_t err = mbc_master_init_tcp(&master_handler); - ESP_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, + TAG, "mb controller initialization fail."); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mb controller initialization fail, returns(0x%x).", (uint32_t)err); err = mbc_master_setup((void*)comm_info); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mb controller setup fail, returns(0x%x).", (uint32_t)err); err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mb controller set descriptor fail, returns(0x%x).", (uint32_t)err); - ESP_LOGI(MASTER_TAG, "Modbus master stack initialized..."); + ESP_LOGI(TAG, "Modbus master stack initialized..."); err = mbc_master_start(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mb controller start fail, returns(0x%x).", (uint32_t)err); vTaskDelay(5); @@ -666,11 +719,11 @@ static esp_err_t master_init(mb_communication_info_t* comm_info) static esp_err_t master_destroy(void) { esp_err_t err = mbc_master_destroy(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - MASTER_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_master_destroy fail, returns(0x%x).", (uint32_t)err); - ESP_LOGI(MASTER_TAG, "Modbus master stack destroy..."); + ESP_LOGI(TAG, "Modbus master stack destroy..."); return err; } diff --git a/examples/protocols/modbus/tcp/mb_tcp_slave/main/Kconfig.projbuild b/examples/protocols/modbus/tcp/mb_tcp_slave/main/Kconfig.projbuild index 45c10bb50e..27a2979099 100644 --- a/examples/protocols/modbus/tcp/mb_tcp_slave/main/Kconfig.projbuild +++ b/examples/protocols/modbus/tcp/mb_tcp_slave/main/Kconfig.projbuild @@ -2,7 +2,7 @@ menu "Modbus Example Configuration" config MB_SLAVE_ADDR int "Modbus slave address" - range 1 127 + range 1 255 default 1 help This is the Modbus slave address in the network. diff --git a/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c b/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c index 0394702434..bfd3fd7cbd 100644 --- a/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c +++ b/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +10,6 @@ #include "esp_err.h" #include "sdkconfig.h" #include "esp_log.h" -#include "esp_check.h" #include "esp_system.h" #include "esp_wifi.h" #include "esp_event.h" @@ -49,7 +48,7 @@ | MB_EVENT_COILS_WR) #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK) -#define SLAVE_TAG "SLAVE_TEST" +static const char *TAG = "SLAVE_TEST"; static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED; @@ -163,8 +162,8 @@ static void slave_operation_func(void *arg) { mb_param_info_t reg_info; // keeps the Modbus registers access information - ESP_LOGI(SLAVE_TAG, "Modbus slave stack initialized."); - ESP_LOGI(SLAVE_TAG, "Start modbus test..."); + ESP_LOGI(TAG, "Modbus slave stack initialized."); + ESP_LOGI(TAG, "Start modbus test..."); // The cycle below will be terminated when parameter holding_data0 // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) { @@ -175,7 +174,7 @@ static void slave_operation_func(void *arg) if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { // Get parameter information from parameter queue ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", rw_str, (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, @@ -193,7 +192,7 @@ static void slave_operation_func(void *arg) } } else if (event & MB_EVENT_INPUT_REG_RD) { ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, (uint32_t)reg_info.type, @@ -201,7 +200,7 @@ static void slave_operation_func(void *arg) (uint32_t)reg_info.size); } else if (event & MB_EVENT_DISCRETE_RD) { ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, (uint32_t)reg_info.type, @@ -209,7 +208,7 @@ static void slave_operation_func(void *arg) (uint32_t)reg_info.size); } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); - ESP_LOGI(SLAVE_TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + ESP_LOGI(TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", rw_str, (uint32_t)reg_info.time_stamp, (uint32_t)reg_info.mb_offset, @@ -220,7 +219,7 @@ static void slave_operation_func(void *arg) } } // Destroy of Modbus controller on alarm - ESP_LOGI(SLAVE_TAG,"Modbus controller destroyed."); + ESP_LOGI(TAG,"Modbus controller destroyed."); vTaskDelay(100); } @@ -231,18 +230,18 @@ static esp_err_t init_services(void) ESP_ERROR_CHECK(nvs_flash_erase()); result = nvs_flash_init(); } - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "nvs_flash_init fail, returns(0x%x).", (uint32_t)result); result = esp_netif_init(); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_netif_init fail, returns(0x%x).", (uint32_t)result); result = esp_event_loop_create_default(); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_event_loop_create_default fail, returns(0x%x).", (uint32_t)result); #if CONFIG_MB_MDNS_IP_RESOLVER @@ -253,14 +252,14 @@ static esp_err_t init_services(void) // Read "Establishing Wi-Fi or Ethernet Connection" section in // examples/protocols/README.md for more information about this function. result = example_connect(); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "example_connect fail, returns(0x%x).", (uint32_t)result); #if CONFIG_EXAMPLE_CONNECT_WIFI result = esp_wifi_set_ps(WIFI_PS_NONE); - ESP_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_wifi_set_ps fail, returns(0x%x).", (uint32_t)result); #endif @@ -272,23 +271,23 @@ static esp_err_t destroy_services(void) esp_err_t err = ESP_OK; err = example_disconnect(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "example_disconnect fail, returns(0x%x).", (uint32_t)err); err = esp_event_loop_delete_default(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "esp_event_loop_delete_default fail, returns(0x%x).", (uint32_t)err); err = esp_netif_deinit(); - ESP_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, + TAG, "esp_netif_deinit fail, returns(0x%x).", (uint32_t)err); err = nvs_flash_deinit(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "nvs_flash_deinit fail, returns(0x%x).", (uint32_t)err); #if CONFIG_MB_MDNS_IP_RESOLVER @@ -306,8 +305,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) // Initialization of Modbus controller esp_err_t err = mbc_slave_init_tcp(&slave_handler); - ESP_RETURN_ON_FALSE((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE, + TAG, "mb controller initialization fail."); comm_info->ip_addr = NULL; // Bind to any address @@ -315,8 +314,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) // Setup communication parameters and start stack err = mbc_slave_setup((void*)comm_info); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_setup fail, returns(0x%x).", (uint32_t)err); @@ -331,8 +330,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) 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 err = mbc_slave_set_descriptor(reg_area); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_set_descriptor fail, returns(0x%x).", (uint32_t)err); @@ -341,8 +340,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) 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 err = mbc_slave_set_descriptor(reg_area); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_set_descriptor fail, returns(0x%x).", (uint32_t)err); @@ -352,8 +351,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) reg_area.address = (void*)&input_reg_params.input_data0; reg_area.size = sizeof(float) << 2; err = mbc_slave_set_descriptor(reg_area); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_set_descriptor fail, returns(0x%x).", (uint32_t)err); reg_area.type = MB_PARAM_INPUT; @@ -361,8 +360,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) reg_area.address = (void*)&input_reg_params.input_data4; reg_area.size = sizeof(float) << 2; err = mbc_slave_set_descriptor(reg_area); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_set_descriptor fail, returns(0x%x).", (uint32_t)err); @@ -372,8 +371,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) reg_area.address = (void*)&coil_reg_params; reg_area.size = sizeof(coil_reg_params); err = mbc_slave_set_descriptor(reg_area); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_set_descriptor fail, returns(0x%x).", (uint32_t)err); @@ -383,8 +382,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) reg_area.address = (void*)&discrete_reg_params; reg_area.size = sizeof(discrete_reg_params); err = mbc_slave_set_descriptor(reg_area); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_set_descriptor fail, returns(0x%x).", (uint32_t)err); @@ -393,8 +392,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) // Starts of modbus controller and stack err = mbc_slave_start(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_start fail, returns(0x%x).", (uint32_t)err); vTaskDelay(5); @@ -404,8 +403,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) static esp_err_t slave_destroy(void) { esp_err_t err = mbc_slave_destroy(); - ESP_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, - SLAVE_TAG, + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, + TAG, "mbc_slave_destroy fail, returns(0x%x).", (uint32_t)err); return err; @@ -420,7 +419,7 @@ void app_main(void) ESP_ERROR_CHECK(init_services()); // Set UART log level - esp_log_level_set(SLAVE_TAG, ESP_LOG_INFO); + esp_log_level_set(TAG, ESP_LOG_INFO); mb_communication_info_t comm_info = { 0 };