feat(gateway): add GatewayNetworkService and enhance runtime channel handling

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Tony
2026-04-29 23:54:33 +08:00
parent 4433fe97c7
commit 52aa2fc129
9 changed files with 661 additions and 12 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
idf_component_register(
SRCS "app_main.cpp"
REQUIRES gateway_core gateway_controller dali_domain gateway_runtime gateway_ble log
REQUIRES gateway_core gateway_controller gateway_network dali_domain gateway_runtime gateway_ble log
)
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
+24
View File
@@ -98,6 +98,18 @@ config GATEWAY_CHANNEL1_SERIAL_RX_BUFFER
range 128 4096
default 512
config GATEWAY_CHANNEL1_SERIAL_TX_BUFFER
int "Serial PHY TX buffer bytes"
depends on GATEWAY_CHANNEL1_PHY_UART1 || GATEWAY_CHANNEL1_PHY_UART2
range 0 4096
default 512
config GATEWAY_CHANNEL1_SERIAL_QUERY_TIMEOUT_MS
int "Serial PHY query timeout ms"
depends on GATEWAY_CHANNEL1_PHY_UART1 || GATEWAY_CHANNEL1_PHY_UART2
range 10 5000
default 500
endmenu
menu "Gateway Channel 2"
@@ -193,6 +205,18 @@ config GATEWAY_CHANNEL2_SERIAL_RX_BUFFER
range 128 4096
default 512
config GATEWAY_CHANNEL2_SERIAL_TX_BUFFER
int "Serial PHY TX buffer bytes"
depends on GATEWAY_CHANNEL_COUNT >= 2 && (GATEWAY_CHANNEL2_PHY_UART1 || GATEWAY_CHANNEL2_PHY_UART2)
range 0 4096
default 512
config GATEWAY_CHANNEL2_SERIAL_QUERY_TIMEOUT_MS
int "Serial PHY query timeout ms"
depends on GATEWAY_CHANNEL_COUNT >= 2 && (GATEWAY_CHANNEL2_PHY_UART1 || GATEWAY_CHANNEL2_PHY_UART2)
range 10 5000
default 500
endmenu
config GATEWAY_ENABLE_DALI_BUS
+150 -9
View File
@@ -2,11 +2,14 @@
#include "gateway_ble.hpp"
#include "gateway_controller.hpp"
#include "gateway_core.hpp"
#include "gateway_network.hpp"
#include "gateway_runtime.hpp"
#include "esp_log.h"
#include "sdkconfig.h"
#include <cstdio>
#include <cstdint>
#include <memory>
#ifndef CONFIG_GATEWAY_CHANNEL_COUNT
@@ -16,10 +19,12 @@
namespace {
constexpr const char* kProjectName = "DALI_485_Gateway";
constexpr const char* kProjectVersion = "0.1.0";
constexpr const char* kTag = "gateway_main";
std::unique_ptr<gateway::DaliDomainService> s_dali_domain;
std::unique_ptr<gateway::GatewayRuntime> s_runtime;
std::unique_ptr<gateway::GatewayController> s_controller;
std::unique_ptr<gateway::GatewayNetworkService> s_network;
std::unique_ptr<gateway::GatewayBleBridge> s_ble_bridge;
[[maybe_unused]] void LogBindError(const char* channel_name, esp_err_t err) {
@@ -28,8 +33,111 @@ std::unique_ptr<gateway::GatewayBleBridge> s_ble_bridge;
}
}
void BindConfiguredChannels(gateway::DaliDomainService& dali_domain,
const gateway::GatewayRuntime& runtime) {
struct ChannelBindingConfig {
bool enabled{false};
bool native_phy{false};
bool serial_phy{false};
uint8_t gateway_id{0};
uint8_t native_bus_id{0};
uint32_t native_baudrate{0};
int uart_port{-1};
};
bool ValidateChannelBindings() {
ChannelBindingConfig channels[CONFIG_GATEWAY_CHANNEL_COUNT] = {};
#if CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE
channels[0].enabled = true;
channels[0].native_phy = true;
channels[0].gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_GW_ID);
channels[0].native_bus_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_NATIVE_BUS_ID);
channels[0].native_baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE);
#elif CONFIG_GATEWAY_CHANNEL1_PHY_UART1
channels[0].enabled = true;
channels[0].serial_phy = true;
channels[0].gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_GW_ID);
channels[0].uart_port = 1;
#elif CONFIG_GATEWAY_CHANNEL1_PHY_UART2
channels[0].enabled = true;
channels[0].serial_phy = true;
channels[0].gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_GW_ID);
channels[0].uart_port = 2;
#endif
#if CONFIG_GATEWAY_CHANNEL_COUNT >= 2
#if CONFIG_GATEWAY_CHANNEL2_PHY_NATIVE
channels[1].enabled = true;
channels[1].native_phy = true;
channels[1].gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_GW_ID);
channels[1].native_bus_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_NATIVE_BUS_ID);
channels[1].native_baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL2_NATIVE_BAUDRATE);
#elif CONFIG_GATEWAY_CHANNEL2_PHY_UART1
channels[1].enabled = true;
channels[1].serial_phy = true;
channels[1].gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_GW_ID);
channels[1].uart_port = 1;
#elif CONFIG_GATEWAY_CHANNEL2_PHY_UART2
channels[1].enabled = true;
channels[1].serial_phy = true;
channels[1].gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_GW_ID);
channels[1].uart_port = 2;
#endif
#endif
bool any_enabled = false;
bool saw_native = false;
uint32_t native_baudrate = 0;
for (int i = 0; i < CONFIG_GATEWAY_CHANNEL_COUNT; ++i) {
if (!channels[i].enabled) {
continue;
}
any_enabled = true;
for (int j = i + 1; j < CONFIG_GATEWAY_CHANNEL_COUNT; ++j) {
if (!channels[j].enabled) {
continue;
}
if (channels[i].gateway_id == channels[j].gateway_id) {
ESP_LOGE(kTag, "duplicate gateway ids configured: %u", channels[i].gateway_id);
return false;
}
if (channels[i].serial_phy && channels[j].serial_phy &&
channels[i].uart_port == channels[j].uart_port) {
ESP_LOGE(kTag, "duplicate serial PHY UART%d configured for multiple channels",
channels[i].uart_port);
return false;
}
if (channels[i].native_phy && channels[j].native_phy &&
channels[i].native_bus_id == channels[j].native_bus_id) {
ESP_LOGE(kTag, "duplicate native DALI bus ids configured: %u",
channels[i].native_bus_id);
return false;
}
}
if (channels[i].native_phy) {
if (!saw_native) {
saw_native = true;
native_baudrate = channels[i].native_baudrate;
} else if (native_baudrate != channels[i].native_baudrate) {
ESP_LOGE(kTag,
"mixed native PHY baudrates are not supported by the shared DALI HAL: %lu vs %lu",
static_cast<unsigned long>(native_baudrate),
static_cast<unsigned long>(channels[i].native_baudrate));
return false;
}
}
}
if (!any_enabled) {
ESP_LOGE(kTag, "no DALI PHY is configured; enable at least one native or serial channel");
return false;
}
return true;
}
esp_err_t BindConfiguredChannels(gateway::DaliDomainService& dali_domain,
const gateway::GatewayRuntime& runtime) {
#if CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE
gateway::DaliHardwareBusConfig channel1{};
channel1.channel_index = 0;
@@ -39,7 +147,11 @@ void BindConfiguredChannels(gateway::DaliDomainService& dali_domain,
channel1.rx_pin = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_NATIVE_RX_PIN);
channel1.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE);
channel1.name = runtime.gatewayName(channel1.gateway_id);
LogBindError("channel1 native DALI", dali_domain.bindHardwareBus(channel1));
esp_err_t err = dali_domain.bindHardwareBus(channel1);
LogBindError("channel1 native DALI", err);
if (err != ESP_OK) {
return err;
}
#elif CONFIG_GATEWAY_CHANNEL1_PHY_UART1 || CONFIG_GATEWAY_CHANNEL1_PHY_UART2
gateway::DaliSerialBusConfig channel1{};
channel1.channel_index = 0;
@@ -53,9 +165,15 @@ void BindConfiguredChannels(gateway::DaliDomainService& dali_domain,
channel1.rx_pin = CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_PIN;
channel1.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL1_SERIAL_BAUDRATE);
channel1.rx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_BUFFER);
channel1.tx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_BUFFER);
channel1.tx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_BUFFER);
channel1.query_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL1_SERIAL_QUERY_TIMEOUT_MS);
channel1.name = runtime.gatewayName(channel1.gateway_id);
LogBindError("channel1 serial DALI", dali_domain.bindSerialBus(channel1));
esp_err_t err = dali_domain.bindSerialBus(channel1);
LogBindError("channel1 serial DALI", err);
if (err != ESP_OK) {
return err;
}
#endif
#if CONFIG_GATEWAY_CHANNEL_COUNT >= 2
@@ -68,7 +186,11 @@ void BindConfiguredChannels(gateway::DaliDomainService& dali_domain,
channel2.rx_pin = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_NATIVE_RX_PIN);
channel2.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL2_NATIVE_BAUDRATE);
channel2.name = runtime.gatewayName(channel2.gateway_id);
LogBindError("channel2 native DALI", dali_domain.bindHardwareBus(channel2));
esp_err_t err = dali_domain.bindHardwareBus(channel2);
LogBindError("channel2 native DALI", err);
if (err != ESP_OK) {
return err;
}
#elif CONFIG_GATEWAY_CHANNEL2_PHY_UART1 || CONFIG_GATEWAY_CHANNEL2_PHY_UART2
gateway::DaliSerialBusConfig channel2{};
channel2.channel_index = 1;
@@ -82,11 +204,19 @@ void BindConfiguredChannels(gateway::DaliDomainService& dali_domain,
channel2.rx_pin = CONFIG_GATEWAY_CHANNEL2_SERIAL_RX_PIN;
channel2.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL2_SERIAL_BAUDRATE);
channel2.rx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_CHANNEL2_SERIAL_RX_BUFFER);
channel2.tx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_CHANNEL2_SERIAL_RX_BUFFER);
channel2.tx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_CHANNEL2_SERIAL_TX_BUFFER);
channel2.query_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL2_SERIAL_QUERY_TIMEOUT_MS);
channel2.name = runtime.gatewayName(channel2.gateway_id);
LogBindError("channel2 serial DALI", dali_domain.bindSerialBus(channel2));
esp_err_t err = dali_domain.bindSerialBus(channel2);
LogBindError("channel2 serial DALI", err);
if (err != ESP_OK) {
return err;
}
#endif
#endif
return ESP_OK;
}
} // namespace
@@ -107,6 +237,8 @@ extern "C" void app_main(void) {
gateway::GatewayCore core(profile);
core.start();
ESP_ERROR_CHECK(ValidateChannelBindings() ? ESP_OK : ESP_ERR_INVALID_STATE);
s_dali_domain = std::make_unique<gateway::DaliDomainService>();
s_runtime = std::make_unique<gateway::GatewayRuntime>(
profile,
@@ -118,7 +250,7 @@ extern "C" void app_main(void) {
s_dali_domain.get());
ESP_ERROR_CHECK(s_runtime->start());
s_runtime->setGatewayCount(CONFIG_GATEWAY_CHANNEL_COUNT);
BindConfiguredChannels(*s_dali_domain, *s_runtime);
ESP_ERROR_CHECK(BindConfiguredChannels(*s_dali_domain, *s_runtime));
gateway::GatewayControllerConfig controller_config;
controller_config.setup_supported = true;
@@ -132,6 +264,15 @@ extern "C" void app_main(void) {
controller_config);
ESP_ERROR_CHECK(s_controller->start());
if (profile.enable_wifi || profile.enable_eth) {
gateway::GatewayNetworkServiceConfig network_config;
network_config.http_enabled = true;
network_config.udp_enabled = true;
s_network = std::make_unique<gateway::GatewayNetworkService>(*s_controller, *s_runtime,
network_config);
ESP_ERROR_CHECK(s_network->start());
}
if (profile.enable_ble) {
s_ble_bridge = std::make_unique<gateway::GatewayBleBridge>(*s_controller, *s_runtime,
*s_dali_domain);