Assign sequential pod IDs from the master with NVS-stable bindings.

Replaces MAC-byte self-IDs with master allocation (1–255), slave preferred-ID reconnect, debug reset via UART/UI, and rate-limited ASSIGN to avoid ESP-NOW NO_MEM storms.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-01 17:25:07 +01:00
co-authored by Cursor
parent af20635047
commit 567dab6d0a
26 changed files with 1261 additions and 163 deletions
+50 -4
View File
@@ -32,7 +32,11 @@ typedef enum _alox_EspNowMessageType {
alox_EspNowMessageType_ESPNOW_TAP_EVENT = 18,
alox_EspNowMessageType_ESPNOW_ECHO_PING = 19,
alox_EspNowMessageType_ESPNOW_ECHO_PONG = 20,
alox_EspNowMessageType_ESPNOW_SET_TAP_CONFIG = 21
alox_EspNowMessageType_ESPNOW_SET_TAP_CONFIG = 21,
/* * Master → slave: assigned logical client id after join/presence. */
alox_EspNowMessageType_ESPNOW_ASSIGN_ID = 22,
/* * Master → slave: forget persisted master/id binding (debug reset). */
alox_EspNowMessageType_ESPNOW_CLEAR_ID_BINDING = 23
} alox_EspNowMessageType;
/* Struct definitions */
@@ -74,11 +78,22 @@ typedef struct _alox_EspNowSlavePresence {
uint32_t network;
pb_callback_t mac;
uint32_t version;
/* * Preferred id from NVS for this master (0 = none / unbound). */
uint32_t slave_id;
bool available;
bool used;
} alox_EspNowSlavePresence;
/* * Master → slave: definitive logical client id for this session/master. */
typedef struct _alox_EspNowAssignId {
uint32_t assigned_id;
} alox_EspNowAssignId;
/* * Master → slave: clear persisted {master_mac, assigned_id} binding. */
typedef struct _alox_EspNowClearIdBinding {
char dummy_field;
} alox_EspNowClearIdBinding;
typedef struct _alox_EspNowAccelDeadzone {
uint32_t deadzone;
uint32_t client_id; /* 0 = all slaves; otherwise only matching slave_id applies */
@@ -204,6 +219,8 @@ typedef struct _alox_EspNowMessage {
alox_EspNowEchoPing echo_ping;
alox_EspNowEchoPong echo_pong;
alox_EspNowTapConfig tap_config;
alox_EspNowAssignId assign_id;
alox_EspNowClearIdBinding clear_id_binding;
} payload;
} alox_EspNowMessage;
@@ -214,8 +231,10 @@ extern "C" {
/* Helper constants for enums */
#define _alox_EspNowMessageType_MIN alox_EspNowMessageType_ESPNOW_UNKNOWN
#define _alox_EspNowMessageType_MAX alox_EspNowMessageType_ESPNOW_SET_TAP_CONFIG
#define _alox_EspNowMessageType_ARRAYSIZE ((alox_EspNowMessageType)(alox_EspNowMessageType_ESPNOW_SET_TAP_CONFIG+1))
#define _alox_EspNowMessageType_MAX alox_EspNowMessageType_ESPNOW_CLEAR_ID_BINDING
#define _alox_EspNowMessageType_ARRAYSIZE ((alox_EspNowMessageType)(alox_EspNowMessageType_ESPNOW_CLEAR_ID_BINDING+1))
@@ -248,6 +267,8 @@ extern "C" {
#define alox_EspNowRestart_init_default {0}
#define alox_EspNowDiscover_init_default {0, 0}
#define alox_EspNowSlavePresence_init_default {0, {{NULL}, NULL}, 0, 0, 0, 0}
#define alox_EspNowAssignId_init_default {0}
#define alox_EspNowClearIdBinding_init_default {0}
#define alox_EspNowAccelDeadzone_init_default {0, 0}
#define alox_EspNowAccelStream_init_default {0, 0}
#define alox_EspNowAccelSample_init_default {0, 0, 0, 0}
@@ -269,6 +290,8 @@ extern "C" {
#define alox_EspNowRestart_init_zero {0}
#define alox_EspNowDiscover_init_zero {0, 0}
#define alox_EspNowSlavePresence_init_zero {0, {{NULL}, NULL}, 0, 0, 0, 0}
#define alox_EspNowAssignId_init_zero {0}
#define alox_EspNowClearIdBinding_init_zero {0}
#define alox_EspNowAccelDeadzone_init_zero {0, 0}
#define alox_EspNowAccelStream_init_zero {0, 0}
#define alox_EspNowAccelSample_init_zero {0, 0, 0, 0}
@@ -300,6 +323,7 @@ extern "C" {
#define alox_EspNowSlavePresence_slave_id_tag 4
#define alox_EspNowSlavePresence_available_tag 5
#define alox_EspNowSlavePresence_used_tag 6
#define alox_EspNowAssignId_assigned_id_tag 1
#define alox_EspNowAccelDeadzone_deadzone_tag 1
#define alox_EspNowAccelDeadzone_client_id_tag 2
#define alox_EspNowAccelStream_enable_tag 1
@@ -368,6 +392,8 @@ extern "C" {
#define alox_EspNowMessage_echo_ping_tag 20
#define alox_EspNowMessage_echo_pong_tag 21
#define alox_EspNowMessage_tap_config_tag 22
#define alox_EspNowMessage_assign_id_tag 23
#define alox_EspNowMessage_clear_id_binding_tag 24
/* Struct field encoding specification for nanopb */
#define alox_EspNowUnicastTest_FIELDLIST(X, a) \
@@ -413,6 +439,16 @@ X(a, STATIC, SINGULAR, BOOL, used, 6)
#define alox_EspNowSlavePresence_CALLBACK pb_default_field_callback
#define alox_EspNowSlavePresence_DEFAULT NULL
#define alox_EspNowAssignId_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, assigned_id, 1)
#define alox_EspNowAssignId_CALLBACK NULL
#define alox_EspNowAssignId_DEFAULT NULL
#define alox_EspNowClearIdBinding_FIELDLIST(X, a) \
#define alox_EspNowClearIdBinding_CALLBACK NULL
#define alox_EspNowClearIdBinding_DEFAULT NULL
#define alox_EspNowAccelDeadzone_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, deadzone, 1) \
X(a, STATIC, SINGULAR, UINT32, client_id, 2)
@@ -534,7 +570,9 @@ X(a, STATIC, ONEOF, MESSAGE, (payload,tap_notify,payload.tap_notify), 18)
X(a, STATIC, ONEOF, MESSAGE, (payload,tap_event,payload.tap_event), 19) \
X(a, STATIC, ONEOF, MESSAGE, (payload,echo_ping,payload.echo_ping), 20) \
X(a, STATIC, ONEOF, MESSAGE, (payload,echo_pong,payload.echo_pong), 21) \
X(a, STATIC, ONEOF, MESSAGE, (payload,tap_config,payload.tap_config), 22)
X(a, STATIC, ONEOF, MESSAGE, (payload,tap_config,payload.tap_config), 22) \
X(a, STATIC, ONEOF, MESSAGE, (payload,assign_id,payload.assign_id), 23) \
X(a, STATIC, ONEOF, MESSAGE, (payload,clear_id_binding,payload.clear_id_binding), 24)
#define alox_EspNowMessage_CALLBACK NULL
#define alox_EspNowMessage_DEFAULT NULL
#define alox_EspNowMessage_payload_discover_MSGTYPE alox_EspNowDiscover
@@ -558,6 +596,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload,tap_config,payload.tap_config), 22)
#define alox_EspNowMessage_payload_echo_ping_MSGTYPE alox_EspNowEchoPing
#define alox_EspNowMessage_payload_echo_pong_MSGTYPE alox_EspNowEchoPong
#define alox_EspNowMessage_payload_tap_config_MSGTYPE alox_EspNowTapConfig
#define alox_EspNowMessage_payload_assign_id_MSGTYPE alox_EspNowAssignId
#define alox_EspNowMessage_payload_clear_id_binding_MSGTYPE alox_EspNowClearIdBinding
extern const pb_msgdesc_t alox_EspNowUnicastTest_msg;
extern const pb_msgdesc_t alox_EspNowEchoPing_msg;
@@ -566,6 +606,8 @@ extern const pb_msgdesc_t alox_EspNowFindMe_msg;
extern const pb_msgdesc_t alox_EspNowRestart_msg;
extern const pb_msgdesc_t alox_EspNowDiscover_msg;
extern const pb_msgdesc_t alox_EspNowSlavePresence_msg;
extern const pb_msgdesc_t alox_EspNowAssignId_msg;
extern const pb_msgdesc_t alox_EspNowClearIdBinding_msg;
extern const pb_msgdesc_t alox_EspNowAccelDeadzone_msg;
extern const pb_msgdesc_t alox_EspNowAccelStream_msg;
extern const pb_msgdesc_t alox_EspNowAccelSample_msg;
@@ -589,6 +631,8 @@ extern const pb_msgdesc_t alox_EspNowMessage_msg;
#define alox_EspNowRestart_fields &alox_EspNowRestart_msg
#define alox_EspNowDiscover_fields &alox_EspNowDiscover_msg
#define alox_EspNowSlavePresence_fields &alox_EspNowSlavePresence_msg
#define alox_EspNowAssignId_fields &alox_EspNowAssignId_msg
#define alox_EspNowClearIdBinding_fields &alox_EspNowClearIdBinding_msg
#define alox_EspNowAccelDeadzone_fields &alox_EspNowAccelDeadzone_msg
#define alox_EspNowAccelStream_fields &alox_EspNowAccelStream_msg
#define alox_EspNowAccelSample_fields &alox_EspNowAccelSample_msg
@@ -611,8 +655,10 @@ extern const pb_msgdesc_t alox_EspNowMessage_msg;
#define alox_EspNowAccelDeadzone_size 12
#define alox_EspNowAccelSample_size 24
#define alox_EspNowAccelStream_size 8
#define alox_EspNowAssignId_size 6
#define alox_EspNowBatteryQuery_size 6
#define alox_EspNowBatteryReport_size 22
#define alox_EspNowClearIdBinding_size 0
#define alox_EspNowDiscover_size 8
#define alox_EspNowEchoPing_size 22
#define alox_EspNowEchoPong_size 22