Expose best_effort/fast/wait/reliable via UART, dashboard, and CLI so loss vs latency can be compared under real multi-pod load. Co-authored-by: Cursor <cursoragent@cursor.com>
225 lines
6.1 KiB
Protocol Buffer
225 lines
6.1 KiB
Protocol Buffer
syntax = "proto3";
|
||
|
||
import "nanopb.proto";
|
||
|
||
package alox;
|
||
|
||
enum EspNowMessageType {
|
||
ESPNOW_UNKNOWN = 0;
|
||
ESPNOW_DISCOVER = 1;
|
||
ESPNOW_SLAVE_INFO = 2;
|
||
ESPNOW_HEARTBEAT = 3;
|
||
ESPNOW_SET_ACCEL_DEADZONE = 4;
|
||
ESPNOW_UNICAST_TEST = 5;
|
||
ESPNOW_OTA_START = 6;
|
||
ESPNOW_OTA_PAYLOAD = 7;
|
||
ESPNOW_OTA_END = 8;
|
||
ESPNOW_OTA_STATUS = 9;
|
||
ESPNOW_FIND_ME = 10;
|
||
ESPNOW_RESTART = 11;
|
||
ESPNOW_ACCEL_SAMPLE = 12;
|
||
ESPNOW_SET_ACCEL_STREAM = 13;
|
||
ESPNOW_LED_RING = 14;
|
||
ESPNOW_BATTERY_QUERY = 15;
|
||
ESPNOW_BATTERY_REPORT = 16;
|
||
ESPNOW_SET_TAP_NOTIFY = 17;
|
||
ESPNOW_TAP_EVENT = 18;
|
||
ESPNOW_ECHO_PING = 19;
|
||
ESPNOW_ECHO_PONG = 20;
|
||
ESPNOW_SET_TAP_CONFIG = 21;
|
||
/** Master → slave: assigned logical client id after join/presence. */
|
||
ESPNOW_ASSIGN_ID = 22;
|
||
/** Master → slave: forget persisted master/id binding (debug reset). */
|
||
ESPNOW_CLEAR_ID_BINDING = 23;
|
||
/** Master → slave: accel/tap ESP-NOW send path (best_effort/fast/wait/reliable). */
|
||
ESPNOW_SET_INPUT_SEND_MODE = 24;
|
||
}
|
||
|
||
message EspNowUnicastTest {
|
||
uint32 seq = 1;
|
||
}
|
||
|
||
/** Master → slave: echo ping (host ts + master monotonic time for RTT). */
|
||
message EspNowEchoPing {
|
||
uint64 host_timestamp_us = 1;
|
||
/** esp_timer_get_time() (µs since boot) when master forwarded this message. */
|
||
uint64 master_time_us = 2;
|
||
}
|
||
|
||
/** Slave → master: echo ping payload unchanged. */
|
||
message EspNowEchoPong {
|
||
uint64 host_timestamp_us = 1;
|
||
uint64 master_time_us = 2;
|
||
}
|
||
|
||
/** Master → slave: locate pod (LED ring R/G/B ×3 @ full brightness). */
|
||
message EspNowFindMe {
|
||
/** 0 = any slave; otherwise only slave_id must match */
|
||
uint32 client_id = 1;
|
||
}
|
||
|
||
/** Master → slave: reboot after short delay. */
|
||
message EspNowRestart {
|
||
uint32 client_id = 1;
|
||
}
|
||
|
||
message EspNowDiscover {
|
||
uint32 network = 1;
|
||
/** Master is in an OTA session (UART upload or ESP-NOW distribution). */
|
||
bool master_ota_pending = 2;
|
||
}
|
||
|
||
message EspNowSlavePresence {
|
||
uint32 network = 1;
|
||
bytes mac = 2;
|
||
uint32 version = 3;
|
||
/** Preferred id from NVS for this master (0 = none / unbound). */
|
||
uint32 slave_id = 4;
|
||
bool available = 5;
|
||
bool used = 6;
|
||
}
|
||
|
||
/** Master → slave: definitive logical client id for this session/master. */
|
||
message EspNowAssignId {
|
||
uint32 assigned_id = 1;
|
||
}
|
||
|
||
/** Master → slave: clear persisted {master_mac, assigned_id} binding. */
|
||
message EspNowClearIdBinding {}
|
||
|
||
message EspNowAccelDeadzone {
|
||
uint32 deadzone = 1;
|
||
uint32 client_id = 2; // 0 = all slaves; otherwise only matching slave_id applies
|
||
}
|
||
|
||
/** Master → slave: enable/disable periodic accel ESP-NOW stream (~10 ms). */
|
||
message EspNowAccelStream {
|
||
bool enable = 1;
|
||
uint32 client_id = 2;
|
||
}
|
||
|
||
/** Slave → master: latest BMA456 sample (best-effort, ~every 10 ms). */
|
||
message EspNowAccelSample {
|
||
uint32 slave_id = 1;
|
||
sint32 x = 2;
|
||
sint32 y = 3;
|
||
sint32 z = 4;
|
||
}
|
||
|
||
/** Master → slave: on-demand LiPo read (optional; slaves also push every ~30 s). */
|
||
message EspNowBatteryQuery {
|
||
uint32 client_id = 1;
|
||
}
|
||
|
||
/** Master → slave: which tap kinds should be reported via ESP-NOW. */
|
||
message EspNowTapNotify {
|
||
uint32 client_id = 1;
|
||
bool single = 2;
|
||
bool double_tap = 3;
|
||
bool triple = 4;
|
||
}
|
||
|
||
/** Master → slave: BMA456H multitap detection parameters. */
|
||
message EspNowTapConfig {
|
||
uint32 client_id = 1; // 0 = all slaves; otherwise only matching slave_id applies
|
||
uint32 tap_sens_thres = 2;
|
||
uint32 max_gest_dur = 3;
|
||
uint32 tap_shock_dur = 4;
|
||
uint32 quite_time_after_gest = 5;
|
||
uint32 wait_for_timeout = 6;
|
||
uint32 axis_sel = 7;
|
||
bool enable_single = 8;
|
||
bool enable_double = 9;
|
||
bool enable_triple = 10;
|
||
}
|
||
|
||
/** Slave → master: tap detected on BMA456 (event, not periodic). */
|
||
message EspNowTapEvent {
|
||
uint32 slave_id = 1;
|
||
/** 1=single, 2=double, 3=triple */
|
||
uint32 kind = 2;
|
||
}
|
||
|
||
/**
|
||
* Master → slave: which esp_now_core_send_* path to use for ACCEL_SAMPLE / TAP_EVENT.
|
||
* Values match uart InputSendMode (0=best_effort … 3=reliable).
|
||
*/
|
||
message EspNowInputSendMode {
|
||
uint32 client_id = 1; // 0 = all slaves; otherwise only matching slave_id applies
|
||
uint32 mode = 2;
|
||
}
|
||
|
||
/** Slave → master: LiPo voltages (periodic ~30 s and on query). */
|
||
message EspNowBatteryReport {
|
||
uint32 client_id = 1;
|
||
bool lipo1_valid = 2;
|
||
bool lipo2_valid = 3;
|
||
uint32 lipo1_mv = 4;
|
||
uint32 lipo2_mv = 5;
|
||
}
|
||
|
||
/** Master → slave: LED ring command (same modes as UART LedRingProgressRequest). */
|
||
message EspNowLedRing {
|
||
uint32 client_id = 1;
|
||
uint32 mode = 2;
|
||
uint32 progress = 3;
|
||
uint32 digit = 4;
|
||
uint32 r = 5;
|
||
uint32 g = 6;
|
||
uint32 b = 7;
|
||
uint32 intensity = 8;
|
||
uint32 blink_ms = 9;
|
||
uint32 blink_count = 10;
|
||
}
|
||
|
||
// Master → slave: begin OTA (erase inactive slot; slave replies ESPNOW_OTA_STATUS).
|
||
message EspNowOtaStart {
|
||
uint32 total_size = 1;
|
||
}
|
||
|
||
// Master → slave: firmware chunk (up to 200 bytes); slave buffers 4 KiB before flash write.
|
||
message EspNowOtaPayload {
|
||
uint32 seq = 1;
|
||
bytes data = 2 [(nanopb).max_size = 200];
|
||
}
|
||
|
||
// Master → slave: finalize OTA (flush, esp_ota_end, set boot partition).
|
||
message EspNowOtaEnd {}
|
||
|
||
// Slave → master: status / block ACK (same status codes as UART OtaStatusPayload).
|
||
message EspNowOtaStatus {
|
||
uint32 status = 1;
|
||
uint32 bytes_written = 2;
|
||
uint32 error = 3;
|
||
}
|
||
|
||
message EspNowMessage {
|
||
EspNowMessageType type = 1;
|
||
oneof payload {
|
||
EspNowDiscover discover = 2;
|
||
EspNowSlavePresence slave_info = 3;
|
||
EspNowSlavePresence heartbeat = 4;
|
||
EspNowAccelDeadzone accel_deadzone = 5;
|
||
EspNowUnicastTest unicast_test = 6;
|
||
EspNowOtaStart ota_start = 7;
|
||
EspNowOtaPayload ota_payload = 8;
|
||
EspNowOtaEnd ota_end = 9;
|
||
EspNowOtaStatus ota_status = 10;
|
||
EspNowFindMe find_me = 11;
|
||
EspNowRestart restart = 12;
|
||
EspNowAccelSample accel_sample = 13;
|
||
EspNowAccelStream accel_stream = 14;
|
||
EspNowLedRing led_ring = 15;
|
||
EspNowBatteryQuery battery_query = 16;
|
||
EspNowBatteryReport battery_report = 17;
|
||
EspNowTapNotify tap_notify = 18;
|
||
EspNowTapEvent tap_event = 19;
|
||
EspNowEchoPing echo_ping = 20;
|
||
EspNowEchoPong echo_pong = 21;
|
||
EspNowTapConfig tap_config = 22;
|
||
EspNowAssignId assign_id = 23;
|
||
EspNowClearIdBinding clear_id_binding = 24;
|
||
EspNowInputSendMode input_send_mode = 25;
|
||
}
|
||
}
|