Skip to content

Commit

Permalink
Rename "satellite enabled" to "mute" (#105619)
Browse files Browse the repository at this point in the history
  • Loading branch information
synesthesiam committed Dec 13, 2023
1 parent 66d24b3 commit aaccf19
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 85 deletions.
28 changes: 14 additions & 14 deletions homeassistant/components/wyoming/devices.py
Expand Up @@ -17,14 +17,14 @@ class SatelliteDevice:
satellite_id: str
device_id: str
is_active: bool = False
is_enabled: bool = True
is_muted: bool = False
pipeline_name: str | None = None
noise_suppression_level: int = 0
auto_gain: int = 0
volume_multiplier: float = 1.0

_is_active_listener: Callable[[], None] | None = None
_is_enabled_listener: Callable[[], None] | None = None
_is_muted_listener: Callable[[], None] | None = None
_pipeline_listener: Callable[[], None] | None = None
_audio_settings_listener: Callable[[], None] | None = None

Expand All @@ -37,12 +37,12 @@ def set_is_active(self, active: bool) -> None:
self._is_active_listener()

@callback
def set_is_enabled(self, enabled: bool) -> None:
"""Set enabled state."""
if enabled != self.is_enabled:
self.is_enabled = enabled
if self._is_enabled_listener is not None:
self._is_enabled_listener()
def set_is_muted(self, muted: bool) -> None:
"""Set muted state."""
if muted != self.is_muted:
self.is_muted = muted
if self._is_muted_listener is not None:
self._is_muted_listener()

@callback
def set_pipeline_name(self, pipeline_name: str) -> None:
Expand Down Expand Up @@ -82,9 +82,9 @@ def set_is_active_listener(self, is_active_listener: Callable[[], None]) -> None
self._is_active_listener = is_active_listener

@callback
def set_is_enabled_listener(self, is_enabled_listener: Callable[[], None]) -> None:
"""Listen for updates to is_enabled."""
self._is_enabled_listener = is_enabled_listener
def set_is_muted_listener(self, is_muted_listener: Callable[[], None]) -> None:
"""Listen for updates to muted status."""
self._is_muted_listener = is_muted_listener

@callback
def set_pipeline_listener(self, pipeline_listener: Callable[[], None]) -> None:
Expand All @@ -105,11 +105,11 @@ def get_assist_in_progress_entity_id(self, hass: HomeAssistant) -> str | None:
"binary_sensor", DOMAIN, f"{self.satellite_id}-assist_in_progress"
)

def get_satellite_enabled_entity_id(self, hass: HomeAssistant) -> str | None:
"""Return entity id for satellite enabled switch."""
def get_muted_entity_id(self, hass: HomeAssistant) -> str | None:
"""Return entity id for satellite muted switch."""
ent_reg = er.async_get(hass)
return ent_reg.async_get_entity_id(
"switch", DOMAIN, f"{self.satellite_id}-satellite_enabled"
"switch", DOMAIN, f"{self.satellite_id}-mute"
)

def get_pipeline_entity_id(self, hass: HomeAssistant) -> str | None:
Expand Down
44 changes: 21 additions & 23 deletions homeassistant/components/wyoming/satellite.py
Expand Up @@ -49,17 +49,16 @@ def __init__(
self.hass = hass
self.service = service
self.device = device
self.is_enabled = True
self.is_running = True

self._client: AsyncTcpClient | None = None
self._chunk_converter = AudioChunkConverter(rate=16000, width=2, channels=1)
self._is_pipeline_running = False
self._audio_queue: asyncio.Queue[bytes | None] = asyncio.Queue()
self._pipeline_id: str | None = None
self._enabled_changed_event = asyncio.Event()
self._muted_changed_event = asyncio.Event()

self.device.set_is_enabled_listener(self._enabled_changed)
self.device.set_is_muted_listener(self._muted_changed)
self.device.set_pipeline_listener(self._pipeline_changed)
self.device.set_audio_settings_listener(self._audio_settings_changed)

Expand All @@ -70,11 +69,11 @@ async def run(self) -> None:
try:
while self.is_running:
try:
# Check if satellite has been disabled
while not self.device.is_enabled:
await self.on_disabled()
# Check if satellite has been muted
while self.device.is_muted:
await self.on_muted()
if not self.is_running:
# Satellite was stopped while waiting to be enabled
# Satellite was stopped while waiting to be unmuted
return

# Connect and run pipeline loop
Expand All @@ -93,8 +92,8 @@ def stop(self) -> None:
"""Signal satellite task to stop running."""
self.is_running = False

# Unblock waiting for enabled
self._enabled_changed_event.set()
# Unblock waiting for unmuted
self._muted_changed_event.set()

async def on_restart(self) -> None:
"""Block until pipeline loop will be restarted."""
Expand All @@ -112,25 +111,24 @@ async def on_reconnect(self) -> None:
)
await asyncio.sleep(_RECONNECT_SECONDS)

