From 0073dc6a23b20d0020372952b595ccac6c1ae994 Mon Sep 17 00:00:00 2001 From: imonlinux <39863321+imonlinux@users.noreply.github.com> Date: Sat, 29 Nov 2025 23:42:24 -0800 Subject: [PATCH] Update __main__.py Imported the new ButtonController. In _init_controllers(): Instantiated ButtonController when config.button.enabled is True. Passed loop, event_bus, state, and config.button. Stored the instance on state.button_controller to keep it alive for the lifetime of the process. Left the rest of startup orchestration unchanged (audio engine, MQTT, LEDs, etc.), so the button is just an additional input surface plugged into the existing architecture. --- linux_voice_assistant/__main__.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/linux_voice_assistant/__main__.py b/linux_voice_assistant/__main__.py index 29f93de..6381589 100644 --- a/linux_voice_assistant/__main__.py +++ b/linux_voice_assistant/__main__.py @@ -15,6 +15,7 @@ from pymicro_wakeword import MicroWakeWord, MicroWakeWordFeatures from pyopen_wakeword import OpenWakeWord from .audio_engine import AudioEngine +from .button_controller import ButtonController from .config import Config, load_config_from_json from .event_bus import EventBus, EventHandler, subscribe from .led_controller import LedController @@ -41,6 +42,7 @@ class WakeWordData: active: Set[str] stop_model: MicroWakeWord + @dataclass class MediaPlayers: """Dataclass to hold media player instances.""" @@ -107,7 +109,7 @@ class MicMuteHandler(EventHandler): { "alarm_duration_seconds": } Semantics: - 0 -> infinite alarm (only stop via Stop wake word / wake word logic) + 0 -> infinite alarm (only Stop/wake word stops it) >0 -> auto-stop alarm after N seconds (plus Stop wake word support) """ duration = data.get("alarm_duration_seconds") @@ -424,6 +426,22 @@ def _init_controllers( mqtt_controller=mqtt_controller, ) + # Hardware button controller (e.g. ReSpeaker 2-Mic HAT) + try: + if getattr(config, "button", None) is not None and config.button.enabled: + button_controller = ButtonController( + loop=loop, + event_bus=event_bus, + state=state, + config=config.button, + ) + # Keep a reference on state so it is not garbage-collected. + setattr(state, "button_controller", button_controller) + else: + _LOGGER.debug("ButtonController not enabled in config; skipping") + except Exception: + _LOGGER.exception("Failed to initialize ButtonController") + async def _run_server(state: ServerState, config: Config): """Starts the ESPHome server and ZeroConf discovery.""" server = await state.loop.create_server(