Implement KNX Gateway functionality with support for DALI integration

- Added gateway_knx.cpp to handle KNX communication and DALI bridge requests.
- Implemented functions for encoding/decoding KNX telegrams and managing group writes.
- Introduced GatewayKnxBridge and GatewayKnxTpIpRouter classes for managing KNX to DALI routing and IP tunneling.
- Added configuration handling for KNX settings, including UART and multicast options.
- Implemented error handling and logging for various KNX operations.

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-08 18:19:37 +08:00
parent 029785ff1d
commit 1a8ee06ec1
10 changed files with 1589 additions and 5 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
idf_component_register(
SRCS "app_main.cpp"
REQUIRES gateway_core gateway_controller gateway_network gateway_bridge gateway_cache dali_domain gateway_runtime gateway_ble gateway_usb_setup gateway_485_control log
REQUIRES gateway_core gateway_controller gateway_network gateway_bridge gateway_cache dali_domain gateway_runtime gateway_ble gateway_usb_setup gateway_485_control gateway_knx log
)
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
+92
View File
@@ -501,6 +501,98 @@ config GATEWAY_START_BACNET_BRIDGE_ENABLED
help
Starts configured BACnet/IP object bindings at boot. Disabled by default so the UDP BACnet/IP port is opened only after provisioning or explicit runtime start.
config GATEWAY_KNX_BRIDGE_SUPPORTED
bool "KNX to DALI bridge is supported"
depends on GATEWAY_BRIDGE_SUPPORTED && GATEWAY_WIFI_SUPPORTED
default n
help
Enables the gateway-owned KNX group-address router and KNXnet/IP TP/IP
router. Group addresses use the configured main group, middle groups as
DALI data types, and subgroups matching DALI short address structure.
config GATEWAY_START_KNX_BRIDGE_ENABLED
bool "Start KNX/IP bridge at startup"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
default n
help
Starts the KNXnet/IP tunneling/multicast listener at boot. Disabled by
default so UDP port 3671 is opened only after provisioning or explicit start.
config GATEWAY_KNX_MAIN_GROUP
int "KNX DALI main group"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 0 31
default 0
help
Main group used by the built-in KNX to DALI router. Middle groups select
the data type and subgroups select broadcast, short-address, or group targets.
config GATEWAY_KNX_TUNNEL_ENABLED
bool "Enable KNXnet/IP tunneling mode"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
default y
config GATEWAY_KNX_MULTICAST_ENABLED
bool "Enable KNXnet/IP multicast routing mode"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
default y
config GATEWAY_KNX_UDP_PORT
int "KNXnet/IP UDP port"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 1 65535
default 3671
config GATEWAY_KNX_MULTICAST_ADDRESS
string "KNXnet/IP multicast address"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED && GATEWAY_KNX_MULTICAST_ENABLED
default "224.0.23.12"
config GATEWAY_KNX_INDIVIDUAL_ADDRESS
int "KNX individual address raw value"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 0 65535
default 4353
help
Raw 16-bit individual address advertised to KNXnet/IP tunnel clients.
The default 4353 is 1.1.1.
config GATEWAY_KNX_TP_UART_PORT
int "KNX TP UART port"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 0 2
default 1
config GATEWAY_KNX_TP_TX_PIN
int "KNX TP UART TX pin"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range -1 48
default -1
config GATEWAY_KNX_TP_RX_PIN
int "KNX TP UART RX pin"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range -1 48
default -1
config GATEWAY_KNX_TP_BAUDRATE
int "KNX TP UART baudrate"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 1200 921600
default 19200
config GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE
int "KNX/IP bridge task stack bytes"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 6144 24576
default 8192
config GATEWAY_BRIDGE_KNX_TASK_PRIORITY
int "KNX/IP bridge task priority"
depends on GATEWAY_KNX_BRIDGE_SUPPORTED
range 1 10
default 5
config GATEWAY_CLOUD_BRIDGE_SUPPORTED
bool "MQTT cloud bridge is supported"
depends on GATEWAY_BRIDGE_SUPPORTED && GATEWAY_WIFI_SUPPORTED
+111
View File
@@ -144,6 +144,46 @@
#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 8192
#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_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 4353
#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 5000
#endif
@@ -237,6 +277,30 @@ constexpr bool kBacnetBridgeStartupEnabled = true;
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
@@ -449,6 +513,26 @@ bool ValidateChannelBindings() {
}
}
if (kKnxBridgeSupported) {
const int knx_uart = CONFIG_GATEWAY_KNX_TP_UART_PORT;
if (k485ControlEnabled && knx_uart == 0) {
ESP_LOGE(kTag, "KNX TP UART0 conflicts with the UART0 control bridge");
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);
return false;
}
for (int i = 0; i < CONFIG_GATEWAY_CHANNEL_COUNT; ++i) {
if (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;
@@ -626,6 +710,9 @@ extern "C" void app_main(void) {
bridge_config.bacnet_enabled = profile.enable_wifi && kBacnetBridgeSupported;
bridge_config.bacnet_startup_enabled = profile.enable_wifi && kBacnetBridgeSupported &&
kBacnetBridgeStartupEnabled;
bridge_config.knx_enabled = profile.enable_wifi && kKnxBridgeSupported;
bridge_config.knx_startup_enabled = profile.enable_wifi && kKnxBridgeSupported &&
kKnxBridgeStartupEnabled;
bridge_config.cloud_enabled = profile.enable_wifi && kCloudBridgeSupported;
bridge_config.cloud_startup_enabled = profile.enable_wifi && kCloudBridgeSupported &&
kCloudBridgeStartupEnabled;
@@ -649,6 +736,9 @@ 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)
@@ -675,6 +765,27 @@ extern "C" void app_main(void) {
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.udp_port = static_cast<uint16_t>(CONFIG_GATEWAY_KNX_UDP_PORT);
default_knx.multicast_address = CONFIG_GATEWAY_KNX_MULTICAST_ADDRESS;
default_knx.individual_address =
static_cast<uint16_t>(CONFIG_GATEWAY_KNX_INDIVIDUAL_ADDRESS);
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);
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);
}
+1
View File
@@ -666,6 +666,7 @@ CONFIG_GATEWAY_MODBUS_TCP_PORT=1502
CONFIG_GATEWAY_MODBUS_UNIT_ID=1
CONFIG_GATEWAY_BACNET_BRIDGE_SUPPORTED=y
# CONFIG_GATEWAY_START_BACNET_BRIDGE_ENABLED is not set
# CONFIG_GATEWAY_KNX_BRIDGE_SUPPORTED is not set
CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED=y
# CONFIG_GATEWAY_START_CLOUD_BRIDGE_ENABLED is not set
CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE=6144