feat(gateway): enable full IP forwarding for KNX TP and enhance group value write handling

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-19 04:18:53 +08:00
parent 3af2995b40
commit 3bc5355041
2 changed files with 19 additions and 5 deletions
+1 -1
View File
@@ -699,7 +699,7 @@ CONFIG_GATEWAY_KNX_TP_RX_PIN=-1
CONFIG_GATEWAY_KNX_TP_BAUDRATE=19200
CONFIG_GATEWAY_KNX_TP_STARTUP_TIMEOUT_MS=2000
CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE=y
# CONFIG_GATEWAY_KNX_TP_FULL_IP_FORWARD is not set
CONFIG_GATEWAY_KNX_TP_FULL_IP_FORWARD=y
CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=12288
CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5
CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED=y
+18 -4
View File
@@ -550,6 +550,10 @@ std::optional<DecodedGroupWrite> DecodeOpenKnxGroupWrite(const uint8_t* data, si
return out;
}
bool IsOpenKnxGroupValueWrite(const uint8_t* data, size_t len) {
return DecodeOpenKnxGroupWrite(data, len).has_value();
}
uint8_t Reg1PercentToArc(uint8_t value) {
if (value == 0 || value == 0xff) {
return value;
@@ -3430,9 +3434,10 @@ void GatewayKnxTpIpRouter::handleTunnellingRequest(const uint8_t* packet_data, s
const uint8_t* cemi = frame.data();
const size_t cemi_len = frame.dataLength();
const std::vector<uint8_t> current_cemi(cemi, cemi + cemi_len);
const bool is_group_value_write = IsOpenKnxGroupValueWrite(cemi, cemi_len);
const bool duplicate_sequence = sequence == client->received_sequence;
const bool duplicate_payload = duplicate_sequence && client->last_received_cemi == current_cemi;
if (duplicate_payload) {
if (duplicate_payload && !is_group_value_write) {
ESP_LOGD(kTag, "duplicate KNXnet/IP tunnelling request channel=%u seq=%u",
static_cast<unsigned>(channel_id), static_cast<unsigned>(sequence));
sendTunnellingAck(channel_id, sequence, kKnxNoError, client->data_remote);
@@ -3453,7 +3458,11 @@ void GatewayKnxTpIpRouter::handleTunnellingRequest(const uint8_t* packet_data, s
}
return;
}
if (duplicate_sequence) {
if (duplicate_payload) {
ESP_LOGI(kTag,
"reprocessing duplicate KNXnet/IP GroupValueWrite channel=%u seq=%u without cached confirmation replay",
static_cast<unsigned>(channel_id), static_cast<unsigned>(sequence));
} else if (duplicate_sequence) {
ESP_LOGW(kTag,
"accept KNXnet/IP tunnelling request channel=%u with repeated seq=%u because cEMI payload changed",
static_cast<unsigned>(channel_id), static_cast<unsigned>(sequence));
@@ -4019,8 +4028,13 @@ bool GatewayKnxTpIpRouter::sendCemiFrameToClient(TunnelClient& client, uint16_t
}
if (service == kServiceTunnellingRequest && message_code.has_value() &&
message_code.value() == L_data_con) {
client.last_tunnel_confirmation_sequence = send_sequence;
client.last_tunnel_confirmation_packet = packet;
if (IsOpenKnxGroupValueWrite(data, len)) {
client.last_tunnel_confirmation_sequence = 0;
client.last_tunnel_confirmation_packet.clear();
} else {
client.last_tunnel_confirmation_sequence = send_sequence;
client.last_tunnel_confirmation_packet = packet;
}
}
ESP_LOGI(kTag, "sent KNXnet/IP cEMI service=0x%04x channel=%u seq=%u cemi=0x%02x len=%u to %s",
static_cast<unsigned>(service), static_cast<unsigned>(client.channel_id),