implement front led switch on

This commit is contained in:
2026-03-10 16:13:45 +01:00
parent 1632e659e5
commit ba27f6155b
3 changed files with 78 additions and 2 deletions

View File

@@ -1684,7 +1684,21 @@ if is_started or is_stopped:
# System expander (collapsed)
############################
with st.expander("System control", expanded=False):
st.subheader("Status LED")
led_enabled_current = bool(saved_settings.get("led_enabled", True))
led_enabled = st.checkbox(
"Blue LED on while transmitting",
value=led_enabled_current,
help="When enabled, the blue LED on GPIO pin 12 lights up while the stream is active."
)
if led_enabled != led_enabled_current:
try:
requests.post(f"{BACKEND_URL}/set_led_enabled", json={"led_enabled": led_enabled}, timeout=2)
except Exception as e:
st.error(f"Failed to update LED setting: {e}")
st.rerun()
st.subheader("System temperatures")
temp_col1, temp_col2, temp_col3 = st.columns([1, 1, 1])
with temp_col1:

View File

@@ -26,6 +26,53 @@ from auracast.utils.sounddevice_utils import (
)
load_dotenv()
# Blue LED on GPIO pin 12 (BCM) turns on while transmitting
LED_PIN = 12
try:
import RPi.GPIO as _GPIO
_GPIO.setmode(_GPIO.BCM)
_GPIO.setup(LED_PIN, _GPIO.OUT)
_GPIO_AVAILABLE = True
except Exception:
_GPIO_AVAILABLE = False
_GPIO = None # type: ignore
_LED_ENABLED: bool = True # toggled via /set_led_enabled
_LED_SETTINGS_FILE = os.path.join(os.path.dirname(__file__), 'led_settings.json')
def _load_led_settings() -> None:
global _LED_ENABLED
try:
if os.path.exists(_LED_SETTINGS_FILE):
with open(_LED_SETTINGS_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
_LED_ENABLED = bool(data.get('led_enabled', True))
except Exception:
_LED_ENABLED = True
def _save_led_settings() -> None:
try:
os.makedirs(os.path.dirname(_LED_SETTINGS_FILE), exist_ok=True)
with open(_LED_SETTINGS_FILE, 'w', encoding='utf-8') as f:
json.dump({'led_enabled': _LED_ENABLED}, f)
except Exception:
pass
def _led_on():
if _GPIO_AVAILABLE and _LED_ENABLED:
try:
_GPIO.output(LED_PIN, _GPIO.HIGH)
except Exception:
pass
def _led_off():
if _GPIO_AVAILABLE:
try:
_GPIO.output(LED_PIN, _GPIO.LOW)
except Exception:
pass
# make sure pipewire sets latency
# Primary and secondary persisted settings files
STREAM_SETTINGS_FILE1 = os.path.join(os.path.dirname(__file__), 'stream_settings.json')
@@ -284,6 +331,7 @@ async def _stop_all() -> bool:
was_running = True
finally:
multicaster2 = None
_led_off()
return was_running
async def _status_primary() -> dict:
@@ -468,6 +516,7 @@ async def init_radio(transport: str, conf: auracast_config.AuracastConfigGroup,
auto_started = False
if any(isinstance(big.audio_source, str) and (big.audio_source.startswith("device:") or big.audio_source.startswith("alsa:") or big.audio_source.startswith("file:")) for big in conf.bigs):
await mc.start_streaming()
_led_on()
auto_started = True
demo_count = sum(1 for big in conf.bigs if isinstance(big.audio_source, str) and big.audio_source.startswith('file:'))
@@ -527,6 +576,16 @@ async def initialize2(conf: auracast_config.AuracastConfigGroup):
multicaster2 = mc
save_settings(persisted, secondary=True)
@app.post("/set_led_enabled")
async def set_led_enabled(body: dict):
"""Enable or disable the blue status LED. Persisted across restarts."""
global _LED_ENABLED
_LED_ENABLED = bool(body.get("led_enabled", True))
_save_led_settings()
if not _LED_ENABLED:
_led_off()
return {"led_enabled": _LED_ENABLED}
@app.post("/stop_audio")
async def stop_audio():
"""Stops streaming on both multicaster1 and multicaster2 (worker thread)."""
@@ -590,6 +649,7 @@ async def get_status():
secondary.update(secondary_persisted)
status["secondary"] = secondary
status["secondary_is_streaming"] = bool(secondary.get("is_streaming", False))
status["led_enabled"] = _LED_ENABLED
return status
@@ -921,6 +981,7 @@ async def _autostart_from_settings():
async def _startup_autostart_event():
# Spawn the autostart task without blocking startup
log.info("[STARTUP] Auracast multicast server startup: initializing settings cache, I2C, and PipeWire cache")
_led_off()
# Run install_asoundconf.sh script
script_path = os.path.join(os.path.dirname(__file__), '..', 'misc', 'install_asoundconf.sh')
@@ -934,6 +995,7 @@ async def _startup_autostart_event():
log.error(f"[STARTUP] Error running install_asoundconf.sh: {str(e)}")
# Hydrate settings cache once to avoid disk I/O during /status
_load_led_settings()
_init_settings_cache_from_disk()
await _init_i2c_on_startup()
# Ensure ADC mixer level is set at startup (default 50%)

View File

@@ -11,7 +11,7 @@ while True:
print("toggle led ON")
GPIO.output(GPIO_PIN, GPIO.HIGH)
time.sleep(1)
print("toggle led ON")
print("toggle led OFF")
GPIO.output(GPIO_PIN, GPIO.LOW)
time.sleep(1)