1 """Support for IKEA Tradfri."""
3 from __future__
import annotations
5 from datetime
import datetime, timedelta
8 from pytradfri
import Gateway, RequestError
9 from pytradfri.api.aiocoap_api
import APIFactory
10 from pytradfri.command
import Command
11 from pytradfri.device
import Device
19 async_dispatcher_connect,
20 async_dispatcher_send,
35 from .coordinator
import TradfriDeviceDataUpdateCoordinator
44 SIGNAL_GW =
"tradfri.gw_status"
52 """Create a gateway."""
53 tradfri_data: dict[str, Any] = {}
54 hass.data.setdefault(DOMAIN, {})[entry.entry_id] = tradfri_data
56 factory = await APIFactory.init(
57 entry.data[CONF_HOST],
58 psk_id=entry.data[CONF_IDENTITY],
59 psk=entry.data[CONF_KEY],
61 tradfri_data[FACTORY] = factory
63 async
def on_hass_stop(event: Event) ->
None:
64 """Close connection when hass stops."""
65 await factory.shutdown()
68 entry.async_on_unload(
69 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop)
76 gateway_info = await
api(gateway.get_gateway_info(), timeout=TIMEOUT_API)
77 devices_commands: Command = await
api(
78 gateway.get_devices(), timeout=TIMEOUT_API
80 devices: list[Device] = await
api(devices_commands, timeout=TIMEOUT_API)
82 except RequestError
as exc:
83 await factory.shutdown()
84 raise ConfigEntryNotReady
from exc
86 dev_reg = dr.async_get(hass)
87 dev_reg.async_get_or_create(
88 config_entry_id=entry.entry_id,
90 identifiers={(DOMAIN, entry.data[CONF_GATEWAY_ID])},
91 manufacturer=
"IKEA of Sweden",
95 sw_version=gateway_info.firmware_version,
102 CONF_GATEWAY_ID: gateway,
104 COORDINATOR_LIST: [],
107 for device
in devices:
109 hass=hass, api=api, device=device
111 await coordinator.async_config_entry_first_refresh()
113 entry.async_on_unload(
116 coordinator_data[COORDINATOR_LIST].append(coordinator)
118 tradfri_data[COORDINATOR] = coordinator_data
120 async
def async_keep_alive(now: datetime) ->
None:
126 await
api(gateway.get_gateway_info())
128 LOGGER.error(
"Keep-alive failed")
133 entry.async_on_unload(
137 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
143 """Unload a config entry."""
144 unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
146 tradfri_data = hass.data[DOMAIN].pop(entry.entry_id)
147 factory = tradfri_data[FACTORY]
148 await factory.shutdown()
155 hass: HomeAssistant, config_entry: ConfigEntry, devices: list[Device]
157 """Remove stale devices from device registry."""
158 device_registry = dr.async_get(hass)
159 device_entries = dr.async_entries_for_config_entry(
160 device_registry, config_entry.entry_id
162 all_device_ids = {device.id
for device
in devices}
164 for device_entry
in device_entries:
165 device_id: str |
None =
None
166 gateway_id: str |
None =
None
168 for identifier
in device_entry.identifiers:
169 if identifier[0] != DOMAIN:
175 if _id == config_entry.data[CONF_GATEWAY_ID]:
182 if gateway_id
is not None:
186 if device_id
is None or device_id
not in all_device_ids:
190 device_registry.async_update_device(
191 device_entry.id, remove_config_entry_id=config_entry.entry_id
None remove_stale_devices(HomeAssistant hass, ConfigEntry config_entry, list[Device] devices)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
CALLBACK_TYPE async_track_time_interval(HomeAssistant hass, Callable[[datetime], Coroutine[Any, Any, None]|None] action, timedelta interval, *str|None name=None, bool|None cancel_on_shutdown=None)