Add LED ring control per client and broadcast over REST and WebSocket.

Solid color mode fills all ring LEDs; master routes UART commands to slaves
via ESPNOW_LED_RING. goTool exposes POST /api/led-ring, WebSocket set_led_ring,
and a dashboard LED panel with master/slave/all targets.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-29 19:24:55 +02:00
co-authored by Cursor
parent 47c75110c9
commit eb67a46158
21 changed files with 759 additions and 133 deletions
+28 -10
View File
@@ -139,8 +139,8 @@ typedef struct _alox_EspNowUnicastTestResponse {
uint32_t seq;
} alox_EspNowUnicastTestResponse;
/* Host → device: LED ring display (progress bar, digit, clear, blink, or find-me).
mode: 0=clear, 1=progress (0100 %), 2=digit (010), 3=blink full ring, 4=find-me (R/G/B ×3 @ full brightness). */
/* Host → master: LED ring on master (client_id=0) and/or slaves via ESP-NOW.
mode: 0=clear, 1=progress (0100 %), 2=digit (010), 3=blink, 4=find-me, 5=all LEDs solid color. */
typedef struct _alox_LedRingProgressRequest {
uint32_t mode;
/* * 0100: fraction of ring LEDs to light (mode=progress) */
@@ -156,6 +156,12 @@ typedef struct _alox_LedRingProgressRequest {
uint32_t blink_ms;
/* * Number of pulses (mode=blink, default 1) */
uint32_t blink_count;
/* * 0 = master ring only; >0 = one slave; ignored when all_clients */
uint32_t client_id;
/* * Broadcast to all registered slaves (and optionally master unless slaves_only) */
bool all_clients;
/* * With all_clients: do not change master ring */
bool slaves_only;
} alox_LedRingProgressRequest;
typedef struct _alox_LedRingProgressResponse {
@@ -163,6 +169,8 @@ typedef struct _alox_LedRingProgressResponse {
uint32_t mode;
uint32_t progress;
uint32_t digit;
uint32_t client_id;
uint32_t slaves_updated;
} alox_LedRingProgressResponse;
/* * Host → master: find-me on local ring (client_id=0) or ESP-NOW unicast to one slave. */
@@ -326,8 +334,8 @@ extern "C" {
#define alox_AccelSnapshotResponse_init_default {0, {alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default, alox_AccelSample_init_default}}
#define alox_EspNowUnicastTestRequest_init_default {0, 0}
#define alox_EspNowUnicastTestResponse_init_default {0, 0}
#define alox_LedRingProgressRequest_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define alox_LedRingProgressResponse_init_default {0, 0, 0, 0}
#define alox_LedRingProgressRequest_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define alox_LedRingProgressResponse_init_default {0, 0, 0, 0, 0, 0}
#define alox_EspNowFindMeRequest_init_default {0}
#define alox_EspNowFindMeResponse_init_default {0, 0}
#define alox_RestartRequest_init_default {0}
@@ -356,8 +364,8 @@ extern "C" {
#define alox_AccelSnapshotResponse_init_zero {0, {alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero, alox_AccelSample_init_zero}}
#define alox_EspNowUnicastTestRequest_init_zero {0, 0}
#define alox_EspNowUnicastTestResponse_init_zero {0, 0}
#define alox_LedRingProgressRequest_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define alox_LedRingProgressResponse_init_zero {0, 0, 0, 0}
#define alox_LedRingProgressRequest_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define alox_LedRingProgressResponse_init_zero {0, 0, 0, 0, 0, 0}
#define alox_EspNowFindMeRequest_init_zero {0}
#define alox_EspNowFindMeResponse_init_zero {0, 0}
#define alox_RestartRequest_init_zero {0}
@@ -426,10 +434,15 @@ extern "C" {
#define alox_LedRingProgressRequest_intensity_tag 7
#define alox_LedRingProgressRequest_blink_ms_tag 8
#define alox_LedRingProgressRequest_blink_count_tag 9
#define alox_LedRingProgressRequest_client_id_tag 10
#define alox_LedRingProgressRequest_all_clients_tag 11
#define alox_LedRingProgressRequest_slaves_only_tag 12
#define alox_LedRingProgressResponse_success_tag 1
#define alox_LedRingProgressResponse_mode_tag 2
#define alox_LedRingProgressResponse_progress_tag 3
#define alox_LedRingProgressResponse_digit_tag 4
#define alox_LedRingProgressResponse_client_id_tag 5
#define alox_LedRingProgressResponse_slaves_updated_tag 6
#define alox_EspNowFindMeRequest_client_id_tag 1
#define alox_EspNowFindMeResponse_success_tag 1
#define alox_EspNowFindMeResponse_client_id_tag 2
@@ -660,7 +673,10 @@ X(a, STATIC, SINGULAR, UINT32, g, 5) \
X(a, STATIC, SINGULAR, UINT32, b, 6) \
X(a, STATIC, SINGULAR, UINT32, intensity, 7) \
X(a, STATIC, SINGULAR, UINT32, blink_ms, 8) \
X(a, STATIC, SINGULAR, UINT32, blink_count, 9)
X(a, STATIC, SINGULAR, UINT32, blink_count, 9) \
X(a, STATIC, SINGULAR, UINT32, client_id, 10) \
X(a, STATIC, SINGULAR, BOOL, all_clients, 11) \
X(a, STATIC, SINGULAR, BOOL, slaves_only, 12)
#define alox_LedRingProgressRequest_CALLBACK NULL
#define alox_LedRingProgressRequest_DEFAULT NULL
@@ -668,7 +684,9 @@ X(a, STATIC, SINGULAR, UINT32, blink_count, 9)
X(a, STATIC, SINGULAR, BOOL, success, 1) \
X(a, STATIC, SINGULAR, UINT32, mode, 2) \
X(a, STATIC, SINGULAR, UINT32, progress, 3) \
X(a, STATIC, SINGULAR, UINT32, digit, 4)
X(a, STATIC, SINGULAR, UINT32, digit, 4) \
X(a, STATIC, SINGULAR, UINT32, client_id, 5) \
X(a, STATIC, SINGULAR, UINT32, slaves_updated, 6)
#define alox_LedRingProgressResponse_CALLBACK NULL
#define alox_LedRingProgressResponse_DEFAULT NULL
@@ -826,8 +844,8 @@ extern const pb_msgdesc_t alox_OtaSlaveProgressResponse_msg;
#define alox_EspNowFindMeResponse_size 8
#define alox_EspNowUnicastTestRequest_size 12
#define alox_EspNowUnicastTestResponse_size 8
#define alox_LedRingProgressRequest_size 54
#define alox_LedRingProgressResponse_size 20
#define alox_LedRingProgressRequest_size 64
#define alox_LedRingProgressResponse_size 32
#define alox_OtaEndPayload_size 0
#define alox_OtaPayload_size 209
#define alox_OtaSlaveProgressEntry_size 30