diff --git a/README.md b/README.md index a9ea7dd..59060c7 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,7 @@ Notes: - Sender error counters are carried in the batch header and applied to all samples. - Receiver ACKs MeterBatch as soon as the batch is reassembled, before MQTT/web/UI work, to avoid missing the sender ACK window. - Receiver repeats ACKs (`ACK_REPEAT_COUNT`) spaced by `ACK_REPEAT_DELAY_MS` to cover sender RX latency. +- Sender ACK RX window is derived from LoRa airtime (bounded min/max) and retried once if the first window misses. ## Device IDs - Derived from WiFi STA MAC. diff --git a/src/main.cpp b/src/main.cpp index 4b1e145..392235f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -862,8 +862,24 @@ static void sender_loop() { if (g_batch_ack_pending) { LoraPacket ack_pkt = {}; + const uint32_t ack_len = 5 + 6 + 2; + uint32_t ack_air_ms = lora_airtime_ms(ack_len); + uint32_t ack_window_ms = ack_air_ms + 300; + if (ack_window_ms < 1200) { + ack_window_ms = 1200; + } + if (ack_window_ms > 4000) { + ack_window_ms = 4000; + } + if (SERIAL_DEBUG_MODE) { + serial_debug_printf("ack: rx window=%lu airtime=%lu", static_cast(ack_window_ms), + static_cast(ack_air_ms)); + } uint32_t rx_start = millis(); - bool got_ack = lora_receive_window(ack_pkt, 400); + bool got_ack = lora_receive_window(ack_pkt, ack_window_ms); + if (!got_ack) { + got_ack = lora_receive_window(ack_pkt, ack_window_ms / 2); + } uint32_t rx_elapsed = millis() - rx_start; if (SERIAL_DEBUG_MODE) { g_sender_rx_window_ms += rx_elapsed;