Raise host frame payload limit so multi-client UART replies fit.

Use a uint16 LE length and 1024-byte max payload so CLIENT_INFO and BATTERY_STATUS no longer fail encoding past ~10 connected pods.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-01 23:43:33 +01:00
co-authored by Cursor
parent 73f48c8002
commit 9046677460
11 changed files with 72 additions and 39 deletions
+2 -2
View File
@@ -166,7 +166,7 @@ Hardware: **UART1**, **921600** baud, **TX = GPIO3**, **RX = GPIO2** (adapter TX
| Field | Value |
|-------|--------|
| Start | `0xAA` |
| Length | 1 byte, payload size 1–252 |
| Length | 2 bytes little-endian, payload size 1–1024 |
| Payload | `length` bytes |
| Checksum | XOR of all payload bytes |
| Stop | `0xCC` |
@@ -178,7 +178,7 @@ Hardware: **UART1**, **921600** baud, **TX = GPIO3**, **RX = GPIO2** (adapter TX
| 0 | Command ID (`MessageType` / `msg_id`) |
| 1… | Arguments (handler receives bytes after ID only) |
Example VERSION request: single-byte payload `03` → frame `AA 01 03 03 CC`.
Example VERSION request: single-byte payload `03` → frame `AA 01 00 03 03 CC`.
Logging:
+3 -3
View File
@@ -113,8 +113,8 @@ static esp_err_t send_tick_truncated(alox_UartMessage *msg) {
size_t payload_len = stream.bytes_written + 1;
uint16_t max_pay = ble_host_max_payload();
/* Framed size = payload + 4; notify must fit ATT MTU-3. */
size_t frame_len = payload_len + 4;
/* Framed size = payload + UART_FRAME_OVERHEAD; notify must fit ATT MTU-3. */
size_t frame_len = payload_len + UART_FRAME_OVERHEAD;
if (payload_len <= MAX_PAYLOAD_SIZE && frame_len <= max_pay) {
uint8_t payload[MAX_PAYLOAD_SIZE];
payload[0] = (uint8_t)msg->type;
@@ -197,7 +197,7 @@ void ble_stream_update(void) {
if (want && !s_running) {
s_running = true;
if (xTaskCreate(ble_stream_task, "ble_stream", 4096, NULL, 5, &s_task) !=
if (xTaskCreate(ble_stream_task, "ble_stream", 8192, NULL, 5, &s_task) !=
pdPASS) {
s_running = false;
s_task = NULL;
+5 -4
View File
@@ -22,14 +22,14 @@ void host_transport_set_cmd_queue(QueueHandle_t cmd_queue) {
QueueHandle_t host_transport_cmd_queue(void) { return s_cmd_queue; }
bool host_enqueue_packet(const uint8_t *payload, uint8_t len) {
bool host_enqueue_packet(const uint8_t *payload, size_t len) {
if (s_cmd_queue == NULL || payload == NULL || len == 0) {
return false;
}
generic_msg_t msg = {
.msg_id = payload[0],
.len = len > 1 ? (size_t)(len - 1) : 0,
.len = len > 1 ? (len - 1) : 0,
.payload = NULL,
};
@@ -63,10 +63,11 @@ esp_err_t host_send_framed(const uint8_t *payload, size_t len) {
checksum ^= payload[i];
}
uint8_t frame[4 + MAX_PAYLOAD_SIZE];
uint8_t frame[UART_FRAME_OVERHEAD + MAX_PAYLOAD_SIZE];
size_t pos = 0;
frame[pos++] = START_MARKER;
frame[pos++] = (uint8_t)len;
frame[pos++] = (uint8_t)(len & 0xff);
frame[pos++] = (uint8_t)((len >> 8) & 0xff);
memcpy(&frame[pos], payload, len);
pos += len;
frame[pos++] = checksum;
+2 -2
View File
@@ -19,7 +19,7 @@ void host_transport_set_cmd_queue(QueueHandle_t cmd_queue);
QueueHandle_t host_transport_cmd_queue(void);
/**
* Build AA|len|payload|xor|CC and send via the registered TX backend.
* Build AA|len_lo|len_hi|payload|xor|CC and send via the registered TX backend.
* Same semantics as uart_send_framed.
*/
esp_err_t host_send_framed(const uint8_t *payload, size_t len);
@@ -31,6 +31,6 @@ esp_err_t host_send_framed(const uint8_t *payload, size_t len);
void host_rx_bytes(const uint8_t *data, size_t len);
/** Enqueue a completed uart_packet_t (payload[0]=msg type). */
bool host_enqueue_packet(const uint8_t *payload, uint8_t len);
bool host_enqueue_packet(const uint8_t *payload, size_t len);
#endif
+13 -4
View File
@@ -81,18 +81,27 @@ bool parse_uart_byte(uint8_t byte, uart_packet_t *p) {
if (byte == START_MARKER) {
p->index = 0;
p->checksum = 0;
p->state = STATE_LEN;
p->len = 0;
p->state = STATE_LEN_LO;
}
break;
case STATE_LEN:
if (byte > MAX_PAYLOAD_SIZE || byte == 0) {
case STATE_LEN_LO:
p->len = byte;
p->state = STATE_LEN_HI;
break;
case STATE_LEN_HI: {
uint16_t len = (uint16_t)(p->len | ((uint16_t)byte << 8));
if (len == 0 || len > MAX_PAYLOAD_SIZE) {
p->state = STATE_START;
} else {
p->len = byte;
p->len = len;
p->index = 0;
p->state = STATE_DATA;
}
break;
}
case STATE_DATA:
p->payload[p->index++] = byte;
+11 -6
View File
@@ -22,13 +22,18 @@
#define UART_DRIVER_TX_BUF_SIZE 4096
#define START_MARKER 0xAA
#define STOP_MARKER 0xCC
#define MAX_BUF_SIZE 252
#define MAX_PAYLOAD_SIZE \
MAX_BUF_SIZE - 4 // Buffer overhead, Start, Len, CRC, End
/** Frame: AA | len_lo | len_hi | payload[len] | xor | CC */
#define UART_FRAME_OVERHEAD 5
/**
* Max application payload (type byte + protobuf). Sized for CLIENT_REGISTRY_MAX
* aggregations (CLIENT_INFO / BATTERY_STATUS with 16+ samples).
*/
#define MAX_PAYLOAD_SIZE 1024
typedef enum {
STATE_START,
STATE_LEN,
STATE_LEN_LO,
STATE_LEN_HI,
STATE_DATA,
STATE_CHECKSUM,
STATE_STOP
@@ -36,8 +41,8 @@ typedef enum {
typedef struct {
uint8_t payload[MAX_PAYLOAD_SIZE];
uint8_t len;
uint8_t index;
uint16_t len;
uint16_t index;
uint8_t checksum;
parser_state_t state;
} uart_packet_t;
+8
View File
@@ -1,18 +1,26 @@
#include "uart_proto.h"
#include "esp_log.h"
#include "pb_encode.h"
#include "uart.h"
#include <string.h>
static const char *TAG = "[UART_PROTO]";
esp_err_t uart_send_uart_message(const alox_UartMessage *msg) {
uint8_t pb_buf[MAX_PAYLOAD_SIZE];
pb_ostream_t stream = pb_ostream_from_buffer(pb_buf, sizeof(pb_buf));
if (!pb_encode(&stream, alox_UartMessage_fields, msg)) {
ESP_LOGE(TAG, "pb_encode failed type=%u (%s)", (unsigned)msg->type,
PB_GET_ERROR(&stream));
return ESP_FAIL;
}
uint8_t payload[MAX_PAYLOAD_SIZE];
if (stream.bytes_written + 1 > sizeof(payload)) {
ESP_LOGE(TAG, "payload too large type=%u need=%u max=%u",
(unsigned)msg->type, (unsigned)(stream.bytes_written + 1),
(unsigned)sizeof(payload));
return ESP_ERR_NO_MEM;
}