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(