implement front led switch on
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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%)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user