powerpods/main/README.md
simon a1629fb3db Fix UART1 GPIO mapping and simplify command logging.
Use TX=GPIO3 and RX=GPIO2 at 921600 to match the terminal adapter wiring;
log received message id and which handler command is triggered.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 22:06:49 +02:00

115 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Command handler
Generic command dispatch for Powerpod. Transports (UART today, ESP-NOW later) enqueue messages on a shared FreeRTOS queue; a dispatcher task invokes registered callbacks by message ID.
## Architecture
```
UART / ESP-NOW → generic_msg_t queue → vCmdDispatcherTask → registered handler
```
- **`cmd_handler`** — queue, registration, dispatcher task
- **`uart`** — framed serial input, converts packets to `generic_msg_t`
- **`powerpod.c`** — creates the queue, calls `init_cmdHandler()` then `init_uart()`
Initialize the command handler **before** UART so the dispatcher is running when packets arrive.
```c
cmd_queue = xQueueCreate(10, sizeof(generic_msg_t));
init_cmdHandler(cmd_queue);
init_uart(cmd_queue);
```
## UART frame format
Packets on **UART1** (921600 baud, **TX=GPIO3**, **RX=GPIO2** — USB adapter on `/dev/ttyUSB0`):
| Field | Value |
|-----------|--------------------------------------------|
| Start | `0xAA` |
| Length | 1 byte, payload size (1252), non-zero |
| Payload | `length` bytes |
| Checksum | XOR of all payload bytes |
| Stop | `0xCC` |
**Payload layout for the command handler:**
| Offset | Meaning |
|--------|----------------------------------|
| 0 | Command ID (`msg_id`, uint8/16) |
| 1… | Arguments (passed to handler) |
Example: command `0x01` with arguments `0x02 0x03` → payload `01 02 03`, length = 3.
The dispatcher strips the first byte; handlers receive only the argument bytes.
## API
### `msg_register_handler(uint16_t id, msg_callback_t cb)`
Register a callback for a command ID. Up to 32 handlers. Re-registering the same ID updates the callback.
```c
static void on_ping(const uint8_t *data, size_t len) {
ESP_LOGI("app", "ping, %u bytes", (unsigned)len);
}
msg_register_handler(0x01, on_ping);
```
Callback signature:
```c
typedef void (*msg_callback_t)(const uint8_t *data, size_t len);
```
### `msg_post(uint16_t id, const uint8_t *data, size_t len)`
Enqueue a command from firmware (e.g. ESP-NOW receive path) without UART. Copies `data` into heap memory; the dispatcher frees it after the handler returns.
```c
uint8_t args[] = {0x02, 0x03};
msg_post(0x01, args, sizeof(args));
```
Returns `ESP_OK`, `ESP_ERR_NO_MEM`, `ESP_ERR_TIMEOUT` (queue full), or `ESP_ERR_INVALID_STATE`.
## Adding a new command
1. Pick a command ID (first byte of UART payload).
2. Implement a handler in `powerpod.c` (or a dedicated module).
3. Call `msg_register_handler()` after `init_cmdHandler()`.
4. From a host tool, send a framed UART packet with that ID in byte 0.
## VERSION command (`MessageType.VERSION` = 3)
Implemented in `cmd_version.c`. Request is a UART frame with payload `03` (command byte only).
Response frame payload:
| Byte 0 | Bytes 1… |
|--------|----------|
| `0x03` | nanopb-encoded `UartMessage` with `type = VERSION` and `version_response` set |
`VersionResponse` fields:
- `version``POWERPOD_FW_VERSION` (default `1`, override at compile time)
- `git_hash` — short git hash from build (`POWERPOD_GIT_HASH`, from `git rev-parse`)
Register additional proto commands the same way: handler + `uart_send_uart_message()` for replies.
## ESP-NOW (planned)
Parse incoming ESP-NOW data in the Wi-Fi layer and call `msg_post()` with the same ID + payload layout as UART (ID separate, arguments in `data`). No changes to `cmd_handler` required.
## Files
| File | Role |
|-----------------|-------------------------------------------|
| `cmd_handler.h` | Types and public API |
| `cmd_handler.c` | Queue dispatch, registration, `msg_post` |
| `uart.c` | Framed UART parser → queue |
| `powerpod.c` | Queue creation and init order |
| `cmd_version.c` | VERSION command handler |
| `uart_proto.c` | Encode/send `UartMessage` over UART |