Files
gateway/apps/gateway/main/app_main.cpp
T
Tony 0827befb06 feat(gateway_cache): enhance DALI state management and caching
- Increased flush interval to 10 seconds and added a refresh interval of 120 seconds in GatewayCacheConfig.
- Introduced a new boolean `stale` in GatewayCacheDaliRuntimeStatus to track stale states.
- Added methods for setting actual DALI levels and persisting DALI address states.
- Implemented functions to build and apply DALI state payloads, including handling scene levels.
- Enhanced the GatewayCache class to manage DALI states more effectively, including loading and persisting states.
- Updated GatewayController to support cache refresh operations, including handling cache commands and reporting cache status.
- Added mechanisms for periodic cache refresh based on idle time and configured intervals.

Signed-off-by: Tony <tonylu@tony-cloud.com>
2026-05-21 15:34:26 +08:00

1044 lines
38 KiB
C++

#include "dali_domain.hpp"
#include "gateway_ble.hpp"
#include "gateway_bridge.hpp"
#include "gateway_cache.hpp"
#include "gateway_controller.hpp"
#include "gateway_core.hpp"
#include "gateway_network.hpp"
#include "gateway_runtime.hpp"
#include "gateway_485_control.hpp"
#include "gateway_usb_setup.hpp"
#include "esp_log.h"
#include "sdkconfig.h"
#include <cstdio>
#include <cstdint>
#include <memory>
#ifndef CONFIG_GATEWAY_CHANNEL_COUNT
#define CONFIG_GATEWAY_CHANNEL_COUNT 2
#endif
#ifndef CONFIG_GATEWAY_NETWORK_HTTP_PORT
#define CONFIG_GATEWAY_NETWORK_HTTP_PORT 80
#endif
#ifndef CONFIG_GATEWAY_NETWORK_UDP_PORT
#define CONFIG_GATEWAY_NETWORK_UDP_PORT 2020
#endif
#ifndef CONFIG_GATEWAY_STATUS_LED_GPIO
#define CONFIG_GATEWAY_STATUS_LED_GPIO -1
#endif
#ifndef CONFIG_GATEWAY_BOOT_BUTTON_GPIO
#define CONFIG_GATEWAY_BOOT_BUTTON_GPIO -1
#endif
#ifndef CONFIG_GATEWAY_BOOT_BUTTON_LONG_PRESS_MS
#define CONFIG_GATEWAY_BOOT_BUTTON_LONG_PRESS_MS 3000
#endif
#ifndef CONFIG_GATEWAY_SETUP_AP_BUTTON_GPIO
#ifdef CONFIG_GATEWAY_BOOT_BUTTON_GPIO
#define CONFIG_GATEWAY_SETUP_AP_BUTTON_GPIO CONFIG_GATEWAY_BOOT_BUTTON_GPIO
#ifdef CONFIG_GATEWAY_BOOT_BUTTON_ACTIVE_LOW
#define CONFIG_GATEWAY_SETUP_AP_BUTTON_ACTIVE_LOW 1
#endif
#else
#define CONFIG_GATEWAY_SETUP_AP_BUTTON_GPIO -1
#endif
#endif
#ifndef CONFIG_GATEWAY_BUTTON_TASK_STACK_SIZE
#define CONFIG_GATEWAY_BUTTON_TASK_STACK_SIZE 8192
#endif
#ifndef CONFIG_GATEWAY_USB_SETUP_CHANNEL_INDEX
#define CONFIG_GATEWAY_USB_SETUP_CHANNEL_INDEX 0
#endif
#ifndef CONFIG_GATEWAY_USB_SETUP_RX_BUFFER
#define CONFIG_GATEWAY_USB_SETUP_RX_BUFFER 256
#endif
#ifndef CONFIG_GATEWAY_USB_SETUP_TX_BUFFER
#define CONFIG_GATEWAY_USB_SETUP_TX_BUFFER 256
#endif
#ifndef CONFIG_GATEWAY_USB_SETUP_READ_TIMEOUT_MS
#define CONFIG_GATEWAY_USB_SETUP_READ_TIMEOUT_MS 20
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_BAUDRATE
#define CONFIG_GATEWAY_485_CONTROL_BAUDRATE 9600
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_TX_PIN
#define CONFIG_GATEWAY_485_CONTROL_TX_PIN -1
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_RX_PIN
#define CONFIG_GATEWAY_485_CONTROL_RX_PIN -1
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_RX_BUFFER
#define CONFIG_GATEWAY_485_CONTROL_RX_BUFFER 256
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_TX_BUFFER
#define CONFIG_GATEWAY_485_CONTROL_TX_BUFFER 256
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_READ_TIMEOUT_MS
#define CONFIG_GATEWAY_485_CONTROL_READ_TIMEOUT_MS 20
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_WRITE_TIMEOUT_MS
#define CONFIG_GATEWAY_485_CONTROL_WRITE_TIMEOUT_MS 20
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_TASK_STACK_SIZE
#define CONFIG_GATEWAY_485_CONTROL_TASK_STACK_SIZE 4096
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_TASK_PRIORITY
#define CONFIG_GATEWAY_485_CONTROL_TASK_PRIORITY 4
#endif
#ifndef CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS
#define CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS 2000
#endif
#ifndef CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC
#define CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC 60
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_IGNORE_INIT_FAILURE
#define CONFIG_GATEWAY_ETHERNET_IGNORE_INIT_FAILURE 0
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_SPI_HOST
#define CONFIG_GATEWAY_ETHERNET_W5500_SPI_HOST 1
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_SCLK_GPIO
#define CONFIG_GATEWAY_ETHERNET_W5500_SCLK_GPIO 14
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_MOSI_GPIO
#define CONFIG_GATEWAY_ETHERNET_W5500_MOSI_GPIO 13
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_MISO_GPIO
#define CONFIG_GATEWAY_ETHERNET_W5500_MISO_GPIO 12
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_CS_GPIO
#define CONFIG_GATEWAY_ETHERNET_W5500_CS_GPIO 15
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_INT_GPIO
#define CONFIG_GATEWAY_ETHERNET_W5500_INT_GPIO 4
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_POLL_PERIOD_MS
#define CONFIG_GATEWAY_ETHERNET_W5500_POLL_PERIOD_MS 0
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_W5500_CLOCK_MHZ
#define CONFIG_GATEWAY_ETHERNET_W5500_CLOCK_MHZ 36
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_PHY_RESET_GPIO
#define CONFIG_GATEWAY_ETHERNET_PHY_RESET_GPIO 5
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_PHY_ADDR
#define CONFIG_GATEWAY_ETHERNET_PHY_ADDR 1
#endif
#ifndef CONFIG_GATEWAY_ETHERNET_RX_TASK_STACK_SIZE
#define CONFIG_GATEWAY_ETHERNET_RX_TASK_STACK_SIZE 3072
#endif
#ifndef CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE
#define CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE 6144
#endif
#ifndef CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_PRIORITY
#define CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_PRIORITY 4
#endif
#ifndef CONFIG_GATEWAY_MODBUS_TCP_PORT
#define CONFIG_GATEWAY_MODBUS_TCP_PORT 1502
#endif
#ifndef CONFIG_GATEWAY_MODBUS_UNIT_ID
#define CONFIG_GATEWAY_MODBUS_UNIT_ID 1
#endif
#ifndef CONFIG_GATEWAY_MODBUS_SERIAL_UART_PORT
#define CONFIG_GATEWAY_MODBUS_SERIAL_UART_PORT 1
#endif
#ifndef CONFIG_GATEWAY_MODBUS_SERIAL_TX_PIN
#define CONFIG_GATEWAY_MODBUS_SERIAL_TX_PIN -1
#endif
#ifndef CONFIG_GATEWAY_MODBUS_SERIAL_RX_PIN
#define CONFIG_GATEWAY_MODBUS_SERIAL_RX_PIN -1
#endif
#ifndef CONFIG_GATEWAY_MODBUS_SERIAL_BAUDRATE
#define CONFIG_GATEWAY_MODBUS_SERIAL_BAUDRATE 9600
#endif
#ifndef CONFIG_GATEWAY_MODBUS_SERIAL_RESPONSE_TIMEOUT_MS
#define CONFIG_GATEWAY_MODBUS_SERIAL_RESPONSE_TIMEOUT_MS 20
#endif
#ifndef CONFIG_GATEWAY_MODBUS_SERIAL_RS485_DE_PIN
#define CONFIG_GATEWAY_MODBUS_SERIAL_RS485_DE_PIN -1
#endif
#ifndef CONFIG_GATEWAY_BRIDGE_BACNET_TASK_STACK_SIZE
#define CONFIG_GATEWAY_BRIDGE_BACNET_TASK_STACK_SIZE 8192
#endif
#ifndef CONFIG_GATEWAY_BRIDGE_BACNET_TASK_PRIORITY
#define CONFIG_GATEWAY_BRIDGE_BACNET_TASK_PRIORITY 5
#endif
#ifndef CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE
#define CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE 12288
#endif
#ifndef CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY
#define CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY 5
#endif
#ifndef CONFIG_GATEWAY_KNX_MAIN_GROUP
#define CONFIG_GATEWAY_KNX_MAIN_GROUP 0
#endif
#ifndef CONFIG_GATEWAY_KNX_DALI_BUS_ID
#define CONFIG_GATEWAY_KNX_DALI_BUS_ID 0
#endif
#ifndef CONFIG_GATEWAY_KNX_UDP_PORT
#define CONFIG_GATEWAY_KNX_UDP_PORT 3671
#endif
#ifndef CONFIG_GATEWAY_KNX_MULTICAST_ADDRESS
#define CONFIG_GATEWAY_KNX_MULTICAST_ADDRESS "224.0.23.12"
#endif
#ifndef CONFIG_GATEWAY_KNX_INDIVIDUAL_ADDRESS
#define CONFIG_GATEWAY_KNX_INDIVIDUAL_ADDRESS 65534
#endif
#ifndef CONFIG_GATEWAY_KNX_IP_INTERFACE_INDIVIDUAL_ADDRESS
#define CONFIG_GATEWAY_KNX_IP_INTERFACE_INDIVIDUAL_ADDRESS 65281
#endif
#ifndef CONFIG_GATEWAY_KNX_PROGRAMMING_BUTTON_GPIO
#define CONFIG_GATEWAY_KNX_PROGRAMMING_BUTTON_GPIO -1
#endif
#ifndef CONFIG_GATEWAY_KNX_PROGRAMMING_LED_GPIO
#define CONFIG_GATEWAY_KNX_PROGRAMMING_LED_GPIO -1
#endif
#ifndef CONFIG_GATEWAY_KNX_TP_UART_PORT
#define CONFIG_GATEWAY_KNX_TP_UART_PORT -1
#endif
#ifndef CONFIG_GATEWAY_KNX_TP_TX_PIN
#define CONFIG_GATEWAY_KNX_TP_TX_PIN -1
#endif
#ifndef CONFIG_GATEWAY_KNX_TP_RX_PIN
#define CONFIG_GATEWAY_KNX_TP_RX_PIN -1
#endif
#ifndef CONFIG_GATEWAY_KNX_TP_BAUDRATE
#define CONFIG_GATEWAY_KNX_TP_BAUDRATE 19200
#endif
#ifndef CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS
#define CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS 10000
#endif
#ifndef CONFIG_GATEWAY_CACHE_REFRESH_INTERVAL_MS
#define CONFIG_GATEWAY_CACHE_REFRESH_INTERVAL_MS 120000
#endif
namespace {
constexpr const char* kProjectName = "DALI_485_Gateway";
constexpr const char* kProjectVersion = "0.1.0";
constexpr const char* kTag = "gateway_main";
#ifdef CONFIG_GATEWAY_WIFI_SUPPORTED
constexpr bool kWifiSupported = true;
#else
constexpr bool kWifiSupported = false;
#endif
#ifdef CONFIG_GATEWAY_ETHERNET_SUPPORTED
constexpr bool kEthernetSupported = true;
#else
constexpr bool kEthernetSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_WIFI_STA_ENABLED
constexpr bool kWifiStartupEnabled = true;
#else
constexpr bool kWifiStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_START_ETHERNET_ENABLED
constexpr bool kEthernetStartupEnabled = true;
#else
constexpr bool kEthernetStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_BLE_SUPPORTED
constexpr bool kBleSupported = true;
#else
constexpr bool kBleSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_BLE_ENABLED
constexpr bool kBleStartupEnabled = true;
#else
constexpr bool kBleStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_ESPNOW_SETUP_SUPPORTED
constexpr bool kEspnowSetupSupported = true;
#else
constexpr bool kEspnowSetupSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_ESPNOW_SETUP_ENABLED
constexpr bool kEspnowSetupStartupEnabled = true;
#else
constexpr bool kEspnowSetupStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_SMARTCONFIG_SUPPORTED
constexpr bool kSmartconfigSupported = true;
#else
constexpr bool kSmartconfigSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_SMARTCONFIG_ENABLED
constexpr bool kSmartconfigStartupEnabled = true;
#else
constexpr bool kSmartconfigStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_USB_STARTUP_SETUP_SERIAL
constexpr bool kUsbSetupStartupEnabled = true;
#else
constexpr bool kUsbSetupStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_BRIDGE_SUPPORTED
constexpr bool kBridgeSupported = true;
#else
constexpr bool kBridgeSupported = false;
#endif
#ifdef CONFIG_GATEWAY_MODBUS_BRIDGE_SUPPORTED
constexpr bool kModbusBridgeSupported = true;
#else
constexpr bool kModbusBridgeSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_MODBUS_BRIDGE_ENABLED
constexpr bool kModbusBridgeStartupEnabled = true;
#else
constexpr bool kModbusBridgeStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_BACNET_BRIDGE_SUPPORTED
constexpr bool kBacnetBridgeSupported = true;
#else
constexpr bool kBacnetBridgeSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_BACNET_BRIDGE_ENABLED
constexpr bool kBacnetBridgeStartupEnabled = true;
#else
constexpr bool kBacnetBridgeStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_KNX_BRIDGE_SUPPORTED
constexpr bool kKnxBridgeSupported = true;
#else
constexpr bool kKnxBridgeSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_KNX_BRIDGE_ENABLED
constexpr bool kKnxBridgeStartupEnabled = true;
#else
constexpr bool kKnxBridgeStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_KNX_TUNNEL_ENABLED
constexpr bool kKnxTunnelEnabled = true;
#else
constexpr bool kKnxTunnelEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_KNX_MULTICAST_ENABLED
constexpr bool kKnxMulticastEnabled = true;
#else
constexpr bool kKnxMulticastEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED
constexpr bool kCloudBridgeSupported = true;
#else
constexpr bool kCloudBridgeSupported = false;
#endif
#ifdef CONFIG_GATEWAY_START_CLOUD_BRIDGE_ENABLED
constexpr bool kCloudBridgeStartupEnabled = true;
#else
constexpr bool kCloudBridgeStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_CACHE_SUPPORTED
constexpr bool kCacheSupported = true;
#else
constexpr bool kCacheSupported = false;
#endif
#ifdef CONFIG_GATEWAY_CACHE_START_ENABLED
constexpr bool kCacheStartupEnabled = true;
#else
constexpr bool kCacheStartupEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED
constexpr bool kCacheReconciliationEnabled = true;
#else
constexpr bool kCacheReconciliationEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_CACHE_FULL_STATE_MIRROR
constexpr bool kCacheFullStateMirrorEnabled = true;
#else
constexpr bool kCacheFullStateMirrorEnabled = false;
#endif
#ifdef CONFIG_GATEWAY_CACHE_LOCAL_GATEWAY_FIRST
constexpr gateway::GatewayCachePriorityMode kCachePriorityMode =
gateway::GatewayCachePriorityMode::kLocalGatewayFirst;
#else
constexpr gateway::GatewayCachePriorityMode kCachePriorityMode =
gateway::GatewayCachePriorityMode::kOutsideBusFirst;
#endif
#if defined(CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_RTU) || \
defined(CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_ASCII)
constexpr bool kModbusDefaultSerialTransport = true;
#else
constexpr bool kModbusDefaultSerialTransport = false;
#endif
#ifdef CONFIG_GATEWAY_MODBUS_ALLOW_UART0
constexpr bool kModbusAllowUart0 = true;
#else
constexpr bool kModbusAllowUart0 = false;
#endif
#ifdef CONFIG_GATEWAY_485_CONTROL_ENABLED
constexpr bool k485ControlEnabled = true;
#else
constexpr bool k485ControlEnabled = false;
#endif
#if defined(CONFIG_ESP_CONSOLE_UART) && defined(CONFIG_ESP_CONSOLE_UART_NUM) && CONFIG_ESP_CONSOLE_UART_NUM == 0
constexpr bool kConsoleOnUart0 = true;
#elif defined(CONFIG_CONSOLE_UART) && defined(CONFIG_CONSOLE_UART_NUM) && CONFIG_CONSOLE_UART_NUM == 0
constexpr bool kConsoleOnUart0 = true;
#else
constexpr bool kConsoleOnUart0 = false;
#endif
#ifdef CONFIG_GATEWAY_MODBUS_SERIAL_RS485_ENABLED
constexpr bool kModbusSerialRs485Enabled = true;
#else
constexpr bool kModbusSerialRs485Enabled = false;
#endif
std::unique_ptr<gateway::DaliDomainService> s_dali_domain;
std::unique_ptr<gateway::GatewayRuntime> s_runtime;
std::unique_ptr<gateway::GatewayCache> s_cache;
std::unique_ptr<gateway::GatewayController> s_controller;
std::unique_ptr<gateway::GatewayBridgeService> s_bridge;
std::unique_ptr<gateway::GatewayNetworkService> s_network;
std::unique_ptr<gateway::GatewayBleBridge> s_ble_bridge;
std::unique_ptr<gateway::Gateway485ControlBridge> s_uart0_control_bridge;
std::unique_ptr<gateway::GatewayUsbSetupBridge> s_usb_setup_bridge;
[[maybe_unused]] void LogBindError(const char* channel_name, esp_err_t err) {
if (err != ESP_OK) {
std::printf("gateway_main: failed to bind %s err=%d\n", channel_name, err);
}
}
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() {
if (k485ControlEnabled && kConsoleOnUart0) {
ESP_LOGE(kTag, "485 control bridge requires moving the ESP-IDF console off UART0");
return false;
}
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 (kModbusBridgeSupported && kModbusDefaultSerialTransport) {
const int modbus_uart = CONFIG_GATEWAY_MODBUS_SERIAL_UART_PORT;
if (k485ControlEnabled && modbus_uart == 0) {
ESP_LOGE(kTag, "Modbus serial UART0 conflicts with the UART0 control bridge");
return false;
}
if (modbus_uart == 0 && !kModbusAllowUart0) {
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",
modbus_uart, i + 1);
return false;
}
}
}
if (kKnxBridgeSupported) {
const int knx_uart = CONFIG_GATEWAY_KNX_TP_UART_PORT;
if (kKnxBridgeStartupEnabled) {
const uint8_t knx_dali_bus_id = static_cast<uint8_t>(CONFIG_GATEWAY_KNX_DALI_BUS_ID);
int matches = 0;
for (int i = 0; i < CONFIG_GATEWAY_CHANNEL_COUNT; ++i) {
if (channels[i].enabled && channels[i].native_phy &&
channels[i].native_bus_id == knx_dali_bus_id) {
++matches;
}
}
if (matches != 1) {
ESP_LOGE(kTag,
"KNX DALI bus id %u must match exactly one enabled native DALI channel",
knx_dali_bus_id);
return false;
}
}
if (knx_uart >= 0 && k485ControlEnabled && knx_uart == 0) {
ESP_LOGE(kTag, "KNX TP UART0 conflicts with the UART0 control bridge");
return false;
}
if (knx_uart >= 0 && knx_uart == 0 && kConsoleOnUart0) {
ESP_LOGE(kTag, "KNX TP-UART on UART0 requires moving the ESP-IDF console off UART0");
return false;
}
if (knx_uart >= 0 && 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);
return false;
}
for (int i = 0; i < CONFIG_GATEWAY_CHANNEL_COUNT; ++i) {
if (knx_uart >= 0 && channels[i].enabled && channels[i].serial_phy &&
channels[i].uart_port == knx_uart) {
ESP_LOGE(kTag, "KNX TP UART%d conflicts with DALI channel %d serial PHY", knx_uart,
i + 1);
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;
channel1.gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_GW_ID);
channel1.bus_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_NATIVE_BUS_ID);
channel1.tx_pin = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_NATIVE_TX_PIN);
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);
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;
channel1.gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL1_GW_ID);
#if CONFIG_GATEWAY_CHANNEL1_PHY_UART1
channel1.uart_port = 1;
#else
channel1.uart_port = 2;
#endif
channel1.tx_pin = CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_PIN;
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_TX_BUFFER);
channel1.query_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL1_SERIAL_QUERY_TIMEOUT_MS);
channel1.name = runtime.gatewayName(channel1.gateway_id);
esp_err_t err1 = dali_domain.bindSerialBus(channel1);
LogBindError("channel1 serial DALI", err1);
if (err1 != ESP_OK) {
return err1;
}
#endif
#if CONFIG_GATEWAY_CHANNEL_COUNT >= 2
#if CONFIG_GATEWAY_CHANNEL2_PHY_NATIVE
gateway::DaliHardwareBusConfig channel2{};
channel2.channel_index = 1;
channel2.gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_GW_ID);
channel2.bus_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_NATIVE_BUS_ID);
channel2.tx_pin = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_NATIVE_TX_PIN);
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);
esp_err_t err2 = dali_domain.bindHardwareBus(channel2);
LogBindError("channel2 native DALI", err2);
if (err2 != ESP_OK) {
return err2;
}
#elif CONFIG_GATEWAY_CHANNEL2_PHY_UART1 || CONFIG_GATEWAY_CHANNEL2_PHY_UART2
gateway::DaliSerialBusConfig channel2{};
channel2.channel_index = 1;
channel2.gateway_id = static_cast<uint8_t>(CONFIG_GATEWAY_CHANNEL2_GW_ID);
#if CONFIG_GATEWAY_CHANNEL2_PHY_UART1
channel2.uart_port = 1;
#else
channel2.uart_port = 2;
#endif
channel2.tx_pin = CONFIG_GATEWAY_CHANNEL2_SERIAL_TX_PIN;
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_TX_BUFFER);
channel2.query_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_CHANNEL2_SERIAL_QUERY_TIMEOUT_MS);
channel2.name = runtime.gatewayName(channel2.gateway_id);
esp_err_t err2 = dali_domain.bindSerialBus(channel2);
LogBindError("channel2 serial DALI", err2);
if (err2 != ESP_OK) {
return err2;
}
#endif
#endif
return ESP_OK;
}
} // namespace
extern "C" void app_main(void) {
ESP_ERROR_CHECK(gateway::InitializeRuntimeNvs());
const gateway::BootProfile profile{
gateway::AppRole::kGateway,
"gateway",
kWifiSupported,
kBleSupported,
kEthernetSupported,
kEspnowSetupSupported,
kUsbSetupStartupEnabled,
};
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,
gateway::GatewayRuntimeConfig{
kProjectName,
kProjectVersion,
gateway::ReadRuntimeSerialId(),
kBleStartupEnabled,
kCacheSupported && kCacheStartupEnabled,
},
s_dali_domain.get());
ESP_ERROR_CHECK(s_runtime->start());
s_runtime->setGatewayCount(CONFIG_GATEWAY_CHANNEL_COUNT);
ESP_ERROR_CHECK(BindConfiguredChannels(*s_dali_domain, *s_runtime));
gateway::GatewayCacheConfig cache_config;
cache_config.cache_enabled = kCacheSupported && kCacheStartupEnabled && s_runtime->cacheEnabled();
cache_config.reconciliation_enabled = cache_config.cache_enabled && kCacheReconciliationEnabled;
cache_config.full_state_mirror_enabled = cache_config.reconciliation_enabled &&
kCacheFullStateMirrorEnabled;
cache_config.flush_interval_ms = static_cast<uint32_t>(CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS);
cache_config.refresh_interval_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_CACHE_REFRESH_INTERVAL_MS);
cache_config.default_priority_mode = kCachePriorityMode;
s_cache = std::make_unique<gateway::GatewayCache>(cache_config);
ESP_ERROR_CHECK(s_cache->start());
gateway::GatewayControllerConfig controller_config;
const bool network_transport_supported = profile.enable_wifi || profile.enable_eth;
controller_config.setup_supported = true;
controller_config.ble_supported = profile.enable_ble;
controller_config.wifi_supported = profile.enable_wifi;
controller_config.ip_router_supported = network_transport_supported;
controller_config.internal_scene_supported = true;
controller_config.internal_group_supported = true;
controller_config.cache_supported = kCacheSupported;
controller_config.cache_refresh_interval_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_CACHE_REFRESH_INTERVAL_MS);
s_controller = std::make_unique<gateway::GatewayController>(*s_runtime, *s_dali_domain,
*s_cache,
controller_config);
if (k485ControlEnabled) {
gateway::Gateway485ControlBridgeConfig gateway485_config;
gateway485_config.enabled = true;
gateway485_config.tx_pin = CONFIG_GATEWAY_485_CONTROL_TX_PIN;
gateway485_config.rx_pin = CONFIG_GATEWAY_485_CONTROL_RX_PIN;
gateway485_config.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_485_CONTROL_BAUDRATE);
gateway485_config.rx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_485_CONTROL_RX_BUFFER);
gateway485_config.tx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_485_CONTROL_TX_BUFFER);
gateway485_config.read_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_485_CONTROL_READ_TIMEOUT_MS);
gateway485_config.write_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_485_CONTROL_WRITE_TIMEOUT_MS);
gateway485_config.task_stack_size =
static_cast<uint32_t>(CONFIG_GATEWAY_485_CONTROL_TASK_STACK_SIZE);
gateway485_config.task_priority =
static_cast<UBaseType_t>(CONFIG_GATEWAY_485_CONTROL_TASK_PRIORITY);
s_uart0_control_bridge = std::make_unique<gateway::Gateway485ControlBridge>(*s_controller,
gateway485_config);
ESP_ERROR_CHECK(s_uart0_control_bridge->start());
}
ESP_ERROR_CHECK(s_controller->start());
if (kBridgeSupported) {
gateway::GatewayBridgeServiceConfig bridge_config;
bridge_config.bridge_enabled = true;
bridge_config.modbus_enabled = kModbusBridgeSupported;
bridge_config.modbus_startup_enabled = kModbusBridgeSupported && kModbusBridgeStartupEnabled;
bridge_config.bacnet_enabled = network_transport_supported && kBacnetBridgeSupported;
bridge_config.bacnet_startup_enabled = network_transport_supported && kBacnetBridgeSupported &&
kBacnetBridgeStartupEnabled;
bridge_config.knx_enabled = network_transport_supported && kKnxBridgeSupported;
bridge_config.knx_startup_enabled = network_transport_supported && kKnxBridgeSupported &&
kKnxBridgeStartupEnabled;
bridge_config.cloud_enabled = network_transport_supported && kCloudBridgeSupported;
bridge_config.cloud_startup_enabled = network_transport_supported && kCloudBridgeSupported &&
kCloudBridgeStartupEnabled;
bridge_config.modbus_task_stack_size =
static_cast<uint32_t>(CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE);
bridge_config.modbus_task_priority =
static_cast<UBaseType_t>(CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_PRIORITY);
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
bridge_config.reserved_uart_ports.push_back(2);
#endif
#if CONFIG_GATEWAY_CHANNEL_COUNT >= 2
#if CONFIG_GATEWAY_CHANNEL2_PHY_UART1
bridge_config.reserved_uart_ports.push_back(1);
#elif CONFIG_GATEWAY_CHANNEL2_PHY_UART2
bridge_config.reserved_uart_ports.push_back(2);
#endif
#endif
if (kModbusBridgeSupported) {
gateway::GatewayModbusConfig default_modbus;
#if defined(CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_RTU)
default_modbus.transport = "rtu-server";
#elif defined(CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_ASCII)
default_modbus.transport = "ascii-server";
#else
default_modbus.transport = "tcp-server";
#endif
default_modbus.port = static_cast<uint16_t>(CONFIG_GATEWAY_MODBUS_TCP_PORT);
default_modbus.unit_id = static_cast<uint8_t>(CONFIG_GATEWAY_MODBUS_UNIT_ID);
default_modbus.serial.uart_port = CONFIG_GATEWAY_MODBUS_SERIAL_UART_PORT;
default_modbus.serial.tx_pin = CONFIG_GATEWAY_MODBUS_SERIAL_TX_PIN;
default_modbus.serial.rx_pin = CONFIG_GATEWAY_MODBUS_SERIAL_RX_PIN;
default_modbus.serial.baudrate =
static_cast<uint32_t>(CONFIG_GATEWAY_MODBUS_SERIAL_BAUDRATE);
default_modbus.serial.response_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_MODBUS_SERIAL_RESPONSE_TIMEOUT_MS);
default_modbus.serial.rs485.enabled = kModbusSerialRs485Enabled;
default_modbus.serial.rs485.de_pin = CONFIG_GATEWAY_MODBUS_SERIAL_RS485_DE_PIN;
bridge_config.default_modbus_config = default_modbus;
}
bridge_config.bacnet_task_stack_size =
static_cast<uint32_t>(CONFIG_GATEWAY_BRIDGE_BACNET_TASK_STACK_SIZE);
bridge_config.bacnet_task_priority =
static_cast<UBaseType_t>(CONFIG_GATEWAY_BRIDGE_BACNET_TASK_PRIORITY);
if (kKnxBridgeSupported) {
gateway::GatewayKnxConfig default_knx;
default_knx.dali_router_enabled = true;
default_knx.ip_router_enabled = true;
default_knx.tunnel_enabled = kKnxTunnelEnabled;
default_knx.multicast_enabled = kKnxMulticastEnabled;
default_knx.main_group = static_cast<uint8_t>(CONFIG_GATEWAY_KNX_MAIN_GROUP);
default_knx.dali_bus_id = static_cast<uint8_t>(CONFIG_GATEWAY_KNX_DALI_BUS_ID);
default_knx.udp_port = static_cast<uint16_t>(CONFIG_GATEWAY_KNX_UDP_PORT);
default_knx.multicast_address = CONFIG_GATEWAY_KNX_MULTICAST_ADDRESS;
default_knx.ip_interface_individual_address =
static_cast<uint16_t>(CONFIG_GATEWAY_KNX_IP_INTERFACE_INDIVIDUAL_ADDRESS);
default_knx.individual_address =
static_cast<uint16_t>(CONFIG_GATEWAY_KNX_INDIVIDUAL_ADDRESS);
default_knx.programming_button_gpio = CONFIG_GATEWAY_KNX_PROGRAMMING_BUTTON_GPIO;
default_knx.programming_led_gpio = CONFIG_GATEWAY_KNX_PROGRAMMING_LED_GPIO;
#ifdef CONFIG_GATEWAY_KNX_PROGRAMMING_BUTTON_ACTIVE_LOW
default_knx.programming_button_active_low = true;
#else
default_knx.programming_button_active_low = false;
#endif
#ifdef CONFIG_GATEWAY_KNX_PROGRAMMING_LED_ACTIVE_HIGH
default_knx.programming_led_active_high = true;
#else
default_knx.programming_led_active_high = false;
#endif
default_knx.tp_uart.uart_port = CONFIG_GATEWAY_KNX_TP_UART_PORT;
default_knx.tp_uart.tx_pin = CONFIG_GATEWAY_KNX_TP_TX_PIN;
default_knx.tp_uart.rx_pin = CONFIG_GATEWAY_KNX_TP_RX_PIN;
default_knx.tp_uart.baudrate = static_cast<uint32_t>(CONFIG_GATEWAY_KNX_TP_BAUDRATE);
default_knx.tp_uart.startup_timeout_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS);
#ifdef CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE
default_knx.tp_uart.nine_bit_mode = true;
#else
default_knx.tp_uart.nine_bit_mode = false;
#endif
bridge_config.default_knx_config = default_knx;
}
bridge_config.knx_task_stack_size =
static_cast<uint32_t>(CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE);
bridge_config.knx_task_priority =
static_cast<UBaseType_t>(CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY);
s_bridge = std::make_unique<gateway::GatewayBridgeService>(*s_dali_domain, *s_cache,
bridge_config);
s_controller->setBridgeService(s_bridge.get());
}
if (profile.enable_wifi || profile.enable_eth) {
gateway::GatewayNetworkServiceConfig network_config;
network_config.wifi_enabled = profile.enable_wifi && kWifiStartupEnabled;
network_config.ethernet_enabled = profile.enable_eth && kEthernetStartupEnabled;
#if CONFIG_GATEWAY_ETHERNET_IGNORE_INIT_FAILURE
network_config.ethernet_ignore_init_failure = true;
#else
network_config.ethernet_ignore_init_failure = false;
#endif
network_config.espnow_setup_enabled = profile.enable_espnow;
network_config.espnow_setup_startup_enabled =
profile.enable_espnow && kEspnowSetupStartupEnabled;
network_config.smartconfig_enabled = profile.enable_wifi && kSmartconfigSupported;
network_config.smartconfig_startup_enabled =
profile.enable_wifi && kSmartconfigSupported && kSmartconfigStartupEnabled;
network_config.smartconfig_timeout_sec = CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC;
#ifdef CONFIG_GATEWAY_NETWORK_HTTP_ENABLED
network_config.http_enabled = true;
#else
network_config.http_enabled = false;
#endif
#ifdef CONFIG_GATEWAY_NETWORK_UDP_ROUTER_ENABLED
network_config.udp_enabled = true;
#else
network_config.udp_enabled = false;
#endif
network_config.http_port = static_cast<uint16_t>(CONFIG_GATEWAY_NETWORK_HTTP_PORT);
network_config.udp_port = static_cast<uint16_t>(CONFIG_GATEWAY_NETWORK_UDP_PORT);
network_config.ethernet_spi_host = CONFIG_GATEWAY_ETHERNET_W5500_SPI_HOST;
network_config.ethernet_spi_sclk_gpio = CONFIG_GATEWAY_ETHERNET_W5500_SCLK_GPIO;
network_config.ethernet_spi_mosi_gpio = CONFIG_GATEWAY_ETHERNET_W5500_MOSI_GPIO;
network_config.ethernet_spi_miso_gpio = CONFIG_GATEWAY_ETHERNET_W5500_MISO_GPIO;
network_config.ethernet_spi_cs_gpio = CONFIG_GATEWAY_ETHERNET_W5500_CS_GPIO;
network_config.ethernet_spi_int_gpio = CONFIG_GATEWAY_ETHERNET_W5500_INT_GPIO;
network_config.ethernet_poll_period_ms =
static_cast<uint32_t>(CONFIG_GATEWAY_ETHERNET_W5500_POLL_PERIOD_MS);
network_config.ethernet_spi_clock_mhz =
static_cast<uint8_t>(CONFIG_GATEWAY_ETHERNET_W5500_CLOCK_MHZ);
network_config.ethernet_phy_reset_gpio = CONFIG_GATEWAY_ETHERNET_PHY_RESET_GPIO;
network_config.ethernet_phy_addr = CONFIG_GATEWAY_ETHERNET_PHY_ADDR;
network_config.ethernet_rx_task_stack_size =
static_cast<uint32_t>(CONFIG_GATEWAY_ETHERNET_RX_TASK_STACK_SIZE);
network_config.status_led_gpio = CONFIG_GATEWAY_STATUS_LED_GPIO;
network_config.boot_button_gpio = CONFIG_GATEWAY_BOOT_BUTTON_GPIO;
network_config.setup_ap_button_gpio = CONFIG_GATEWAY_SETUP_AP_BUTTON_GPIO;
network_config.boot_button_long_press_ms = CONFIG_GATEWAY_BOOT_BUTTON_LONG_PRESS_MS;
network_config.boot_button_task_stack_size =
static_cast<uint32_t>(CONFIG_GATEWAY_BUTTON_TASK_STACK_SIZE);
#ifdef CONFIG_GATEWAY_STATUS_LED_ACTIVE_HIGH
network_config.status_led_active_high = true;
#else
network_config.status_led_active_high = false;
#endif
#ifdef CONFIG_GATEWAY_BOOT_BUTTON_ACTIVE_LOW
network_config.boot_button_active_low = true;
#else
network_config.boot_button_active_low = false;
#endif
#ifdef CONFIG_GATEWAY_SETUP_AP_BUTTON_ACTIVE_LOW
network_config.setup_ap_button_active_low = true;
#else
network_config.setup_ap_button_active_low = false;
#endif
s_network = std::make_unique<gateway::GatewayNetworkService>(*s_controller, *s_runtime,
*s_dali_domain, network_config,
s_bridge.get());
ESP_ERROR_CHECK(s_network->start());
}
if (s_bridge != nullptr) {
ESP_ERROR_CHECK(s_bridge->start());
}
if (profile.enable_ble) {
s_ble_bridge = std::make_unique<gateway::GatewayBleBridge>(*s_controller, *s_runtime,
*s_dali_domain);
ESP_ERROR_CHECK(s_ble_bridge->start());
}
if (profile.enable_usb) {
gateway::GatewayUsbSetupBridgeConfig usb_config;
usb_config.enabled = true;
usb_config.channel_index = static_cast<uint8_t>(CONFIG_GATEWAY_USB_SETUP_CHANNEL_INDEX);
usb_config.rx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_USB_SETUP_RX_BUFFER);
usb_config.tx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_USB_SETUP_TX_BUFFER);
usb_config.read_timeout_ms = static_cast<uint32_t>(CONFIG_GATEWAY_USB_SETUP_READ_TIMEOUT_MS);
s_usb_setup_bridge = std::make_unique<gateway::GatewayUsbSetupBridge>(*s_controller,
*s_dali_domain,
usb_config);
ESP_ERROR_CHECK(s_usb_setup_bridge->start());
}
const auto device_info = s_runtime->deviceInfo();
std::printf("gateway_main: dali domain implementation=%s bound=%d channels=%u\n",
s_dali_domain->implementationName(), s_dali_domain->isBound(),
static_cast<unsigned>(s_dali_domain->channelCount()));
for (const auto& channel : s_dali_domain->channelInfo()) {
std::printf("gateway_main: channel=%u gateway=%u name=%s\n", channel.channel_index,
channel.gateway_id, channel.name.c_str());
}
std::printf("gateway_main: runtime device type=%s serial=%s project=%s version=%s\n",
device_info.type.c_str(), device_info.serial_id.c_str(),
device_info.project.c_str(), device_info.version.c_str());
}