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:
Tony
2026-05-27 21:06:58 +08:00
parent 6d0b36b60a
commit 078c37a20f
12 changed files with 338 additions and 27 deletions
@@ -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);