From 68250dc9375ccb270b0eb5c0280fa83e0b5076d1 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:19:32 +0100 Subject: [PATCH] Mark implicit ACK for MQTT as MQTT transport (#8939) * Mark implicit ACK for MQTT as MQTT transport * TRUNK * Fix build * Make sure implicit ACKs from MQTT do not stop retransmissions in ReliableRouter --------- Co-authored-by: Ben Meadors --- src/mesh/MeshModule.h | 2 +- src/mesh/ReliableRouter.cpp | 4 +++- src/modules/RoutingModule.cpp | 6 ++++++ src/modules/RoutingModule.h | 3 +++ src/mqtt/MQTT.cpp | 9 ++++++--- src/platform/nrf52/main-nrf52.cpp | 2 +- 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/mesh/MeshModule.h b/src/mesh/MeshModule.h index eda3f8881..e7178bcfe 100644 --- a/src/mesh/MeshModule.h +++ b/src/mesh/MeshModule.h @@ -225,4 +225,4 @@ class MeshModule /** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet * This ensures that if the request packet was sent reliably, the reply is sent that way as well. */ -void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to); \ No newline at end of file +void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to); diff --git a/src/mesh/ReliableRouter.cpp b/src/mesh/ReliableRouter.cpp index 00066a7a3..7619fc106 100644 --- a/src/mesh/ReliableRouter.cpp +++ b/src/mesh/ReliableRouter.cpp @@ -150,7 +150,9 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas PacketId nakId = (c && c->error_reason != meshtastic_Routing_Error_NONE) ? p->decoded.request_id : 0; // We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records - if (ackId || nakId) { + if ((ackId || nakId) && + // Implicit ACKs from MQTT should not stop retransmissions + !(isFromUs(p) && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT)) { LOG_DEBUG("Received a %s for 0x%x, stopping retransmissions", ackId ? "ACK" : "NAK", ackId); if (ackId) { stopRetransmission(p->to, ackId); diff --git a/src/modules/RoutingModule.cpp b/src/modules/RoutingModule.cpp index 05173983c..662f5379a 100644 --- a/src/modules/RoutingModule.cpp +++ b/src/modules/RoutingModule.cpp @@ -75,6 +75,12 @@ uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit return Default::getConfiguredOrDefaultHopLimit(config.lora.hop_limit); // Use the default hop limit } +meshtastic_MeshPacket *RoutingModule::allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, + uint8_t hopLimit) +{ + return MeshModule::allocAckNak(err, to, idFrom, chIndex, hopLimit); +} + RoutingModule::RoutingModule() : ProtobufModule("routing", meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg) { isPromiscuous = true; diff --git a/src/modules/RoutingModule.h b/src/modules/RoutingModule.h index a4e0679d0..5d4b9596f 100644 --- a/src/modules/RoutingModule.h +++ b/src/modules/RoutingModule.h @@ -16,6 +16,9 @@ class RoutingModule : public ProtobufModule virtual void sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, uint8_t hopLimit = 0, bool ackWantsAck = false); + meshtastic_MeshPacket *allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, + uint8_t hopLimit = 0); + // Given the hopStart and hopLimit upon reception of a request, return the hop limit to use for the response uint8_t getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit); diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index ad35e152a..7c33f0360 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -87,10 +87,13 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length) // Generate an implicit ACK towards ourselves (handled and processed only locally!) for this message. // We do this because packets are not rebroadcasted back into MQTT anymore and we assume that at least one node // receives it when we get our own packet back. Then we'll stop our retransmissions. - if (isFromUs(e.packet)) - routingModule->sendAckNak(meshtastic_Routing_Error_NONE, getFrom(e.packet), e.packet->id, ch.index); - else + if (isFromUs(e.packet)) { + auto pAck = routingModule->allocAckNak(meshtastic_Routing_Error_NONE, getFrom(e.packet), e.packet->id, ch.index); + pAck->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT; + router->sendLocal(pAck); + } else { LOG_INFO("Ignore downlink message we originally sent"); + } return; } if (isFromUs(e.packet)) { diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index 5d1ba20ba..472107229 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -337,7 +337,7 @@ void cpuDeepSleep(uint32_t msecToWake) #endif #ifdef TTGO_T_ECHO - // To power off the T-Echo, the display must be set + // To power off the T-Echo, the display must be set // as an input pin; otherwise, there will be leakage current. pinMode(PIN_EINK_CS, INPUT); pinMode(PIN_EINK_DC, INPUT);