- Reconnect and re-subscribe on every (re)connect; log the subscribe result. - Heartbeat every 5 min on voice/audio_stream (valid silent PCM frame) so the Directive-1 watchdog can tell "device dead" from "nobody spoke". voice_bridge treats it as silence and ignores it. - Retained LWT "offline" / "online" presence on voice/status for layer attribution in the watchdog. - LED: green now means MQTT connected AND publishing. Wi-Fi down = red blink, Wi-Fi up but MQTT down = amber blink. Never green without MQTT. - Log the reason on every drop: PubSubClient state code, or the Wi-Fi disconnect reason from the Wi-Fi event. - Bound the I2S read (50 ms) so Wi-Fi/MQTT housekeeping cannot stall; reset a stale streaming state on disconnect (the stuck-green bug). - Document the MQTT/LED contract in README; flag config.h and led_control.h as stale drafts so they cannot creep back as a second config. - Credentials stay placeholders; nothing secret is committed. Not flashed/tested: no ESP32 and no arduino-cli is reachable from the build environment. Hardware-in-the-loop verification needs a human at the device. Co-Authored-By: Paperclip <noreply@paperclip.ing>
80 lines
2.1 KiB
C
80 lines
2.1 KiB
C
#pragma once
|
|
// STALE / UNUSED. This header is an early LED draft and is NOT compiled:
|
|
// voice_assistant.ino does not include it. It also defines a conflicting
|
|
// `strip` / `DeviceState` / `currentState`, so including it would break the
|
|
// sketch. LED behaviour now lives in voice_assistant.ino (see renderLed()).
|
|
#include <Freenove_WS2812_Lib_for_ESP32.h>
|
|
#include "config.h"
|
|
|
|
// Initialize (LED_COUNT, LED_PIN, CHANNEL, TYPE)
|
|
// Channel 0 is fine.
|
|
Freenove_ESP32_WS2812 strip(NUM_LEDS, LED_PIN, 0, TYPE_GRB);
|
|
|
|
enum DeviceState {
|
|
STATE_IDLE,
|
|
STATE_WAKE_DETECTED,
|
|
STATE_RECORDING,
|
|
STATE_TRANSMITTING,
|
|
STATE_ACK_RECEIVED,
|
|
STATE_ERROR
|
|
};
|
|
|
|
DeviceState currentState = STATE_IDLE;
|
|
unsigned long stateTimer = 0;
|
|
|
|
void setupLEDs() {
|
|
strip.begin();
|
|
strip.setBrightness(30);
|
|
strip.show(); // Off
|
|
}
|
|
|
|
// Helper for Color compatibility
|
|
uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
|
|
return strip.Wheel((r << 16) | (g << 8) | b); // Not used by this lib but keeps API
|
|
}
|
|
|
|
void setRingColor(uint32_t r, uint8_t g, uint8_t b) {
|
|
strip.setAllLedsColor(r, g, b);
|
|
}
|
|
|
|
// Overload for compatibility with previous code calling Color()
|
|
// We actually just need to rewrite the helper slightly
|
|
void setRingColor(uint32_t color) {
|
|
// Extract RGB from 32-bit int
|
|
uint8_t r = (uint8_t)(color >> 16);
|
|
uint8_t g = (uint8_t)(color >> 8);
|
|
uint8_t b = (uint8_t)color;
|
|
strip.setAllLedsColor(r, g, b);
|
|
}
|
|
|
|
void updateLEDs() {
|
|
switch (currentState) {
|
|
case STATE_IDLE:
|
|
strip.setAllLedsColor(0, 0, 0);
|
|
break;
|
|
case STATE_WAKE_DETECTED:
|
|
strip.setAllLedsColor(255, 0, 0);
|
|
break;
|
|
case STATE_RECORDING:
|
|
strip.setAllLedsColor(0, 255, 0);
|
|
break;
|
|
case STATE_TRANSMITTING:
|
|
strip.setAllLedsColor(0, 0, 255);
|
|
break;
|
|
case STATE_ERROR:
|
|
strip.setAllLedsColor(255, 255, 255);
|
|
break;
|
|
case STATE_ACK_RECEIVED:
|
|
// Simple rainbow
|
|
for (int j = 0; j < 255; j += 2) {
|
|
for (int i = 0; i < NUM_LEDS; i++) {
|
|
strip.setLedColorData(i, strip.Wheel((i * 256 / NUM_LEDS + j) & 255));
|
|
}
|
|
strip.show();
|
|
delay(10);
|
|
}
|
|
currentState = STATE_IDLE;
|
|
break;
|
|
}
|
|
}
|