feat(gateway): enhance DALI and KNX handling with broadcast management support and configurable task stack size
Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -1577,6 +1577,15 @@ config GATEWAY_DALI_BAUDRATE
|
||||
help
|
||||
Runtime baudrate used when initializing the local DALI bus.
|
||||
|
||||
config GATEWAY_CONTROLLER_TASK_STACK_SIZE
|
||||
int "Gateway controller task stack bytes"
|
||||
range 6144 24576
|
||||
default 12288
|
||||
help
|
||||
Stack used by the gateway command controller. BLE bridge transport
|
||||
requests are decoded in this task and may execute JSON-heavy bridge
|
||||
management actions such as KNX programming-mode changes.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Connectivity Startup"
|
||||
|
||||
@@ -164,6 +164,10 @@
|
||||
#define CONFIG_GATEWAY_ETHERNET_RX_TASK_STACK_SIZE 3072
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_GATEWAY_CONTROLLER_TASK_STACK_SIZE
|
||||
#define CONFIG_GATEWAY_CONTROLLER_TASK_STACK_SIZE 12288
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE
|
||||
#define CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE 6144
|
||||
#endif
|
||||
@@ -978,6 +982,8 @@ extern "C" void app_main(void) {
|
||||
ESP_ERROR_CHECK(s_cache->start());
|
||||
|
||||
gateway::GatewayControllerConfig controller_config;
|
||||
controller_config.task_stack_size =
|
||||
static_cast<uint32_t>(CONFIG_GATEWAY_CONTROLLER_TASK_STACK_SIZE);
|
||||
const bool network_transport_supported = profile.enable_wifi || profile.enable_eth;
|
||||
controller_config.setup_supported = true;
|
||||
controller_config.ble_supported = profile.enable_ble;
|
||||
|
||||
+107
-12
@@ -600,7 +600,7 @@ CONFIG_PARTITION_TABLE_MD5=y
|
||||
#
|
||||
# DALI Settings
|
||||
#
|
||||
CONFIG_GATEWAY_CHANNEL_COUNT=2
|
||||
CONFIG_GATEWAY_CHANNEL_COUNT=1
|
||||
|
||||
#
|
||||
# Gateway Channel 1
|
||||
@@ -619,17 +619,78 @@ CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE=1200
|
||||
#
|
||||
# Gateway Channel 2
|
||||
#
|
||||
CONFIG_GATEWAY_CHANNEL2_GW_ID=4
|
||||
# CONFIG_GATEWAY_CHANNEL2_PHY_DISABLED is not set
|
||||
CONFIG_GATEWAY_CHANNEL2_PHY_NATIVE=y
|
||||
# CONFIG_GATEWAY_CHANNEL2_PHY_UART1 is not set
|
||||
# CONFIG_GATEWAY_CHANNEL2_PHY_UART2 is not set
|
||||
CONFIG_GATEWAY_CHANNEL2_NATIVE_BUS_ID=1
|
||||
CONFIG_GATEWAY_CHANNEL2_NATIVE_TX_PIN=4
|
||||
CONFIG_GATEWAY_CHANNEL2_NATIVE_RX_PIN=3
|
||||
CONFIG_GATEWAY_CHANNEL2_NATIVE_BAUDRATE=1200
|
||||
# end of Gateway Channel 2
|
||||
|
||||
#
|
||||
# Gateway Channel 3
|
||||
#
|
||||
# end of Gateway Channel 3
|
||||
|
||||
#
|
||||
# Gateway Channel 4
|
||||
#
|
||||
# end of Gateway Channel 4
|
||||
|
||||
#
|
||||
# Gateway Channel 5
|
||||
#
|
||||
# end of Gateway Channel 5
|
||||
|
||||
#
|
||||
# Gateway Channel 6
|
||||
#
|
||||
# end of Gateway Channel 6
|
||||
|
||||
#
|
||||
# Gateway Channel 7
|
||||
#
|
||||
# end of Gateway Channel 7
|
||||
|
||||
#
|
||||
# Gateway Channel 8
|
||||
#
|
||||
# end of Gateway Channel 8
|
||||
|
||||
#
|
||||
# Gateway Channel 9
|
||||
#
|
||||
# end of Gateway Channel 9
|
||||
|
||||
#
|
||||
# Gateway Channel 10
|
||||
#
|
||||
# end of Gateway Channel 10
|
||||
|
||||
#
|
||||
# Gateway Channel 11
|
||||
#
|
||||
# end of Gateway Channel 11
|
||||
|
||||
#
|
||||
# Gateway Channel 12
|
||||
#
|
||||
# end of Gateway Channel 12
|
||||
|
||||
#
|
||||
# Gateway Channel 13
|
||||
#
|
||||
# end of Gateway Channel 13
|
||||
|
||||
#
|
||||
# Gateway Channel 14
|
||||
#
|
||||
# end of Gateway Channel 14
|
||||
|
||||
#
|
||||
# Gateway Channel 15
|
||||
#
|
||||
# end of Gateway Channel 15
|
||||
|
||||
#
|
||||
# Gateway Channel 16
|
||||
#
|
||||
# end of Gateway Channel 16
|
||||
|
||||
#
|
||||
# Gateway Cache
|
||||
#
|
||||
@@ -644,10 +705,11 @@ CONFIG_GATEWAY_CACHE_OUTSIDE_BUS_FIRST=y
|
||||
# end of Gateway Cache
|
||||
|
||||
# CONFIG_GATEWAY_ENABLE_DALI_BUS is not set
|
||||
CONFIG_GATEWAY_CONTROLLER_TASK_STACK_SIZE=12288
|
||||
# end of DALI Settings
|
||||
|
||||
#
|
||||
# Gateway Startup Services
|
||||
# Connectivity Startup
|
||||
#
|
||||
CONFIG_GATEWAY_BLE_SUPPORTED=y
|
||||
CONFIG_GATEWAY_START_BLE_ENABLED=y
|
||||
@@ -661,6 +723,7 @@ CONFIG_GATEWAY_SMARTCONFIG_TIMEOUT_SEC=60
|
||||
CONFIG_GATEWAY_ETHERNET_SUPPORTED=y
|
||||
CONFIG_GATEWAY_START_ETHERNET_ENABLED=y
|
||||
CONFIG_GATEWAY_ETHERNET_IGNORE_INIT_FAILURE=y
|
||||
# end of Connectivity Startup
|
||||
|
||||
#
|
||||
# Gateway Wired Ethernet
|
||||
@@ -678,7 +741,15 @@ CONFIG_GATEWAY_ETHERNET_PHY_ADDR=1
|
||||
CONFIG_GATEWAY_ETHERNET_RX_TASK_STACK_SIZE=4096
|
||||
# end of Gateway Wired Ethernet
|
||||
|
||||
#
|
||||
# Bridge Runtime
|
||||
#
|
||||
CONFIG_GATEWAY_BRIDGE_SUPPORTED=y
|
||||
# end of Bridge Runtime
|
||||
|
||||
#
|
||||
# Modbus Settings
|
||||
#
|
||||
CONFIG_GATEWAY_MODBUS_BRIDGE_SUPPORTED=y
|
||||
# CONFIG_GATEWAY_START_MODBUS_BRIDGE_ENABLED is not set
|
||||
CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_TCP=y
|
||||
@@ -686,8 +757,14 @@ CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_TCP=y
|
||||
# CONFIG_GATEWAY_MODBUS_DEFAULT_TRANSPORT_ASCII is not set
|
||||
CONFIG_GATEWAY_MODBUS_TCP_PORT=1502
|
||||
CONFIG_GATEWAY_MODBUS_UNIT_ID=1
|
||||
# end of Modbus Settings
|
||||
|
||||
#
|
||||
# BACnet Settings
|
||||
#
|
||||
CONFIG_GATEWAY_BACNET_BRIDGE_SUPPORTED=y
|
||||
# CONFIG_GATEWAY_START_BACNET_BRIDGE_ENABLED is not set
|
||||
# end of BACnet Settings
|
||||
|
||||
#
|
||||
# KNX Settings
|
||||
@@ -737,6 +814,9 @@ CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=12288
|
||||
CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5
|
||||
# end of KNX Settings
|
||||
|
||||
#
|
||||
# Cloud Settings
|
||||
#
|
||||
CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED=y
|
||||
# CONFIG_GATEWAY_START_CLOUD_BRIDGE_ENABLED is not set
|
||||
CONFIG_GATEWAY_CLOUD_TOPIC_PREFIX="devices"
|
||||
@@ -747,14 +827,29 @@ CONFIG_GATEWAY_CLOUD_LTE_UART_PORT=-1
|
||||
CONFIG_GATEWAY_CLOUD_LTE_UART_TX_PIN=-1
|
||||
CONFIG_GATEWAY_CLOUD_LTE_UART_RX_PIN=-1
|
||||
CONFIG_GATEWAY_CLOUD_LTE_UART_BAUDRATE=115200
|
||||
# end of Cloud Settings
|
||||
|
||||
#
|
||||
# Bridge Task Settings
|
||||
#
|
||||
CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_STACK_SIZE=6144
|
||||
CONFIG_GATEWAY_BRIDGE_MODBUS_TASK_PRIORITY=4
|
||||
CONFIG_GATEWAY_BRIDGE_BACNET_TASK_STACK_SIZE=8192
|
||||
CONFIG_GATEWAY_BRIDGE_BACNET_TASK_PRIORITY=5
|
||||
# end of Bridge Task Settings
|
||||
|
||||
#
|
||||
# USB Setup
|
||||
#
|
||||
CONFIG_GATEWAY_USB_STARTUP_DEBUG_JTAG=y
|
||||
# CONFIG_GATEWAY_USB_STARTUP_SETUP_SERIAL is not set
|
||||
# end of USB Setup
|
||||
|
||||
#
|
||||
# UART0 Control
|
||||
#
|
||||
# CONFIG_GATEWAY_485_CONTROL_ENABLED is not set
|
||||
# end of Gateway Startup Services
|
||||
# end of UART0 Control
|
||||
|
||||
#
|
||||
# Gateway Network Services
|
||||
|
||||
@@ -24,7 +24,7 @@ class GatewayBridgeService;
|
||||
class GatewayRuntime;
|
||||
|
||||
struct GatewayControllerConfig {
|
||||
uint32_t task_stack_size{6144};
|
||||
uint32_t task_stack_size{12288};
|
||||
UBaseType_t task_priority{5};
|
||||
int color_temperature_min{2000};
|
||||
int color_temperature_max{6500};
|
||||
|
||||
@@ -69,6 +69,8 @@ class EtsDeviceRuntime {
|
||||
bool transmitTpFrame(const uint8_t* data, size_t len);
|
||||
|
||||
bool handleTunnelFrame(const uint8_t* data, size_t len, CemiFrameSender sender);
|
||||
bool handleLocalBroadcastManagementFrame(const uint8_t* data, size_t len,
|
||||
CemiFrameSender sender);
|
||||
bool handleBusFrame(const uint8_t* data, size_t len);
|
||||
bool emitGroupValue(uint16_t group_object_number, const uint8_t* data, size_t len,
|
||||
CemiFrameSender sender);
|
||||
|
||||
@@ -44,6 +44,8 @@ class OamRouterRuntime {
|
||||
Platform* platform();
|
||||
void setNetworkInterface(esp_netif_t* netif);
|
||||
bool handleTunnelFrame(const uint8_t* data, size_t len, CemiFrameSender sender);
|
||||
bool handleLocalBroadcastManagementFrame(const uint8_t* data, size_t len,
|
||||
CemiFrameSender sender);
|
||||
void loop();
|
||||
|
||||
private:
|
||||
|
||||
@@ -42,6 +42,21 @@ bool IsUsableIndividualAddress(uint16_t address) {
|
||||
return address != 0 && address != kInvalidIndividualAddress;
|
||||
}
|
||||
|
||||
bool IsBroadcastManagementRequest(CemiFrame& frame) {
|
||||
if (frame.addressType() != GroupAddress || frame.destinationAddress() != 0x0000) {
|
||||
return false;
|
||||
}
|
||||
switch (frame.apdu().type()) {
|
||||
case IndividualAddressWrite:
|
||||
case IndividualAddressRead:
|
||||
case IndividualAddressSerialNumberRead:
|
||||
case IndividualAddressSerialNumberWrite:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string HexBytesString(const uint8_t* data, size_t length) {
|
||||
if (data == nullptr || length == 0) {
|
||||
return {};
|
||||
@@ -336,6 +351,28 @@ bool EtsDeviceRuntime::handleTunnelFrame(const uint8_t* data, size_t len,
|
||||
return consumed;
|
||||
}
|
||||
|
||||
bool EtsDeviceRuntime::handleLocalBroadcastManagementFrame(const uint8_t* data, size_t len,
|
||||
CemiFrameSender sender) {
|
||||
if (data == nullptr || len < 2) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> frame_data(data, data + len);
|
||||
CemiFrame frame(frame_data.data(), static_cast<uint16_t>(frame_data.size()));
|
||||
if (!frame.valid() || !IsBroadcastManagementRequest(frame)) {
|
||||
return false;
|
||||
}
|
||||
const HopCountType hop_type =
|
||||
frame.npdu().hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter;
|
||||
sender_ = std::move(sender);
|
||||
ActiveFunctionPropertyRuntimeScope callback_scope(this);
|
||||
device_.injectDataBroadcastIndication(hop_type, frame.priority(), frame.sourceAddress(),
|
||||
frame.apdu());
|
||||
loop();
|
||||
sender_ = nullptr;
|
||||
installGroupObjectCallbacks();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EtsDeviceRuntime::handleBusFrame(const uint8_t* data, size_t len) {
|
||||
auto* data_link_layer = device_.getDataLinkLayer();
|
||||
if (data_link_layer == nullptr || data == nullptr || len < 2) {
|
||||
@@ -592,6 +629,10 @@ bool EtsDeviceRuntime::shouldConsumeTunnelFrame(CemiFrame& frame) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsBroadcastManagementRequest(frame)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (frame.addressType() == IndividualAddress) {
|
||||
if (dest == own_address || dest == client_address ||
|
||||
(commissioning && dest == kKnxUnconfiguredBroadcastAddress)) {
|
||||
|
||||
@@ -823,6 +823,22 @@ std::optional<MessageCode> CemiMessageCode(const uint8_t* data, size_t len) {
|
||||
return static_cast<MessageCode>(data[0]);
|
||||
}
|
||||
|
||||
bool IsKnxBroadcastManagementRequest(CemiFrame& frame) {
|
||||
if (frame.messageCode() != L_data_req || frame.addressType() != GroupAddress ||
|
||||
frame.destinationAddress() != 0x0000) {
|
||||
return false;
|
||||
}
|
||||
switch (frame.apdu().type()) {
|
||||
case IndividualAddressWrite:
|
||||
case IndividualAddressRead:
|
||||
case IndividualAddressSerialNumberRead:
|
||||
case IndividualAddressSerialNumberWrite:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t KnxIpServiceForCemi(const uint8_t* data, size_t len, uint16_t fallback_service) {
|
||||
const auto message_code = CemiMessageCode(data, len);
|
||||
if (!message_code.has_value()) {
|
||||
|
||||
@@ -19,14 +19,98 @@ bool GatewayKnxTpIpRouter::handleOpenKnxTunnelFrame(const uint8_t* data, size_t
|
||||
const uint8_t* suppress_routing_echo,
|
||||
size_t suppress_routing_echo_len) {
|
||||
bool route_to_oam = response_client != nullptr && response_client->oam_router_persona;
|
||||
if (!route_to_oam && data != nullptr && len >= 2) {
|
||||
bool route_to_all_internal_instances = false;
|
||||
if (data != nullptr && len >= 2) {
|
||||
std::vector<uint8_t> frame_data(data, data + len);
|
||||
CemiFrame frame(frame_data.data(), static_cast<uint16_t>(frame_data.size()));
|
||||
if (frame.valid() && oam_router_ != nullptr &&
|
||||
MatchesOamRouterLocalIndividualAddress(frame, *oam_router_)) {
|
||||
route_to_oam = true;
|
||||
if (frame.valid()) {
|
||||
route_to_all_internal_instances = IsKnxBroadcastManagementRequest(frame);
|
||||
if (!route_to_oam && oam_router_ != nullptr &&
|
||||
MatchesOamRouterLocalIndividualAddress(frame, *oam_router_)) {
|
||||
route_to_oam = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (route_to_all_internal_instances) {
|
||||
SemaphoreGuard guard(openknx_lock_);
|
||||
if (ets_device_ == nullptr && oam_router_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> tunnel_confirmation;
|
||||
const bool needs_tunnel_confirmation =
|
||||
response_client != nullptr && response_client->connected &&
|
||||
response_service == kServiceTunnellingRequest &&
|
||||
BuildTunnelConfirmationFrame(data, len, &tunnel_confirmation);
|
||||
bool sent_tunnel_confirmation = false;
|
||||
const auto send_response =
|
||||
[this, response_client, response_service, needs_tunnel_confirmation,
|
||||
&tunnel_confirmation, &sent_tunnel_confirmation, suppress_routing_echo,
|
||||
suppress_routing_echo_len](const uint8_t* response, size_t response_len) {
|
||||
if (response == nullptr || response_len == 0) {
|
||||
return;
|
||||
}
|
||||
publishCloudCemiFrame(response, response_len);
|
||||
const bool routing_context =
|
||||
response_client == nullptr && response_service == kServiceRoutingIndication;
|
||||
const auto message_code = CemiMessageCode(response, response_len);
|
||||
if (routing_context && suppress_routing_echo != nullptr &&
|
||||
IsLocalRoutingEchoIndication(response, response_len, suppress_routing_echo,
|
||||
suppress_routing_echo_len)) {
|
||||
return;
|
||||
}
|
||||
if (needs_tunnel_confirmation && !sent_tunnel_confirmation &&
|
||||
message_code.has_value() && message_code.value() != L_data_con) {
|
||||
sent_tunnel_confirmation = sendCemiFrameToClient(
|
||||
*response_client, kServiceTunnellingRequest,
|
||||
tunnel_confirmation.data(), tunnel_confirmation.size());
|
||||
}
|
||||
|
||||
const uint16_t service = KnxIpServiceForCemi(response, response_len, response_service);
|
||||
if (service == kServiceDeviceConfigurationRequest) {
|
||||
if (response_client != nullptr && response_client->connected) {
|
||||
sendCemiFrameToClient(*response_client, service, response, response_len);
|
||||
} else if (routing_context) {
|
||||
sendRoutingIndication(response, response_len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (message_code.has_value() && message_code.value() == L_data_con) {
|
||||
if (routing_context) {
|
||||
return;
|
||||
}
|
||||
if (response_client != nullptr && response_client->connected) {
|
||||
sent_tunnel_confirmation =
|
||||
sendCemiFrameToClient(*response_client, service, response, response_len) ||
|
||||
sent_tunnel_confirmation;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (routing_context) {
|
||||
sendRoutingIndication(response, response_len);
|
||||
return;
|
||||
}
|
||||
if (response_client != nullptr && response_client->connected) {
|
||||
sendCemiFrameToClient(*response_client, service, response, response_len);
|
||||
return;
|
||||
}
|
||||
sendTunnelIndication(response, response_len);
|
||||
};
|
||||
bool consumed = false;
|
||||
if (ets_device_ != nullptr) {
|
||||
consumed = ets_device_->handleLocalBroadcastManagementFrame(data, len, send_response) ||
|
||||
consumed;
|
||||
}
|
||||
if (oam_router_ != nullptr) {
|
||||
consumed = oam_router_->handleLocalBroadcastManagementFrame(data, len, send_response) ||
|
||||
consumed;
|
||||
}
|
||||
if (needs_tunnel_confirmation && consumed && !sent_tunnel_confirmation) {
|
||||
sendCemiFrameToClient(*response_client, kServiceTunnellingRequest,
|
||||
tunnel_confirmation.data(), tunnel_confirmation.size());
|
||||
}
|
||||
syncOpenKnxConfigFromDevice();
|
||||
return consumed;
|
||||
}
|
||||
if (route_to_oam) {
|
||||
return handleOamRouterTunnelFrame(data, len, response_client, response_service,
|
||||
suppress_routing_echo, suppress_routing_echo_len);
|
||||
|
||||
@@ -184,21 +184,31 @@ void GatewayKnxTpIpRouter::handleRoutingIndication(const uint8_t* packet_data, s
|
||||
const uint8_t* cemi = frame.data();
|
||||
const size_t cemi_len = frame.dataLength();
|
||||
bool consumed_by_local_application = false;
|
||||
const bool addressed_to_oam =
|
||||
const bool addressed_to_oam =
|
||||
oam_router_ != nullptr && MatchesOamRouterLocalIndividualAddress(frame, *oam_router_);
|
||||
const bool addressed_to_reg1 =
|
||||
const bool addressed_to_reg1 =
|
||||
ets_device_ != nullptr && MatchesOpenKnxLocalIndividualAddress(frame, *ets_device_);
|
||||
if (addressed_to_oam || addressed_to_reg1) {
|
||||
std::vector<uint8_t> local_tunnel_frame;
|
||||
if (BuildLocalRoutingTunnelFrame(cemi, cemi_len, &local_tunnel_frame)) {
|
||||
consumed_by_local_application = handleOpenKnxTunnelFrame(
|
||||
std::vector<uint8_t> local_tunnel_frame;
|
||||
const bool has_local_tunnel_frame =
|
||||
BuildLocalRoutingTunnelFrame(cemi, cemi_len, &local_tunnel_frame);
|
||||
bool broadcast_management = false;
|
||||
if (has_local_tunnel_frame) {
|
||||
CemiFrame local_frame(local_tunnel_frame.data(),
|
||||
static_cast<uint16_t>(local_tunnel_frame.size()));
|
||||
broadcast_management = local_frame.valid() && IsKnxBroadcastManagementRequest(local_frame);
|
||||
}
|
||||
if ((addressed_to_oam || addressed_to_reg1 || broadcast_management) &&
|
||||
has_local_tunnel_frame) {
|
||||
consumed_by_local_application = handleOpenKnxTunnelFrame(
|
||||
local_tunnel_frame.data(), local_tunnel_frame.size(), nullptr,
|
||||
kServiceRoutingIndication,
|
||||
frame.messageCode() == L_data_ind ? cemi : nullptr,
|
||||
frame.messageCode() == L_data_ind ? cemi_len : 0);
|
||||
}
|
||||
}
|
||||
if (consumed_by_local_application) {
|
||||
if (broadcast_management) {
|
||||
transmitOpenKnxTpFrame(cemi, cemi_len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const bool consumed_by_openknx = handleOpenKnxBusFrame(cemi, cemi_len);
|
||||
@@ -387,6 +397,7 @@ void GatewayKnxTpIpRouter::handleTunnellingRequest(const uint8_t* packet_data, s
|
||||
if (frame.messageCode() == L_data_req && frame.sourceAddress() == 0) {
|
||||
frame.sourceAddress(client->individual_address);
|
||||
}
|
||||
const bool broadcast_management = IsKnxBroadcastManagementRequest(frame);
|
||||
const uint8_t* cemi = frame.data();
|
||||
const size_t cemi_len = frame.dataLength();
|
||||
const std::vector<uint8_t> current_cemi(cemi, cemi + cemi_len);
|
||||
@@ -441,9 +452,9 @@ void GatewayKnxTpIpRouter::handleTunnellingRequest(const uint8_t* packet_data, s
|
||||
const bool consumed_by_openknx = handleOpenKnxTunnelFrame(
|
||||
cemi, cemi_len, client, kServiceTunnellingRequest);
|
||||
const bool routed_to_dali = routeOpenKnxGroupWrite(cemi, cemi_len, "KNX tunnel frame");
|
||||
const bool sent_to_tp = !consumed_by_openknx && !routed_to_dali &&
|
||||
const bool sent_to_tp = (!consumed_by_openknx || broadcast_management) && !routed_to_dali &&
|
||||
transmitOpenKnxTpFrame(cemi, cemi_len);
|
||||
if ((!consumed_by_openknx && routed_to_dali) || sent_to_tp) {
|
||||
if (!consumed_by_openknx && (routed_to_dali || sent_to_tp)) {
|
||||
std::vector<uint8_t> tunnel_confirmation;
|
||||
if (BuildTunnelConfirmationFrame(cemi, cemi_len, &tunnel_confirmation)) {
|
||||
sendCemiFrameToClient(*client, kServiceTunnellingRequest, tunnel_confirmation.data(),
|
||||
|
||||
@@ -22,6 +22,21 @@ bool IsUsableIndividualAddress(uint16_t address) {
|
||||
return address != 0 && address != kInvalidIndividualAddress;
|
||||
}
|
||||
|
||||
bool IsBroadcastManagementRequest(CemiFrame& frame) {
|
||||
if (frame.addressType() != GroupAddress || frame.destinationAddress() != 0x0000) {
|
||||
return false;
|
||||
}
|
||||
switch (frame.apdu().type()) {
|
||||
case IndividualAddressWrite:
|
||||
case IndividualAddressRead:
|
||||
case IndividualAddressSerialNumberRead:
|
||||
case IndividualAddressSerialNumberWrite:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t OamBauNumberFromBaseMac() {
|
||||
uint8_t mac[6]{};
|
||||
if (esp_efuse_mac_get_default(mac) != ESP_OK && esp_read_mac(mac, ESP_MAC_WIFI_STA) != ESP_OK) {
|
||||
@@ -218,6 +233,33 @@ bool OamRouterRuntime::handleTunnelFrame(const uint8_t* data, size_t len,
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OamRouterRuntime::handleLocalBroadcastManagementFrame(const uint8_t* data, size_t len,
|
||||
CemiFrameSender sender) {
|
||||
#if defined(ENABLE_BAU091A_PERSONA)
|
||||
if (data == nullptr || len < 2) {
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> frame_data(data, data + len);
|
||||
CemiFrame frame(frame_data.data(), static_cast<uint16_t>(frame_data.size()));
|
||||
if (!frame.valid() || !IsBroadcastManagementRequest(frame)) {
|
||||
return false;
|
||||
}
|
||||
const HopCountType hop_type =
|
||||
frame.npdu().hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter;
|
||||
sender_ = std::move(sender);
|
||||
device_.injectDataBroadcastIndication(hop_type, frame.priority(), frame.sourceAddress(),
|
||||
frame.apdu());
|
||||
loop();
|
||||
sender_ = nullptr;
|
||||
return true;
|
||||
#else
|
||||
(void)data;
|
||||
(void)len;
|
||||
(void)sender;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OamRouterRuntime::loop() {
|
||||
#if defined(ENABLE_BAU091A_PERSONA)
|
||||
device_.loop();
|
||||
@@ -268,6 +310,9 @@ bool OamRouterRuntime::shouldConsumeTunnelFrame(CemiFrame& frame) const {
|
||||
return dest == individualAddress() || dest == tunnelClientAddress() ||
|
||||
(commissioning && dest == kKnxUnconfiguredBroadcastAddress);
|
||||
}
|
||||
if (IsBroadcastManagementRequest(frame)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
|
||||
+1
-1
Submodule knx updated: ae3645239f...d19859af47
Reference in New Issue
Block a user