Add RX reject reasons to telemetry and UI

BACKWARD-INCOMPATIBLE: MeterBatch schema bumped to v2 with err_rx_reject.
- Track and log RX reject reasons (CRC/protocol/role/payload/length/id/batch)
- Include rx_reject in sender telemetry JSON and receiver web UI
- Add lora_receive reject reason logging under SERIAL_DEBUG_MODE
This commit is contained in:
2026-02-04 01:01:49 +01:00
parent 0e7214d606
commit 1024aa3dd0
10 changed files with 143 additions and 27 deletions
+25
View File
@@ -3,6 +3,26 @@
#include <SPI.h>
#include <math.h>
static RxRejectReason g_last_rx_reject_reason = RxRejectReason::None;
static uint32_t g_last_rx_reject_log_ms = 0;
static void note_reject(RxRejectReason reason) {
g_last_rx_reject_reason = reason;
if (SERIAL_DEBUG_MODE) {
uint32_t now_ms = millis();
if (now_ms - g_last_rx_reject_log_ms >= 1000) {
g_last_rx_reject_log_ms = now_ms;
Serial.printf("lora_rx: reject reason=%s\n", rx_reject_reason_text(reason));
}
}
}
RxRejectReason lora_get_last_rx_reject_reason() {
RxRejectReason reason = g_last_rx_reject_reason;
g_last_rx_reject_reason = RxRejectReason::None;
return reason;
}
static uint16_t crc16_ccitt(const uint8_t *data, size_t len) {
uint16_t crc = 0xFFFF;
for (size_t i = 0; i < len; ++i) {
@@ -95,6 +115,7 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) {
while (LoRa.available()) {
LoRa.read();
}
note_reject(RxRejectReason::LengthMismatch);
return false;
}
@@ -105,15 +126,18 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) {
}
if (len < 7) {
note_reject(RxRejectReason::LengthMismatch);
return false;
}
uint16_t crc_calc = crc16_ccitt(buffer, len - 2);
uint16_t crc_rx = static_cast<uint16_t>(buffer[len - 2] << 8) | buffer[len - 1];
if (crc_calc != crc_rx) {
note_reject(RxRejectReason::CrcFail);
return false;
}
if (buffer[0] != PROTOCOL_VERSION) {
note_reject(RxRejectReason::BadProtocol);
return false;
}
@@ -123,6 +147,7 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) {
pkt.payload_type = static_cast<PayloadType>(buffer[4]);
pkt.payload_len = len - 7;
if (pkt.payload_len > LORA_MAX_PAYLOAD) {
note_reject(RxRejectReason::LengthMismatch);
return false;
}
memcpy(pkt.payload, &buffer[5], pkt.payload_len);