diff --git a/README.md b/README.md index c1c03c1..22afcb8 100644 --- a/README.md +++ b/README.md @@ -239,6 +239,7 @@ Notes: - Total power is computed on receiver as `p1 + p2 + p3`. - 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. ## Device IDs - Derived from WiFi STA MAC. diff --git a/include/config.h b/include/config.h index bdaefcc..00c9d14 100644 --- a/include/config.h +++ b/include/config.h @@ -76,6 +76,8 @@ constexpr uint32_t METER_SEND_INTERVAL_MS = 30000; constexpr uint32_t BATTERY_SAMPLE_INTERVAL_MS = 60000; constexpr float BATTERY_CAL = 1.083f; constexpr uint32_t BATCH_ACK_TIMEOUT_MS = 3000; +constexpr uint8_t ACK_REPEAT_COUNT = 3; +constexpr uint32_t ACK_REPEAT_DELAY_MS = 200; constexpr uint8_t BATCH_MAX_RETRIES = 2; constexpr uint8_t METER_BATCH_MAX_SAMPLES = 30; constexpr uint8_t BATCH_QUEUE_DEPTH = 10; diff --git a/src/main.cpp b/src/main.cpp index 875482d..33d9a85 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -497,10 +497,17 @@ static void send_batch_ack(uint16_t batch_id, uint16_t sender_id) { write_u16_le(&ack.payload[0], batch_id); write_u16_le(&ack.payload[2], sender_id); write_u16_le(&ack.payload[4], g_short_id); - if (SERIAL_DEBUG_MODE) { - serial_debug_printf("ack: tx batch_id=%u to sender=%04X", batch_id, sender_id); + uint8_t repeats = ACK_REPEAT_COUNT == 0 ? 1 : ACK_REPEAT_COUNT; + for (uint8_t i = 0; i < repeats; ++i) { + if (SERIAL_DEBUG_MODE) { + serial_debug_printf("ack: tx repeat %u/%u batch_id=%u", static_cast(i + 1), + static_cast(repeats), batch_id); + } + lora_send(ack); + if (i + 1 < repeats && ACK_REPEAT_DELAY_MS > 0) { + delay(ACK_REPEAT_DELAY_MS); + } } - lora_send(ack); lora_receive_continuous(); } @@ -852,7 +859,7 @@ static void sender_loop() { if (ack_sender == g_short_id && ack_receiver == ack_pkt.device_id_short && g_batch_ack_pending && ack_id == g_last_sent_batch_id) { g_last_acked_batch_id = ack_id; - serial_debug_printf("ack: ok batch_id=%u", ack_id); + serial_debug_printf("ack: rx ok batch_id=%u", ack_id); finish_inflight_batch(); } else if (SERIAL_DEBUG_MODE) { serial_debug_printf("ack: reject batch_id=%u sender=%u receiver=%u exp_batch=%u exp_sender=%u",