mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Move LG webOS TV actions to entitiy services (#135285)
This commit is contained in:
parent
bce7e9ba5e
commit
1f0eda8e47
@ -4,72 +4,33 @@ from __future__ import annotations
|
||||
|
||||
from contextlib import suppress
|
||||
import logging
|
||||
from typing import NamedTuple
|
||||
|
||||
from aiowebostv import WebOsClient, WebOsTvPairError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import notify as hass_notify
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_COMMAND,
|
||||
ATTR_ENTITY_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant, ServiceCall
|
||||
from homeassistant.core import Event, HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||
from homeassistant.helpers import config_validation as cv, discovery
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import (
|
||||
ATTR_BUTTON,
|
||||
ATTR_CONFIG_ENTRY_ID,
|
||||
ATTR_PAYLOAD,
|
||||
ATTR_SOUND_OUTPUT,
|
||||
DATA_CONFIG_ENTRY,
|
||||
DATA_HASS_CONFIG,
|
||||
DOMAIN,
|
||||
PLATFORMS,
|
||||
SERVICE_BUTTON,
|
||||
SERVICE_COMMAND,
|
||||
SERVICE_SELECT_SOUND_OUTPUT,
|
||||
WEBOSTV_EXCEPTIONS,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
|
||||
|
||||
CALL_SCHEMA = vol.Schema({vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids})
|
||||
|
||||
|
||||
class ServiceMethodDetails(NamedTuple):
|
||||
"""Details for SERVICE_TO_METHOD mapping."""
|
||||
|
||||
method: str
|
||||
schema: vol.Schema
|
||||
|
||||
|
||||
BUTTON_SCHEMA = CALL_SCHEMA.extend({vol.Required(ATTR_BUTTON): cv.string})
|
||||
|
||||
COMMAND_SCHEMA = CALL_SCHEMA.extend(
|
||||
{vol.Required(ATTR_COMMAND): cv.string, vol.Optional(ATTR_PAYLOAD): dict}
|
||||
)
|
||||
|
||||
SOUND_OUTPUT_SCHEMA = CALL_SCHEMA.extend({vol.Required(ATTR_SOUND_OUTPUT): cv.string})
|
||||
|
||||
SERVICE_TO_METHOD = {
|
||||
SERVICE_BUTTON: ServiceMethodDetails(method="async_button", schema=BUTTON_SCHEMA),
|
||||
SERVICE_COMMAND: ServiceMethodDetails(
|
||||
method="async_command", schema=COMMAND_SCHEMA
|
||||
),
|
||||
SERVICE_SELECT_SOUND_OUTPUT: ServiceMethodDetails(
|
||||
method="async_select_sound_output",
|
||||
schema=SOUND_OUTPUT_SCHEMA,
|
||||
),
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -100,17 +61,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
# Update the stored key without triggering reauth
|
||||
update_client_key(hass, entry, client)
|
||||
|
||||
async def async_service_handler(service: ServiceCall) -> None:
|
||||
method = SERVICE_TO_METHOD[service.service]
|
||||
data = service.data.copy()
|
||||
data["method"] = method.method
|
||||
async_dispatcher_send(hass, DOMAIN, data)
|
||||
|
||||
for service, method in SERVICE_TO_METHOD.items():
|
||||
hass.services.async_register(
|
||||
DOMAIN, service, async_service_handler, schema=method.schema
|
||||
)
|
||||
|
||||
hass.data[DOMAIN][DATA_CONFIG_ENTRY][entry.entry_id] = client
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
@ -174,17 +124,10 @@ def update_client_key(
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
if unload_ok:
|
||||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
|
||||
client = hass.data[DOMAIN][DATA_CONFIG_ENTRY].pop(entry.entry_id)
|
||||
await hass_notify.async_reload(hass, DOMAIN)
|
||||
client.clear_state_update_callbacks()
|
||||
await client.disconnect()
|
||||
|
||||
# unregister service calls, check if this is the last entry to unload
|
||||
if unload_ok and not hass.data[DOMAIN][DATA_CONFIG_ENTRY]:
|
||||
for service in SERVICE_TO_METHOD:
|
||||
hass.services.async_remove(DOMAIN, service)
|
||||
|
||||
return unload_ok
|
||||
|
@ -12,6 +12,7 @@ import logging
|
||||
from typing import Any, Concatenate, cast
|
||||
|
||||
from aiowebostv import WebOsClient, WebOsTvPairError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import util
|
||||
from homeassistant.components.media_player import (
|
||||
@ -22,29 +23,29 @@ from homeassistant.components.media_player import (
|
||||
MediaType,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
ENTITY_MATCH_ALL,
|
||||
ENTITY_MATCH_NONE,
|
||||
)
|
||||
from homeassistant.const import ATTR_COMMAND, ATTR_SUPPORTED_FEATURES
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.helpers.trigger import PluggableAction
|
||||
from homeassistant.helpers.typing import VolDictType
|
||||
|
||||
from . import update_client_key
|
||||
from .const import (
|
||||
ATTR_BUTTON,
|
||||
ATTR_PAYLOAD,
|
||||
ATTR_SOUND_OUTPUT,
|
||||
CONF_SOURCES,
|
||||
DATA_CONFIG_ENTRY,
|
||||
DOMAIN,
|
||||
LIVE_TV_APP_ID,
|
||||
SERVICE_BUTTON,
|
||||
SERVICE_COMMAND,
|
||||
SERVICE_SELECT_SOUND_OUTPUT,
|
||||
WEBOSTV_EXCEPTIONS,
|
||||
)
|
||||
from .triggers.turn_on import async_get_turn_on_trigger
|
||||
@ -71,11 +72,29 @@ MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)
|
||||
PARALLEL_UPDATES = 0
|
||||
SCAN_INTERVAL = timedelta(seconds=10)
|
||||
|
||||
BUTTON_SCHEMA: VolDictType = {vol.Required(ATTR_BUTTON): cv.string}
|
||||
COMMAND_SCHEMA: VolDictType = {
|
||||
vol.Required(ATTR_COMMAND): cv.string,
|
||||
vol.Optional(ATTR_PAYLOAD): dict,
|
||||
}
|
||||
SOUND_OUTPUT_SCHEMA: VolDictType = {vol.Required(ATTR_SOUND_OUTPUT): cv.string}
|
||||
|
||||
SERVICES = (
|
||||
(SERVICE_BUTTON, BUTTON_SCHEMA, "async_button"),
|
||||
(SERVICE_COMMAND, COMMAND_SCHEMA, "async_command"),
|
||||
(SERVICE_SELECT_SOUND_OUTPUT, SOUND_OUTPUT_SCHEMA, "async_select_sound_output"),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
"""Set up the LG webOS Smart TV platform."""
|
||||
platform = entity_platform.async_get_current_platform()
|
||||
|
||||
for service_name, schema, method in SERVICES:
|
||||
platform.async_register_entity_service(service_name, schema, method)
|
||||
|
||||
client = hass.data[DOMAIN][DATA_CONFIG_ENTRY][entry.entry_id]
|
||||
async_add_entities([LgWebOSMediaPlayerEntity(entry, client)])
|
||||
|
||||
@ -143,10 +162,6 @@ class LgWebOSMediaPlayerEntity(RestoreEntity, MediaPlayerEntity):
|
||||
)
|
||||
)
|
||||
|
||||
self.async_on_remove(
|
||||
async_dispatcher_connect(self.hass, DOMAIN, self.async_signal_handler)
|
||||
)
|
||||
|
||||
await self._client.register_state_update_callback(
|
||||
self.async_handle_state_update
|
||||
)
|
||||
@ -166,19 +181,6 @@ class LgWebOSMediaPlayerEntity(RestoreEntity, MediaPlayerEntity):
|
||||
"""Call disconnect on removal."""
|
||||
self._client.unregister_state_update_callback(self.async_handle_state_update)
|
||||
|
||||
async def async_signal_handler(self, data: dict[str, Any]) -> None:
|
||||
"""Handle domain-specific signal by calling appropriate method."""
|
||||
if (entity_ids := data[ATTR_ENTITY_ID]) == ENTITY_MATCH_NONE:
|
||||
return
|
||||
|
||||
if entity_ids == ENTITY_MATCH_ALL or self.entity_id in entity_ids:
|
||||
params = {
|
||||
key: value
|
||||
for key, value in data.items()
|
||||
if key not in ["entity_id", "method"]
|
||||
}
|
||||
await getattr(self, data["method"])(**params)
|
||||
|
||||
async def async_handle_state_update(self, _client: WebOsClient) -> None:
|
||||
"""Update state from WebOsClient."""
|
||||
self._update_states()
|
||||
|
@ -1,8 +1,6 @@
|
||||
rules:
|
||||
# Bronze
|
||||
action-setup:
|
||||
status: todo
|
||||
comment: move actions to entity services
|
||||
action-setup: done
|
||||
appropriate-polling: done
|
||||
brands: done
|
||||
common-modules:
|
||||
|
Loading…
x
Reference in New Issue
Block a user