From cffd95a015dad372b7316b1731ae77d1fb2958e0 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Tue, 23 Jan 2024 19:37:25 -0600 Subject: [PATCH] Pause Wyoming satellite on mute (#108322) Pause satellite on mute --- .../components/wyoming/manifest.json | 2 +- homeassistant/components/wyoming/satellite.py | 34 +++++++++++++++---- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/wyoming/__init__.py | 7 ++++ tests/components/wyoming/test_wake_word.py | 3 ++ 6 files changed, 41 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/wyoming/manifest.json b/homeassistant/components/wyoming/manifest.json index 430e46fd890..14cf9f77683 100644 --- a/homeassistant/components/wyoming/manifest.json +++ b/homeassistant/components/wyoming/manifest.json @@ -6,6 +6,6 @@ "dependencies": ["assist_pipeline"], "documentation": "https://www.home-assistant.io/integrations/wyoming", "iot_class": "local_push", - "requirements": ["wyoming==1.5.0"], + "requirements": ["wyoming==1.5.2"], "zeroconf": ["_wyoming._tcp.local."] } diff --git a/homeassistant/components/wyoming/satellite.py b/homeassistant/components/wyoming/satellite.py index 8e7586534f5..0cb2796b9f0 100644 --- a/homeassistant/components/wyoming/satellite.py +++ b/homeassistant/components/wyoming/satellite.py @@ -12,7 +12,7 @@ from wyoming.client import AsyncTcpClient from wyoming.error import Error from wyoming.ping import Ping, Pong from wyoming.pipeline import PipelineStage, RunPipeline -from wyoming.satellite import RunSatellite +from wyoming.satellite import PauseSatellite, RunSatellite from wyoming.tts import Synthesize, SynthesizeVoice from wyoming.vad import VoiceStarted, VoiceStopped from wyoming.wake import Detect, Detection @@ -76,6 +76,7 @@ class WyomingSatellite: try: # Check if satellite has been muted while self.device.is_muted: + _LOGGER.debug("Satellite is muted") await self.on_muted() if not self.is_running: # Satellite was stopped while waiting to be unmuted @@ -86,15 +87,23 @@ class WyomingSatellite: except asyncio.CancelledError: raise # don't restart except Exception: # pylint: disable=broad-exception-caught + # Ensure sensor is off (before restart) + self.device.set_is_active(False) + + # Wait to restart await self.on_restart() finally: - # Ensure sensor is off + # Ensure sensor is off (before stop) self.device.set_is_active(False) await self.on_stopped() def stop(self) -> None: """Signal satellite task to stop running.""" + # Tell satellite to stop running + self._send_pause() + + # Stop task loop self.is_running = False # Unblock waiting for unmuted @@ -103,7 +112,7 @@ class WyomingSatellite: async def on_restart(self) -> None: """Block until pipeline loop will be restarted.""" _LOGGER.warning( - "Unexpected error running satellite. Restarting in %s second(s)", + "Satellite has been disconnected. Reconnecting in %s second(s)", _RECONNECT_SECONDS, ) await asyncio.sleep(_RESTART_SECONDS) @@ -126,12 +135,23 @@ class WyomingSatellite: # ------------------------------------------------------------------------- + def _send_pause(self) -> None: + """Send a pause message to satellite.""" + if self._client is not None: + self.hass.async_create_background_task( + self._client.write_event(PauseSatellite().event()), + "pause satellite", + ) + def _muted_changed(self) -> None: """Run when device muted status changes.""" if self.device.is_muted: # Cancel any running pipeline self._audio_queue.put_nowait(None) + # Send pause event so satellite can react immediately + self._send_pause() + self._muted_changed_event.set() self._muted_changed_event.clear() @@ -149,16 +169,18 @@ class WyomingSatellite: async def _connect_and_loop(self) -> None: """Connect to satellite and run pipelines until an error occurs.""" - self.device.set_is_active(False) - while self.is_running and (not self.device.is_muted): try: await self._connect() break except ConnectionError: + self._client = None # client is not valid + await self.on_reconnect() - assert self._client is not None + if self._client is None: + return + _LOGGER.debug("Connected to satellite") if (not self.is_running) or self.device.is_muted: diff --git a/requirements_all.txt b/requirements_all.txt index 2ba9def2cf5..f8093a92aaf 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2825,7 +2825,7 @@ wled==0.17.0 wolf-smartset==0.1.11 # homeassistant.components.wyoming -wyoming==1.5.0 +wyoming==1.5.2 # homeassistant.components.xbox xbox-webapi==2.0.11 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 974bd73385a..8059ffd271d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2148,7 +2148,7 @@ wled==0.17.0 wolf-smartset==0.1.11 # homeassistant.components.wyoming -wyoming==1.5.0 +wyoming==1.5.2 # homeassistant.components.xbox xbox-webapi==2.0.11 diff --git a/tests/components/wyoming/__init__.py b/tests/components/wyoming/__init__.py index 268ebef1d06..2adc9a21b6f 100644 --- a/tests/components/wyoming/__init__.py +++ b/tests/components/wyoming/__init__.py @@ -35,8 +35,10 @@ STT_INFO = Info( installed=True, attribution=TEST_ATTR, languages=["en-US"], + version=None, ) ], + version=None, ) ] ) @@ -55,8 +57,10 @@ TTS_INFO = Info( attribution=TEST_ATTR, languages=["en-US"], speakers=[TtsVoiceSpeaker(name="Test Speaker")], + version=None, ) ], + version=None, ) ] ) @@ -74,8 +78,10 @@ WAKE_WORD_INFO = Info( installed=True, attribution=TEST_ATTR, languages=["en-US"], + version=None, ) ], + version=None, ) ] ) @@ -86,6 +92,7 @@ SATELLITE_INFO = Info( installed=True, attribution=TEST_ATTR, area="Office", + version=None, ) ) EMPTY_INFO = Info() diff --git a/tests/components/wyoming/test_wake_word.py b/tests/components/wyoming/test_wake_word.py index 36a6daf0452..1ab869b1b0a 100644 --- a/tests/components/wyoming/test_wake_word.py +++ b/tests/components/wyoming/test_wake_word.py @@ -188,6 +188,7 @@ async def test_dynamic_wake_word_info( installed=True, attribution=TEST_ATTR, languages=[], + version=None, ), WakeModel( name="ww2", @@ -195,8 +196,10 @@ async def test_dynamic_wake_word_info( installed=True, attribution=TEST_ATTR, languages=[], + version=None, ), ], + version=None, ) ] )