1 """Support for LG webOS Smart TV."""
3 from __future__
import annotations
5 from contextlib
import suppress
7 from typing
import NamedTuple
9 from aiowebostv
import WebOsClient, WebOsTvPairError
10 import voluptuous
as vol
20 EVENT_HOMEASSISTANT_STOP,
39 SERVICE_SELECT_SOUND_OUTPUT,
43 CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
45 CALL_SCHEMA = vol.Schema({vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids})
49 """Details for SERVICE_TO_METHOD mapping."""
55 BUTTON_SCHEMA = CALL_SCHEMA.extend({vol.Required(ATTR_BUTTON): cv.string})
57 COMMAND_SCHEMA = CALL_SCHEMA.extend(
58 {vol.Required(ATTR_COMMAND): cv.string, vol.Optional(ATTR_PAYLOAD): dict}
61 SOUND_OUTPUT_SCHEMA = CALL_SCHEMA.extend({vol.Required(ATTR_SOUND_OUTPUT): cv.string})
66 method=
"async_command", schema=COMMAND_SCHEMA
69 method=
"async_select_sound_output",
70 schema=SOUND_OUTPUT_SCHEMA,
74 _LOGGER = logging.getLogger(__name__)
77 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
78 """Set up the LG WebOS TV platform."""
79 hass.data.setdefault(DOMAIN, {})
80 hass.data[DOMAIN].setdefault(DATA_CONFIG_ENTRY, {})
81 hass.data[DOMAIN][DATA_HASS_CONFIG] = config
87 """Set the config entry up."""
88 host = entry.data[CONF_HOST]
89 key = entry.data[CONF_CLIENT_SECRET]
92 client = WebOsClient(host, key)
93 with suppress(*WEBOSTV_EXCEPTIONS):
95 await client.connect()
96 except WebOsTvPairError
as err:
103 async
def async_service_handler(service: ServiceCall) ->
None:
104 method = SERVICE_TO_METHOD[service.service]
105 data = service.data.copy()
106 data[
"method"] = method.method
109 for service, method
in SERVICE_TO_METHOD.items():
110 hass.services.async_register(
111 DOMAIN, service, async_service_handler, schema=method.schema
114 hass.data[DOMAIN][DATA_CONFIG_ENTRY][entry.entry_id] = client
115 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
119 hass.async_create_task(
120 discovery.async_load_platform(
125 CONF_NAME: entry.title,
126 ATTR_CONFIG_ENTRY_ID: entry.entry_id,
128 hass.data[DOMAIN][DATA_HASS_CONFIG],
132 if not entry.update_listeners:
133 entry.async_on_unload(entry.add_update_listener(async_update_options))
135 async
def async_on_stop(_event: Event) ->
None:
136 """Unregister callbacks and disconnect."""
137 client.clear_state_update_callbacks()
138 await client.disconnect()
140 entry.async_on_unload(
141 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_on_stop)
147 """Update options."""
148 await hass.config_entries.async_reload(entry.entry_id)
153 client = WebOsClient(host, key)
155 await client.connect()
156 except WebOsTvPairError:
157 _LOGGER.warning(
"Connected to LG webOS TV %s but not paired", host)
164 hass: HomeAssistant, entry: ConfigEntry, client: WebOsClient
166 """Check and update stored client key if key has changed."""
167 host = entry.data[CONF_HOST]
168 key = entry.data[CONF_CLIENT_SECRET]
170 if client.client_key != key:
171 _LOGGER.debug(
"Updating client key for host %s", host)
172 data = {CONF_HOST: host, CONF_CLIENT_SECRET: client.client_key}
173 hass.config_entries.async_update_entry(entry, data=data)
177 """Unload a config entry."""
178 unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
181 client = hass.data[DOMAIN][DATA_CONFIG_ENTRY].pop(entry.entry_id)
182 await hass_notify.async_reload(hass, DOMAIN)
183 client.clear_state_update_callbacks()
184 await client.disconnect()
187 if unload_ok
and not hass.data[DOMAIN][DATA_CONFIG_ENTRY]:
188 for service
in SERVICE_TO_METHOD:
189 hass.services.async_remove(DOMAIN, service)
WebOsClient async_control_connect(str host, str|None key)
bool async_setup(HomeAssistant hass, ConfigType config)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
None async_update_options(HomeAssistant hass, ConfigEntry entry)
None update_client_key(HomeAssistant hass, ConfigEntry entry, WebOsClient client)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)