Add audio_delay number entity to Sonos (#63566)

This commit is contained in:
jjlawren 2022-01-10 09:04:40 -06:00 committed by GitHub
parent e2f9284c55
commit 740a8c33ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 113 additions and 18 deletions

View file

@ -5,17 +5,22 @@ import logging
from homeassistant.components.number import NumberEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import SONOS_CREATE_LEVELS
from .entity import SonosEntity
from .exception import SpeakerUnavailable
from .helpers import soco_error
from .speaker import SonosSpeaker
LEVEL_TYPES = ("bass", "treble")
LEVEL_TYPES = {
"audio_delay": (0, 5),
"bass": (-10, 10),
"treble": (-10, 10),
}
_LOGGER = logging.getLogger(__name__)
@ -27,14 +32,26 @@ async def async_setup_entry(
) -> None:
"""Set up the Sonos number platform from a config entry."""
@callback
def _async_create_entities(speaker: SonosSpeaker) -> None:
def available_soco_attributes(speaker: SonosSpeaker) -> list[str]:
features = []
for level_type, valid_range in LEVEL_TYPES.items():
if (state := getattr(speaker.soco, level_type, None)) is not None:
setattr(speaker, level_type, state)
features.append((level_type, valid_range))
return features
async def _async_create_entities(speaker: SonosSpeaker) -> None:
entities = []
for level_type in LEVEL_TYPES:
available_features = await hass.async_add_executor_job(
available_soco_attributes, speaker
)
for level_type, valid_range in available_features:
_LOGGER.debug(
"Creating %s number control on %s", level_type, speaker.zone_name
)
entities.append(SonosLevelEntity(speaker, level_type))
entities.append(SonosLevelEntity(speaker, level_type, valid_range))
async_add_entities(entities)
config_entry.async_on_unload(
@ -46,19 +63,30 @@ class SonosLevelEntity(SonosEntity, NumberEntity):
"""Representation of a Sonos level entity."""
_attr_entity_category = EntityCategory.CONFIG
_attr_min_value = -10
_attr_max_value = 10
def __init__(self, speaker: SonosSpeaker, level_type: str) -> None:
def __init__(
self, speaker: SonosSpeaker, level_type: str, valid_range: tuple[int]
) -> None:
"""Initialize the level entity."""
super().__init__(speaker)
self._attr_unique_id = f"{self.soco.uid}-{level_type}"
self._attr_name = f"{self.speaker.zone_name} {level_type.capitalize()}"
name_suffix = level_type.replace("_", " ").title()
self._attr_name = f"{self.speaker.zone_name} {name_suffix}"
self.level_type = level_type
self._attr_min_value, self._attr_max_value = valid_range
async def _async_poll(self) -> None:
"""Poll the value if subscriptions are not working."""
# Handled by SonosSpeaker
await self.hass.async_add_executor_job(self.update)
@soco_error(raise_on_err=False)
def update(self) -> None:
"""Fetch number state if necessary."""
if not self.available:
raise SpeakerUnavailable
state = getattr(self.soco, self.level_type)
setattr(self.speaker, self.level_type, state)
@soco_error()
def set_value(self, value: float) -> None: