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>
107 lines
2.9 KiB
C
107 lines
2.9 KiB
C
#include "host_transport.h"
|
|
#include "cmd_handler.h"
|
|
#include "esp_log.h"
|
|
#include "uart.h"
|
|
#include "uart_messages.pb.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static const char *TAG = "[HOST]";
|
|
|
|
static host_tx_fn_t s_tx_fn;
|
|
static QueueHandle_t s_cmd_queue;
|
|
static uart_packet_t s_rx_packet = {.state = STATE_START};
|
|
static TickType_t s_last_byte_ticks;
|
|
static const TickType_t s_rx_timeout_ticks = pdMS_TO_TICKS(50);
|
|
|
|
void host_transport_set_tx(host_tx_fn_t tx_fn) { s_tx_fn = tx_fn; }
|
|
|
|
void host_transport_set_cmd_queue(QueueHandle_t cmd_queue) {
|
|
s_cmd_queue = cmd_queue;
|
|
}
|
|
|
|
QueueHandle_t host_transport_cmd_queue(void) { return s_cmd_queue; }
|
|
|
|
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 ? (len - 1) : 0,
|
|
.payload = NULL,
|
|
};
|
|
|
|
if (msg.len > 0) {
|
|
msg.payload = malloc(msg.len);
|
|
if (msg.payload == NULL) {
|
|
ESP_LOGE(TAG, "failed to allocate command payload");
|
|
return false;
|
|
}
|
|
memcpy(msg.payload, &payload[1], msg.len);
|
|
}
|
|
|
|
if (xQueueSend(s_cmd_queue, &msg, pdMS_TO_TICKS(500)) != pdPASS) {
|
|
free(msg.payload);
|
|
ESP_LOGW(TAG, "command queue full (cmd 0x%02x)", (unsigned)msg.msg_id);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
esp_err_t host_send_framed(const uint8_t *payload, size_t len) {
|
|
if (payload == NULL || len == 0 || len > MAX_PAYLOAD_SIZE) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
if (s_tx_fn == NULL) {
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
uint8_t checksum = 0;
|
|
for (size_t i = 0; i < len; i++) {
|
|
checksum ^= payload[i];
|
|
}
|
|
|
|
uint8_t frame[UART_FRAME_OVERHEAD + MAX_PAYLOAD_SIZE];
|
|
size_t pos = 0;
|
|
frame[pos++] = START_MARKER;
|
|
frame[pos++] = (uint8_t)(len & 0xff);
|
|
frame[pos++] = (uint8_t)((len >> 8) & 0xff);
|
|
memcpy(&frame[pos], payload, len);
|
|
pos += len;
|
|
frame[pos++] = checksum;
|
|
frame[pos++] = STOP_MARKER;
|
|
|
|
return s_tx_fn(frame, pos);
|
|
}
|
|
|
|
void host_rx_bytes(const uint8_t *data, size_t len) {
|
|
if (data == NULL || len == 0) {
|
|
return;
|
|
}
|
|
|
|
TickType_t now = xTaskGetTickCount();
|
|
if (s_rx_packet.state != STATE_START &&
|
|
(now - s_last_byte_ticks) > s_rx_timeout_ticks) {
|
|
s_rx_packet.state = STATE_START;
|
|
}
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
if (parse_uart_byte(data[i], &s_rx_packet)) {
|
|
uint8_t cmd =
|
|
s_rx_packet.len > 0 ? s_rx_packet.payload[0] : 0;
|
|
/* OTA payloads are high-rate; avoid INFO spam starving the dispatcher. */
|
|
if (cmd == (uint8_t)alox_MessageType_OTA_PAYLOAD) {
|
|
ESP_LOGD(TAG, "received message cmd=0x%02x len=%u", cmd,
|
|
(unsigned)s_rx_packet.len);
|
|
} else {
|
|
ESP_LOGI(TAG, "received message cmd=0x%02x len=%u", cmd,
|
|
(unsigned)s_rx_packet.len);
|
|
}
|
|
host_enqueue_packet(s_rx_packet.payload, s_rx_packet.len);
|
|
}
|
|
}
|
|
s_last_byte_ticks = now;
|
|
}
|