Fix YoLink SpeakerHub support (#107925)
* improve * Fix when hub offline/online message pushing * fix as suggestion * check config entry load state * Add exception translationpull/109883/head
parent
e720b398d2
commit
f61c70b686
|
@ -19,8 +19,10 @@ from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
|||
from homeassistant.helpers import (
|
||||
aiohttp_client,
|
||||
config_entry_oauth2_flow,
|
||||
config_validation as cv,
|
||||
device_registry as dr,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from . import api
|
||||
from .const import DOMAIN, YOLINK_EVENT
|
||||
|
@ -30,6 +32,8 @@ from .services import async_register_services
|
|||
|
||||
SCAN_INTERVAL = timedelta(minutes=5)
|
||||
|
||||
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
|
||||
|
||||
|
||||
PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
|
@ -96,6 +100,14 @@ class YoLinkHomeStore:
|
|||
device_coordinators: dict[str, YoLinkCoordinator]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up YoLink."""
|
||||
|
||||
async_register_services(hass)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up yolink from a config entry."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
@ -147,8 +159,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
async_register_services(hass, entry)
|
||||
|
||||
async def async_yolink_unload(event) -> None:
|
||||
"""Unload yolink."""
|
||||
await yolink_home.async_unload()
|
||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from yolink.client_request import ClientRequest
|
||||
from yolink.const import ATTR_DEVICE_SPEAKER_HUB
|
||||
|
@ -30,6 +31,7 @@ class YoLinkNumberTypeConfigEntityDescription(NumberEntityDescription):
|
|||
"""YoLink NumberEntity description."""
|
||||
|
||||
exists_fn: Callable[[YoLinkDevice], bool]
|
||||
should_update_entity: Callable
|
||||
value: Callable
|
||||
|
||||
|
||||
|
@ -37,6 +39,14 @@ NUMBER_TYPE_CONF_SUPPORT_DEVICES = [ATTR_DEVICE_SPEAKER_HUB]
|
|||
|
||||
SUPPORT_SET_VOLUME_DEVICES = [ATTR_DEVICE_SPEAKER_HUB]
|
||||
|
||||
|
||||
def get_volume_value(state: dict[str, Any]) -> int | None:
|
||||
"""Get volume option."""
|
||||
if (options := state.get("options")) is not None:
|
||||
return options.get("volume")
|
||||
return None
|
||||
|
||||
|
||||
DEVICE_CONFIG_DESCRIPTIONS: tuple[YoLinkNumberTypeConfigEntityDescription, ...] = (
|
||||
YoLinkNumberTypeConfigEntityDescription(
|
||||
key=OPTIONS_VALUME,
|
||||
|
@ -48,7 +58,8 @@ DEVICE_CONFIG_DESCRIPTIONS: tuple[YoLinkNumberTypeConfigEntityDescription, ...]
|
|||
native_unit_of_measurement=None,
|
||||
icon="mdi:volume-high",
|
||||
exists_fn=lambda device: device.device_type in SUPPORT_SET_VOLUME_DEVICES,
|
||||
value=lambda state: state["options"]["volume"],
|
||||
should_update_entity=lambda value: value is not None,
|
||||
value=get_volume_value,
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -98,7 +109,10 @@ class YoLinkNumberTypeConfigEntity(YoLinkEntity, NumberEntity):
|
|||
@callback
|
||||
def update_entity_state(self, state: dict) -> None:
|
||||
"""Update HA Entity State."""
|
||||
attr_val = self.entity_description.value(state)
|
||||
if (
|
||||
attr_val := self.entity_description.value(state)
|
||||
) is None and self.entity_description.should_update_entity(attr_val) is False:
|
||||
return
|
||||
self._attr_native_value = attr_val
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
import voluptuous as vol
|
||||
from yolink.client_request import ClientRequest
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||
|
||||
from .const import (
|
||||
|
@ -19,7 +20,7 @@ from .const import (
|
|||
SERVICE_PLAY_ON_SPEAKER_HUB = "play_on_speaker_hub"
|
||||
|
||||
|
||||
def async_register_services(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
def async_register_services(hass: HomeAssistant) -> None:
|
||||
"""Register services for YoLink integration."""
|
||||
|
||||
async def handle_speaker_hub_play_call(service_call: ServiceCall) -> None:
|
||||
|
@ -28,6 +29,17 @@ def async_register_services(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
|||
device_registry = dr.async_get(hass)
|
||||
device_entry = device_registry.async_get(service_data[ATTR_TARGET_DEVICE])
|
||||
if device_entry is not None:
|
||||
for entry_id in device_entry.config_entries:
|
||||
if (entry := hass.config_entries.async_get_entry(entry_id)) is None:
|
||||
continue
|
||||
if entry.domain == DOMAIN:
|
||||
break
|
||||
if entry is None or entry.state == ConfigEntryState.NOT_LOADED:
|
||||
raise ServiceValidationError(
|
||||
"Config entry not found or not loaded!",
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="invalid_config_entry",
|
||||
)
|
||||
home_store = hass.data[DOMAIN][entry.entry_id]
|
||||
for identifier in device_entry.identifiers:
|
||||
if (
|
||||
|
|
|
@ -7,9 +7,7 @@ play_on_speaker_hub:
|
|||
device:
|
||||
filter:
|
||||
- integration: yolink
|
||||
manufacturer: YoLink
|
||||
model: SpeakerHub
|
||||
|
||||
message:
|
||||
required: true
|
||||
example: hello, yolink
|
||||
|
|
|
@ -37,6 +37,11 @@
|
|||
"button_4_long_press": "Button_4 (long press)"
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"invalid_config_entry": {
|
||||
"message": "Config entry not found or not loaded!"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"switch": {
|
||||
"usb_ports": { "name": "USB ports" },
|
||||
|
|
Loading…
Reference in New Issue