async def on_disabled(self) -> None:
"""Block until device may be enabled again."""
await self._enabled_changed_event.wait()
async def on_muted(self) -> None:
"""Block until device may be unmated again."""
await self._muted_changed_event.wait()

async def on_stopped(self) -> None:
"""Run when run() has fully stopped."""
_LOGGER.debug("Satellite task stopped")

# -------------------------------------------------------------------------

def _enabled_changed(self) -> None:
"""Run when device enabled status changes."""

if not self.device.is_enabled:
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)

self._enabled_changed_event.set()
self._enabled_changed_event.clear()
self._muted_changed_event.set()
self._muted_changed_event.clear()

def _pipeline_changed(self) -> None:
"""Run when device pipeline changes."""
Expand All @@ -148,7 +146,7 @@ async def _run_once(self) -> None:
"""Run pipelines until an error occurs."""
self.device.set_is_active(False)

while self.is_running and self.is_enabled:
while self.is_running and (not self.device.is_muted):
try:
await self._connect()
break
Expand All @@ -158,7 +156,7 @@ async def _run_once(self) -> None:
assert self._client is not None
_LOGGER.debug("Connected to satellite")

if (not self.is_running) or (not self.is_enabled):
if (not self.is_running) or self.device.is_muted:
# Run was cancelled or satellite was disabled during connection
return

Expand All @@ -167,7 +165,7 @@ async def _run_once(self) -> None:

# Wait until we get RunPipeline event
run_pipeline: RunPipeline | None = None
while self.is_running and self.is_enabled:
while self.is_running and (not self.device.is_muted):
run_event = await self._client.read_event()
if run_event is None:
raise ConnectionResetError("Satellite disconnected")
Expand All @@ -181,7 +179,7 @@ async def _run_once(self) -> None:
assert run_pipeline is not None
_LOGGER.debug("Received run information: %s", run_pipeline)

if (not self.is_running) or (not self.is_enabled):
if (not self.is_running) or self.device.is_muted:
# Run was cancelled or satellite was disabled while waiting for
# RunPipeline event.
return
Expand All @@ -196,7 +194,7 @@ async def _run_once(self) -> None:
raise ValueError(f"Invalid end stage: {end_stage}")

# Each loop is a pipeline run
while self.is_running and self.is_enabled:
while self.is_running and (not self.device.is_muted):
# Use select to get pipeline each time in case it's changed
pipeline_id = pipeline_select.get_chosen_pipeline(
self.hass,
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/wyoming/strings.json
Expand Up @@ -49,8 +49,8 @@
}
},
"switch": {
"satellite_enabled": {
"name": "Satellite enabled"
"mute": {
"name": "Mute"
}
},
"number": {
Expand Down
18 changes: 9 additions & 9 deletions homeassistant/components/wyoming/switch.py
Expand Up @@ -29,17 +29,17 @@ async def async_setup_entry(
# Setup is only forwarded for satellites
assert item.satellite is not None

async_add_entities([WyomingSatelliteEnabledSwitch(item.satellite.device)])
async_add_entities([WyomingSatelliteMuteSwitch(item.satellite.device)])


class WyomingSatelliteEnabledSwitch(
class WyomingSatelliteMuteSwitch(
WyomingSatelliteEntity, restore_state.RestoreEntity, SwitchEntity
):
"""Entity to represent if satellite is enabled."""
"""Entity to represent if satellite is muted."""

entity_description = SwitchEntityDescription(
key="satellite_enabled",
translation_key="satellite_enabled",
key="mute",
translation_key="mute",
entity_category=EntityCategory.CONFIG,
)

Expand All @@ -49,17 +49,17 @@ async def async_added_to_hass(self) -> None:

state = await self.async_get_last_state()

# Default to on
self._attr_is_on = (state is None) or (state.state == STATE_ON)
# Default to off
self._attr_is_on = (state is not None) and (state.state == STATE_ON)

async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on."""
self._attr_is_on = True
self.async_write_ha_state()
self._device.set_is_enabled(True)
self._device.set_is_muted(True)

async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off."""
self._attr_is_on = False
self.async_write_ha_state()
self._device.set_is_enabled(False)
self._device.set_is_muted(False)
20 changes: 10 additions & 10 deletions tests/components/wyoming/test_devices.py
Expand Up @@ -5,7 +5,7 @@
from homeassistant.components.wyoming import DOMAIN
from homeassistant.components.wyoming.devices import SatelliteDevice
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.const import STATE_OFF
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr

Expand Down Expand Up @@ -34,11 +34,11 @@ async def test_device_registry_info(
assert assist_in_progress_state is not None
assert assist_in_progress_state.state == STATE_OFF

satellite_enabled_id = satellite_device.get_satellite_enabled_entity_id(hass)
assert satellite_enabled_id
satellite_enabled_state = hass.states.get(satellite_enabled_id)
assert satellite_enabled_state is not None
assert satellite_enabled_state.state == STATE_ON
muted_id = satellite_device.get_muted_entity_id(hass)
assert muted_id
muted_state = hass.states.get(muted_id)
assert muted_state is not None
assert muted_state.state == STATE_OFF

pipeline_entity_id = satellite_device.get_pipeline_entity_id(hass)
assert pipeline_entity_id
Expand All @@ -59,9 +59,9 @@ async def test_remove_device_registry_entry(
assert assist_in_progress_id
assert hass.states.get(assist_in_progress_id) is not None

satellite_enabled_id = satellite_device.get_satellite_enabled_entity_id(hass)
assert satellite_enabled_id
assert hass.states.get(satellite_enabled_id) is not None
muted_id = satellite_device.get_muted_entity_id(hass)
assert muted_id
assert hass.states.get(muted_id) is not None

pipeline_entity_id = satellite_device.get_pipeline_entity_id(hass)
assert pipeline_entity_id
Expand All @@ -74,5 +74,5 @@ async def test_remove_device_registry_entry(

# Everything should be gone
assert hass.states.get(assist_in_progress_id) is None
assert hass.states.get(satellite_enabled_id) is None
assert hass.states.get(muted_id) is None
assert hass.states.get(pipeline_entity_id) is None
26 changes: 13 additions & 13 deletions tests/components/wyoming/test_satellite.py
Expand Up @@ -196,7 +196,7 @@ async def test_satellite_pipeline(hass: HomeAssistant) -> None:
await mock_client.detect_event.wait()

assert not device.is_active
assert device.is_enabled
assert not device.is_muted

# Wake word is detected
event_callback(
Expand Down Expand Up @@ -312,36 +312,36 @@ async def test_satellite_pipeline(hass: HomeAssistant) -> None:
await hass.async_block_till_done()


async def test_satellite_disabled(hass: HomeAssistant) -> None:
"""Test callback for a satellite that has been disabled."""
on_disabled_event = asyncio.Event()
async def test_satellite_muted(hass: HomeAssistant) -> None:
"""Test callback for a satellite that has been muted."""
on_muted_event = asyncio.Event()

original_make_satellite = wyoming._make_satellite

def make_disabled_satellite(
def make_muted_satellite(
hass: HomeAssistant, config_entry: ConfigEntry, service: WyomingService
):
satellite = original_make_satellite(hass, config_entry, service)
satellite.device.set_is_enabled(False)
satellite.device.set_is_muted(True)

return satellite

async def on_disabled(self):
self.device.set_is_enabled(True)
on_disabled_event.set()
async def on_muted(self):
self.device.set_is_muted(False)
on_muted_event.set()

with patch(
"homeassistant.components.wyoming.data.load_wyoming_info",
return_value=SATELLITE_INFO,
), patch(
"homeassistant.components.wyoming._make_satellite", make_disabled_satellite
"homeassistant.components.wyoming._make_satellite", make_muted_satellite
), patch(
"homeassistant.components.wyoming.satellite.WyomingSatellite.on_disabled",
on_disabled,
"homeassistant.components.wyoming.satellite.WyomingSatellite.on_muted",
on_muted,
):
await setup_config_entry(hass)
async with asyncio.timeout(1):
await on_disabled_event.wait()
await on_muted_event.wait()


async def test_satellite_restart(hass: HomeAssistant) -> None:
Expand Down
28 changes: 14 additions & 14 deletions tests/components/wyoming/test_switch.py
Expand Up @@ -7,35 +7,35 @@
from . import reload_satellite


async def test_satellite_enabled(
async def test_muted(
hass: HomeAssistant,
satellite_config_entry: ConfigEntry,
satellite_device: SatelliteDevice,
) -> None:
"""Test satellite enabled."""
satellite_enabled_id = satellite_device.get_satellite_enabled_entity_id(hass)
assert satellite_enabled_id
"""Test satellite muted."""
muted_id = satellite_device.get_muted_entity_id(hass)
assert muted_id

state = hass.states.get(satellite_enabled_id)
state = hass.states.get(muted_id)
assert state is not None
assert state.state == STATE_ON
assert satellite_device.is_enabled
assert state.state == STATE_OFF
assert not satellite_device.is_muted

await hass.services.async_call(
"switch",
"turn_off",
{"entity_id": satellite_enabled_id},
"turn_on",
{"entity_id": muted_id},
blocking=True,
)

state = hass.states.get(satellite_enabled_id)
state = hass.states.get(muted_id)
assert state is not None
assert state.state == STATE_OFF
assert not satellite_device.is_enabled
assert state.state == STATE_ON
assert satellite_device.is_muted

# test restore
satellite_device = await reload_satellite(hass, satellite_config_entry.entry_id)

state = hass.states.get(satellite_enabled_id)
state = hass.states.get(muted_id)
assert state is not None
assert state.state == STATE_OFF
assert state.state == STATE_ON

0 comments on commit aaccf19

Please sign in to comment.