From e94945fc0fadae63dbe395c2e2332888d8b7f614 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 11 May 2026 03:44:14 +0800 Subject: [PATCH] feat(gateway): enhance UART configuration validation for Modbus and KNX Signed-off-by: Tony --- apps/gateway/main/app_main.cpp | 17 +- .../gateway_bridge/include/gateway_bridge.hpp | 6 + .../gateway_bridge/src/gateway_bridge.cpp | 277 ++++++++++++++++-- components/gateway_knx/src/gateway_knx.cpp | 22 +- 4 files changed, 286 insertions(+), 36 deletions(-) diff --git a/apps/gateway/main/app_main.cpp b/apps/gateway/main/app_main.cpp index 6e50de0..fabb509 100644 --- a/apps/gateway/main/app_main.cpp +++ b/apps/gateway/main/app_main.cpp @@ -504,6 +504,10 @@ bool ValidateChannelBindings() { ESP_LOGE(kTag, "Modbus serial is configured on UART0, but UART0 is reserved for console"); return false; } + if (modbus_uart == 0 && kConsoleOnUart0) { + ESP_LOGE(kTag, "Modbus serial UART0 requires moving the ESP-IDF console off UART0"); + return false; + } for (int i = 0; i < CONFIG_GATEWAY_CHANNEL_COUNT; ++i) { if (channels[i].enabled && channels[i].serial_phy && channels[i].uart_port == modbus_uart) { ESP_LOGE(kTag, "Modbus serial UART%d conflicts with DALI channel %d serial PHY", @@ -519,6 +523,10 @@ bool ValidateChannelBindings() { ESP_LOGE(kTag, "KNX TP UART0 conflicts with the UART0 control bridge"); return false; } + if (knx_uart == 0 && kConsoleOnUart0) { + ESP_LOGE(kTag, "KNX TP-UART on UART0 requires moving the ESP-IDF console off UART0"); + return false; + } if (kModbusBridgeSupported && kModbusDefaultSerialTransport && knx_uart == CONFIG_GATEWAY_MODBUS_SERIAL_UART_PORT) { ESP_LOGE(kTag, "KNX TP UART%d conflicts with default Modbus serial UART", knx_uart); @@ -720,10 +728,8 @@ extern "C" void app_main(void) { static_cast(CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE); bridge_config.modbus_task_priority = static_cast(CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_PRIORITY); - bridge_config.allow_modbus_uart0 = kModbusAllowUart0 && !k485ControlEnabled; - if (!bridge_config.allow_modbus_uart0) { - bridge_config.reserved_uart_ports.push_back(0); - } + bridge_config.allow_modbus_uart0 = kModbusAllowUart0 && !kConsoleOnUart0 && !k485ControlEnabled; + bridge_config.allow_knx_uart0 = !kConsoleOnUart0 && !k485ControlEnabled; #if CONFIG_GATEWAY_CHANNEL1_PHY_UART1 bridge_config.reserved_uart_ports.push_back(1); #elif CONFIG_GATEWAY_CHANNEL1_PHY_UART2 @@ -736,9 +742,6 @@ extern "C" void app_main(void) { bridge_config.reserved_uart_ports.push_back(2); #endif #endif - if (kKnxBridgeSupported) { - bridge_config.reserved_uart_ports.push_back(CONFIG_GATEWAY_KNX_TP_UART_PORT); - } if (kModbusBridgeSupported) { gateway::GatewayModbusConfig default_modbus; #if defined(CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_RTU) diff --git a/components/gateway_bridge/include/gateway_bridge.hpp b/components/gateway_bridge/include/gateway_bridge.hpp index 17327e9..981fb3e 100644 --- a/components/gateway_bridge/include/gateway_bridge.hpp +++ b/components/gateway_bridge/include/gateway_bridge.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,7 @@ struct GatewayBridgeServiceConfig { UBaseType_t modbus_task_priority{4}; std::optional default_modbus_config; bool allow_modbus_uart0{false}; + bool allow_knx_uart0{false}; std::vector reserved_uart_ports; uint32_t bacnet_task_stack_size{8192}; UBaseType_t bacnet_task_priority{5}; @@ -63,6 +65,10 @@ class GatewayBridgeService { ChannelRuntime* findRuntime(uint8_t gateway_id); const ChannelRuntime* findRuntime(uint8_t gateway_id) const; + void collectUsedRuntimeResources(uint8_t except_gateway_id, + std::set* modbus_tcp_ports, + std::set* knx_udp_ports, + std::set* serial_uarts) const; DaliDomainService& dali_domain_; GatewayCache& cache_; diff --git a/components/gateway_bridge/src/gateway_bridge.cpp b/components/gateway_bridge/src/gateway_bridge.cpp index 7dffc9a..5b835d2 100644 --- a/components/gateway_bridge/src/gateway_bridge.cpp +++ b/components/gateway_bridge/src/gateway_bridge.cpp @@ -1186,6 +1186,7 @@ struct GatewayBridgeService::ChannelRuntime { int modbus_client_sock{-1}; int modbus_uart_port{-1}; std::string modbus_last_error; + std::string knx_last_error; struct DiagnosticSnapshotCacheEntry { DaliDomainSnapshot snapshot; @@ -1460,6 +1461,13 @@ struct GatewayBridgeService::ChannelRuntime { if (!parsed.has_value()) { return ESP_ERR_INVALID_ARG; } + { + LockGuard guard(lock); + const esp_err_t validation_err = validateStoredBridgeConfigLocked(parsed.value()); + if (validation_err != ESP_OK) { + return validation_err; + } + } BridgeProvisioningStore store(bridgeNamespace()); const esp_err_t err = store.saveObject( kBridgeConfigKey, @@ -1832,7 +1840,8 @@ struct GatewayBridgeService::ChannelRuntime { } #endif - esp_err_t startKnx() { + esp_err_t startKnx(std::set* used_ports = nullptr, + std::set* used_uarts = nullptr) { LockGuard guard(lock); if (!service_config.knx_enabled) { return ESP_ERR_NOT_SUPPORTED; @@ -1844,15 +1853,44 @@ struct GatewayBridgeService::ChannelRuntime { if (!config.has_value()) { return ESP_ERR_NOT_FOUND; } + std::string validation_error; + const esp_err_t validation_err = validateKnxConfigLocked( + config.value(), activeModbusConfigLocked(), &validation_error); + if (validation_err != ESP_OK) { + knx_last_error = validation_error; + return validation_err; + } + if (config->ip_router_enabled && used_ports != nullptr) { + if (used_ports->find(config->udp_port) != used_ports->end()) { + knx_last_error = "duplicate KNXnet/IP UDP port " + std::to_string(config->udp_port); + return ESP_ERR_INVALID_STATE; + } + used_ports->insert(config->udp_port); + } + if (config->ip_router_enabled && used_uarts != nullptr) { + const int uart_port = config->tp_uart.uart_port; + if (used_uarts->find(uart_port) != used_uarts->end()) { + knx_last_error = "KNX TP-UART UART" + std::to_string(uart_port) + + " is already used by another runtime"; + return ESP_ERR_INVALID_STATE; + } + used_uarts->insert(uart_port); + } knx->setConfig(config.value()); knx_router->setConfig(config.value()); if (!config->ip_router_enabled) { knx_started = false; return ESP_ERR_NOT_SUPPORTED; } + knx_last_error.clear(); const esp_err_t err = knx_router->start(service_config.knx_task_stack_size, service_config.knx_task_priority); knx_started = err == ESP_OK; + if (err != ESP_OK) { + knx_last_error = knx_router->lastError().empty() + ? "failed to start KNX TP-UART router" + : knx_router->lastError(); + } return err; } @@ -1961,9 +1999,10 @@ struct GatewayBridgeService::ChannelRuntime { cJSON_AddBoolToObject(knx_json, "startupEnabled", service_config.knx_startup_enabled); cJSON_AddBoolToObject(knx_json, "started", knx_started); cJSON_AddBoolToObject(knx_json, "routerReady", knx_router != nullptr && knx_router->started()); - if (knx_router != nullptr) { - cJSON_AddStringToObject(knx_json, "lastError", knx_router->lastError().c_str()); - } + const std::string router_error = knx_router == nullptr ? "" : knx_router->lastError(); + cJSON_AddStringToObject(knx_json, "lastError", + knx_last_error.empty() ? router_error.c_str() + : knx_last_error.c_str()); if (effective_knx.has_value()) { cJSON_AddBoolToObject(knx_json, "daliRouterEnabled", effective_knx->dali_router_enabled); @@ -2713,22 +2752,120 @@ struct GatewayBridgeService::ChannelRuntime { service_config.reserved_uart_ports.end(); } - esp_err_t validateSerialModbusConfigLocked(const GatewayModbusConfig& config) const { + esp_err_t validateSerialModbusConfigLocked( + const GatewayModbusConfig& config, + const std::optional& candidate_knx, + std::string* error_message = nullptr) const { const int uart_port = config.serial.uart_port; if (uart_port < 0 || uart_port > 2) { + if (error_message != nullptr) { + *error_message = "Modbus serial UART port must be 0, 1, or 2"; + } return ESP_ERR_INVALID_ARG; } if (uart_port == 0 && !service_config.allow_modbus_uart0) { + if (error_message != nullptr) { + *error_message = + "Modbus serial on UART0 requires moving the ESP-IDF console and UART0 control off UART0"; + } return ESP_ERR_INVALID_STATE; } if (isReservedUartLocked(uart_port)) { + if (error_message != nullptr) { + *error_message = "Modbus serial UART" + std::to_string(uart_port) + + " is already reserved by a DALI serial PHY"; + } + return ESP_ERR_INVALID_STATE; + } + if (service_config.knx_enabled && candidate_knx.has_value() && + candidate_knx->ip_router_enabled && candidate_knx->tp_uart.uart_port == uart_port) { + if (error_message != nullptr) { + *error_message = "Modbus serial UART" + std::to_string(uart_port) + + " conflicts with KNX TP-UART; choose another free UART for RS485"; + } return ESP_ERR_INVALID_STATE; } return ESP_OK; } + esp_err_t validateKnxConfigLocked(const GatewayKnxConfig& config, + const std::optional& candidate_modbus, + std::string* error_message = nullptr) const { + if (!config.ip_router_enabled) { + return ESP_OK; + } + const int uart_port = config.tp_uart.uart_port; + if (uart_port < 0 || uart_port > 2) { + if (error_message != nullptr) { + *error_message = "KNX TP-UART port must be 0, 1, or 2"; + } + return ESP_ERR_INVALID_ARG; + } + if (uart_port == 0 && !service_config.allow_knx_uart0) { + if (error_message != nullptr) { + *error_message = + "KNX TP-UART on UART0 requires moving the ESP-IDF console and UART0 control off UART0"; + } + return ESP_ERR_INVALID_STATE; + } + if (isReservedUartLocked(uart_port)) { + if (error_message != nullptr) { + *error_message = "KNX TP-UART UART" + std::to_string(uart_port) + + " is already reserved by a DALI serial PHY"; + } + return ESP_ERR_INVALID_STATE; + } + if (service_config.modbus_enabled && candidate_modbus.has_value() && + GatewayModbusTransportIsSerial(candidate_modbus->transport) && + candidate_modbus->serial.uart_port == uart_port) { + if (error_message != nullptr) { + *error_message = "KNX TP-UART UART" + std::to_string(uart_port) + + " conflicts with Modbus serial UART"; + } + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; + } + + esp_err_t validateStoredBridgeConfigLocked(const GatewayBridgeStoredConfig& config) { + const auto candidate_modbus = config.modbus.has_value() ? config.modbus + : service_config.default_modbus_config; + const auto candidate_knx = config.knx.has_value() ? config.knx + : service_config.default_knx_config; + std::string validation_error; + if (candidate_modbus.has_value() && + GatewayModbusTransportIsSerial(candidate_modbus->transport)) { + const esp_err_t err = validateSerialModbusConfigLocked( + candidate_modbus.value(), candidate_knx, &validation_error); + if (err != ESP_OK) { + modbus_last_error = validation_error; + return err; + } + } + if (candidate_knx.has_value()) { + const esp_err_t err = validateKnxConfigLocked(candidate_knx.value(), candidate_modbus, + &validation_error); + if (err != ESP_OK) { + knx_last_error = validation_error; + return err; + } + } + modbus_last_error.clear(); + knx_last_error.clear(); + return ESP_OK; + } + esp_err_t saveModbusConfig(const GatewayModbusConfig& config) { LockGuard guard(lock); + if (GatewayModbusTransportIsSerial(config.transport)) { + std::string validation_error; + const esp_err_t validation_err = validateSerialModbusConfigLocked( + config, activeKnxConfigLocked(), &validation_error); + if (validation_err != ESP_OK) { + modbus_last_error = validation_error; + return validation_err; + } + } BridgeProvisioningStore store(bridgeNamespace()); const esp_err_t err = store.saveObject( kBridgeConfigKey, @@ -2742,6 +2879,7 @@ struct GatewayBridgeService::ChannelRuntime { if (modbus != nullptr) { modbus->setConfig(config); } + modbus_last_error.clear(); return ESP_OK; } @@ -2752,8 +2890,33 @@ struct GatewayBridgeService::ChannelRuntime { return service_config.default_knx_config; } - esp_err_t saveKnxConfig(const GatewayKnxConfig& config) { + esp_err_t saveKnxConfig(const GatewayKnxConfig& config, + std::set* used_ports = nullptr, + std::set* used_uarts = nullptr) { LockGuard guard(lock); + std::string validation_error; + const esp_err_t validation_err = validateKnxConfigLocked( + config, activeModbusConfigLocked(), &validation_error); + if (validation_err != ESP_OK) { + knx_last_error = validation_error; + return validation_err; + } + const bool restart_router = knx_started || (knx_router != nullptr && knx_router->started()); + if (restart_router && config.ip_router_enabled && used_ports != nullptr && + used_ports->find(config.udp_port) != used_ports->end()) { + knx_last_error = "duplicate KNXnet/IP UDP port " + std::to_string(config.udp_port); + return ESP_ERR_INVALID_STATE; + } + if (restart_router && config.ip_router_enabled && used_uarts != nullptr && + used_uarts->find(config.tp_uart.uart_port) != used_uarts->end()) { + knx_last_error = "KNX TP-UART UART" + std::to_string(config.tp_uart.uart_port) + + " is already used by another runtime"; + return ESP_ERR_INVALID_STATE; + } + if (restart_router && knx_router != nullptr) { + knx_router->stop(); + knx_started = false; + } BridgeProvisioningStore store(bridgeNamespace()); const esp_err_t err = store.saveObject( kBridgeConfigKey, @@ -2770,6 +2933,10 @@ struct GatewayBridgeService::ChannelRuntime { if (knx_router != nullptr) { knx_router->setConfig(config); } + if (restart_router) { + return startKnx(used_ports, used_uarts); + } + knx_last_error.clear(); return ESP_OK; } @@ -2920,14 +3087,18 @@ struct GatewayBridgeService::ChannelRuntime { return ESP_ERR_NOT_FOUND; } if (GatewayModbusTransportIsSerial(config->transport)) { - const esp_err_t serial_err = validateSerialModbusConfigLocked(config.value()); + std::string validation_error; + const esp_err_t serial_err = validateSerialModbusConfigLocked( + config.value(), activeKnxConfigLocked(), &validation_error); if (serial_err != ESP_OK) { - modbus_last_error = "invalid or reserved Modbus serial UART"; + modbus_last_error = validation_error; return serial_err; } if (used_uarts != nullptr) { const int uart_port = config->serial.uart_port; if (used_uarts->find(uart_port) != used_uarts->end()) { + modbus_last_error = "Modbus serial UART" + std::to_string(uart_port) + + " is already used by another runtime"; ESP_LOGW(kTag, "gateway=%u skips duplicate Modbus serial UART%d", channel.gateway_id, uart_port); return ESP_ERR_INVALID_STATE; @@ -2938,6 +3109,7 @@ struct GatewayBridgeService::ChannelRuntime { const uint16_t port = config->port == 0 ? kGatewayModbusDefaultTcpPort : config->port; if (GatewayModbusTransportIsTcp(config->transport) && used_ports != nullptr) { if (used_ports->find(port) != used_ports->end()) { + modbus_last_error = "duplicate Modbus TCP port " + std::to_string(port); ESP_LOGW(kTag, "gateway=%u skips duplicate Modbus TCP port %u", channel.gateway_id, port); return ESP_ERR_INVALID_STATE; } @@ -3289,7 +3461,9 @@ struct GatewayBridgeService::ChannelRuntime { const esp_err_t err = saveModbusConfig(parsed.value()); cJSON_Delete(root); if (err != ESP_OK) { - writeModbusManagementResponse(uart_port, false, action.c_str(), esp_err_to_name(err)); + writeModbusManagementResponse( + uart_port, false, action.c_str(), + modbus_last_error.empty() ? esp_err_to_name(err) : modbus_last_error.c_str()); return; } writeModbusManagementResponse(uart_port, true, action.c_str(), nullptr); @@ -3367,11 +3541,11 @@ esp_err_t GatewayBridgeService::start() { runtimes_.push_back(std::move(runtime)); } + std::set used_serial_uarts; if (config_.modbus_enabled && config_.modbus_startup_enabled) { - std::set used_ports; - std::set used_uarts; + std::set used_modbus_ports; for (const auto& runtime : runtimes_) { - const esp_err_t err = runtime->startModbus(&used_ports, &used_uarts); + const esp_err_t err = runtime->startModbus(&used_modbus_ports, &used_serial_uarts); if (err != ESP_OK && err != ESP_ERR_NOT_FOUND && err != ESP_ERR_NOT_SUPPORTED) { ESP_LOGW(kTag, "gateway=%u Modbus startup skipped: %s", runtime->channel.gateway_id, esp_err_to_name(err)); @@ -3380,8 +3554,9 @@ esp_err_t GatewayBridgeService::start() { } if (config_.knx_enabled && config_.knx_startup_enabled) { + std::set used_knx_ports; for (const auto& runtime : runtimes_) { - const esp_err_t err = runtime->startKnx(); + const esp_err_t err = runtime->startKnx(&used_knx_ports, &used_serial_uarts); if (err != ESP_OK && err != ESP_ERR_NOT_FOUND && err != ESP_ERR_NOT_SUPPORTED) { ESP_LOGW(kTag, "gateway=%u KNX/IP startup skipped: %s", runtime->channel.gateway_id, esp_err_to_name(err)); @@ -3422,6 +3597,44 @@ const GatewayBridgeService::ChannelRuntime* GatewayBridgeService::findRuntime( return nullptr; } +void GatewayBridgeService::collectUsedRuntimeResources( + uint8_t except_gateway_id, + std::set* modbus_tcp_ports, + std::set* knx_udp_ports, + std::set* serial_uarts) const { + for (const auto& runtime : runtimes_) { + if (runtime->channel.gateway_id == except_gateway_id) { + continue; + } + LockGuard guard(runtime->lock); + if (runtime->modbus_started) { + const auto modbus_config = runtime->activeModbusConfigLocked(); + if (modbus_config.has_value()) { + if (GatewayModbusTransportIsSerial(modbus_config->transport) && serial_uarts != nullptr) { + serial_uarts->insert(modbus_config->serial.uart_port); + } else if (GatewayModbusTransportIsTcp(modbus_config->transport) && + modbus_tcp_ports != nullptr) { + const uint16_t port = modbus_config->port == 0 ? kGatewayModbusDefaultTcpPort + : modbus_config->port; + modbus_tcp_ports->insert(port); + } + } + } + if (runtime->knx_started || + (runtime->knx_router != nullptr && runtime->knx_router->started())) { + const auto knx_config = runtime->activeKnxConfigLocked(); + if (knx_config.has_value() && knx_config->ip_router_enabled) { + if (knx_udp_ports != nullptr) { + knx_udp_ports->insert(knx_config->udp_port); + } + if (serial_uarts != nullptr) { + serial_uarts->insert(knx_config->tp_uart.uart_port); + } + } + } + } +} + GatewayBridgeHttpResponse GatewayBridgeService::handleGet( const std::string& action_arg, int gateway_id_arg, const std::string& query_arg) { if (!config_.bridge_enabled) { @@ -3626,7 +3839,12 @@ GatewayBridgeHttpResponse GatewayBridgeService::handlePost( if (action == "config" || action == "save_config") { const esp_err_t err = runtime->saveBridgeConfig(body); if (err != ESP_OK) { - return ErrorResponse(err, "failed to save bridge config"); + const char* message = !runtime->knx_last_error.empty() + ? runtime->knx_last_error.c_str() + : (!runtime->modbus_last_error.empty() + ? runtime->modbus_last_error.c_str() + : "failed to save bridge config"); + return ErrorResponse(err, message); } return handleGet("config", gateway_id.value()); } @@ -3666,9 +3884,15 @@ GatewayBridgeHttpResponse GatewayBridgeService::handlePost( return handleGet("cloud", gateway_id.value()); } if (action == "modbus_start") { - const esp_err_t err = runtime->startModbus(); + std::set used_modbus_ports; + std::set used_serial_uarts; + collectUsedRuntimeResources(gateway_id.value(), &used_modbus_ports, nullptr, + &used_serial_uarts); + const esp_err_t err = runtime->startModbus(&used_modbus_ports, &used_serial_uarts); if (err != ESP_OK) { - return ErrorResponse(err, "failed to start Modbus bridge"); + return ErrorResponse(err, runtime->modbus_last_error.empty() + ? "failed to start Modbus bridge" + : runtime->modbus_last_error.c_str()); } return handleGet("modbus", gateway_id.value()); } @@ -3694,16 +3918,29 @@ GatewayBridgeHttpResponse GatewayBridgeService::handlePost( if (!parsed.has_value()) { return ErrorResponse(ESP_ERR_INVALID_ARG, "invalid KNX config"); } - const esp_err_t err = runtime->saveKnxConfig(parsed.value()); + std::set used_knx_ports; + std::set used_serial_uarts; + collectUsedRuntimeResources(gateway_id.value(), nullptr, &used_knx_ports, + &used_serial_uarts); + const esp_err_t err = runtime->saveKnxConfig(parsed.value(), &used_knx_ports, + &used_serial_uarts); if (err != ESP_OK) { - return ErrorResponse(err, "failed to save KNX bridge config"); + return ErrorResponse(err, runtime->knx_last_error.empty() + ? "failed to save KNX bridge config" + : runtime->knx_last_error.c_str()); } return handleGet("knx", gateway_id.value()); } if (action == "knx_start") { - const esp_err_t err = runtime->startKnx(); + std::set used_knx_ports; + std::set used_serial_uarts; + collectUsedRuntimeResources(gateway_id.value(), nullptr, &used_knx_ports, + &used_serial_uarts); + const esp_err_t err = runtime->startKnx(&used_knx_ports, &used_serial_uarts); if (err != ESP_OK) { - return ErrorResponse(err, "failed to start KNX/IP bridge"); + return ErrorResponse(err, runtime->knx_last_error.empty() + ? "failed to start KNX/IP bridge" + : runtime->knx_last_error.c_str()); } return handleGet("knx", gateway_id.value()); } diff --git a/components/gateway_knx/src/gateway_knx.cpp b/components/gateway_knx/src/gateway_knx.cpp index d192ce6..96feda0 100644 --- a/components/gateway_knx/src/gateway_knx.cpp +++ b/components/gateway_knx/src/gateway_knx.cpp @@ -655,10 +655,18 @@ esp_err_t GatewayKnxTpIpRouter::start(uint32_t task_stack_size, UBaseType_t task } stop_requested_ = false; last_error_.clear(); + if (!configureSocket()) { + return ESP_FAIL; + } + if (!configureTpUart()) { + closeSockets(); + return ESP_FAIL; + } const BaseType_t created = xTaskCreate(&GatewayKnxTpIpRouter::TaskEntry, "gw_knx_ip", task_stack_size, this, task_priority, &task_handle_); if (created != pdPASS) { task_handle_ = nullptr; + closeSockets(); return ESP_ERR_NO_MEM; } started_ = true; @@ -668,6 +676,11 @@ esp_err_t GatewayKnxTpIpRouter::start(uint32_t task_stack_size, UBaseType_t task esp_err_t GatewayKnxTpIpRouter::stop() { stop_requested_ = true; closeSockets(); + const TaskHandle_t current_task = xTaskGetCurrentTaskHandle(); + for (int attempt = 0; task_handle_ != nullptr && task_handle_ != current_task && attempt < 50; + ++attempt) { + vTaskDelay(pdMS_TO_TICKS(10)); + } return ESP_OK; } @@ -680,15 +693,6 @@ void GatewayKnxTpIpRouter::TaskEntry(void* arg) { } void GatewayKnxTpIpRouter::taskLoop() { - if (!configureSocket()) { - finishTask(); - return; - } - if (!configureTpUart()) { - finishTask(); - return; - } - std::array buffer{}; while (!stop_requested_) { sockaddr_in remote{};