diff --git a/docs/stats_binary_frames.md b/docs/stats_binary_frames.md index f3b17da96..6afb04da2 100644 --- a/docs/stats_binary_frames.md +++ b/docs/stats_binary_frames.md @@ -17,6 +17,10 @@ The `CMD_GET_STATS` command uses a 2-byte frame structure: - `STATS_TYPE_RADIO` (1) - Get radio statistics - `STATS_TYPE_PACKETS` (2) - Get packet statistics +For unsupported sub-types, firmware returns: +- `RESP_CODE_ERR` (`1`) +- error code `ERR_CODE_ILLEGAL_ARG` (`6`) + ## Response Codes | Response | Code | Description | @@ -94,7 +98,7 @@ struct StatsRadio { ## RESP_CODE_STATS + STATS_TYPE_PACKETS (24, 2) -**Total Frame Size:** 26 bytes (legacy) or 30 bytes (includes `recv_errors`) +**Total Frame Size:** 30 bytes | Offset | Size | Type | Field Name | Description | Range/Notes | |--------|------|------|------------|-------------|-------------| @@ -106,14 +110,14 @@ struct StatsRadio { | 14 | 4 | uint32_t | direct_tx | Packets sent via direct routing | 0 - 4,294,967,295 | | 18 | 4 | uint32_t | flood_rx | Packets received via flood routing | 0 - 4,294,967,295 | | 22 | 4 | uint32_t | direct_rx | Packets received via direct routing | 0 - 4,294,967,295 | -| 26 | 4 | uint32_t | recv_errors | Receive/CRC errors (RadioLib); present only in 30-byte frame | 0 - 4,294,967,295 | +| 26 | 4 | uint32_t | recv_errors | Receive/CRC errors (RadioLib) | 0 - 4,294,967,295 | ### Notes - Counters are cumulative from boot and may wrap. - `recv = flood_rx + direct_rx` - `sent = flood_tx + direct_tx` -- Clients should accept frame length ≥ 26; if length ≥ 30, parse `recv_errors` at offset 26. +- Current companion firmware always writes `recv_errors` in this frame. ### Example Structure (C/C++) @@ -127,7 +131,7 @@ struct StatsPackets { uint32_t direct_tx; uint32_t flood_rx; uint32_t direct_rx; - uint32_t recv_errors; // present when frame size is 30 + uint32_t recv_errors; } __attribute__((packed)); ``` @@ -186,23 +190,20 @@ def parse_stats_radio(frame): } def parse_stats_packets(frame): - """Parse RESP_CODE_STATS + STATS_TYPE_PACKETS frame (26 or 30 bytes)""" - assert len(frame) >= 26, "STATS_TYPE_PACKETS frame too short" - response_code, stats_type, recv, sent, flood_tx, direct_tx, flood_rx, direct_rx = \ - struct.unpack('= 30, "STATS_TYPE_PACKETS frame too short" + response_code, stats_type, recv, sent, flood_tx, direct_tx, flood_rx, direct_rx, recv_errors = \ + struct.unpack('= 30: - (recv_errors,) = struct.unpack('= 30) { - result.recv_errors = view.getUint32(26, true); - } return result; } ``` @@ -325,4 +324,3 @@ function parseStatsPackets(buffer: ArrayBuffer): StatsPackets { - Packet counters (uint32_t): May wrap after extended high-traffic operation. - Time fields (uint32_t): Max ~136 years. - SNR (int8_t, scaled by 4): Range -32 to +31.75 dB, 0.25 dB precision. -