1 """Support for Ambient Weather Station Service."""
3 from __future__
import annotations
7 from aioambient
import Websocket
8 from aioambient.errors
import WebsocketError
15 EVENT_HOMEASSISTANT_STOP,
29 TYPE_SOLARRADIATION_LX,
32 PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
34 DATA_CONFIG =
"config"
36 DEFAULT_SOCKET_MIN_RETRY = 15
39 type AmbientStationConfigEntry = ConfigEntry[AmbientStation]
44 """Calculate illuminance (in lux)."""
45 return round(value / 0.0079)
50 """Hydrate station data with addition or normalized data."""
51 if (irradiation := data.get(TYPE_SOLARRADIATION))
is not None:
58 hass: HomeAssistant, entry: AmbientStationConfigEntry
60 """Set up the Ambient PWS as config entry."""
61 if not entry.unique_id:
62 hass.config_entries.async_update_entry(
63 entry, unique_id=entry.data[CONF_APP_KEY]
69 Websocket(entry.data[CONF_APP_KEY], entry.data[CONF_API_KEY]),
73 await ambient.ws_connect()
74 except WebsocketError
as err:
75 LOGGER.error(
"Config entry failed: %s", err)
76 raise ConfigEntryNotReady
from err
78 entry.runtime_data = ambient
80 async
def _async_disconnect_websocket(_: Event) ->
None:
81 await ambient.websocket.disconnect()
83 entry.async_on_unload(
84 hass.bus.async_listen_once(
85 EVENT_HOMEASSISTANT_STOP, _async_disconnect_websocket
93 hass: HomeAssistant, entry: AmbientStationConfigEntry
95 """Unload an Ambient PWS config entry."""
96 unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
98 hass.async_create_task(entry.runtime_data.ws_disconnect(), eager_start=
True)
104 """Migrate old entry."""
105 version = entry.version
107 LOGGER.debug(
"Migrating from version %s", version)
111 dev_reg = dr.async_get(hass)
112 dev_reg.async_clear_config_entry(entry.entry_id)
114 en_reg = er.async_get(hass)
115 en_reg.async_clear_config_entry(entry.entry_id)
118 hass.config_entries.async_update_entry(entry, version=version)
120 LOGGER.info(
"Migration to version %s successful", version)
126 """Define a class to handle the Ambient websocket."""
129 self, hass: HomeAssistant, entry: ConfigEntry, websocket: Websocket
136 self.stations: dict[str, dict] = {}
140 """Register handlers and connect to the websocket."""
142 def on_connect() -> None:
143 """Define a handler to fire when the websocket is connected."""
144 LOGGER.info(
"Connected to websocket")
146 def on_data(data: dict) ->
None:
147 """Define a handler to fire when the data is received."""
148 mac = data[
"macAddress"]
151 if data == self.stations[mac][ATTR_LAST_DATA]:
154 LOGGER.debug(
"New data received: %s", data)
158 def on_disconnect() -> None:
159 """Define a handler to fire when the websocket is disconnected."""
160 LOGGER.info(
"Disconnected from websocket")
162 def on_subscribed(data: dict) ->
None:
163 """Define a handler to fire when the subscription is set."""
164 for station
in data[
"devices"]:
165 if (mac := station[
"macAddress"])
in self.stations:
168 LOGGER.debug(
"New station subscription: %s", data)
170 self.stations[mac] = {
172 ATTR_LOCATION: station.get(
"info", {}).
get(
"location"),
173 ATTR_NAME: station.get(
"info", {}).
get(
"name", mac),
181 self.
_hass_hass.async_create_task(
182 self.
_hass_hass.config_entries.async_forward_entry_setups(
183 self.
_entry_entry, PLATFORMS
190 self.
websocketwebsocket.on_connect(on_connect)
192 self.
websocketwebsocket.on_disconnect(on_disconnect)
193 self.
websocketwebsocket.on_subscribed(on_subscribed)
198 """Disconnect from the websocket."""
199 await self.
websocketwebsocket.disconnect()
None __init__(self, HomeAssistant hass, ConfigEntry entry, Websocket websocket)
bool async_setup_entry(HomeAssistant hass, AmbientStationConfigEntry entry)
int async_wm2_to_lx(float value)
dict[str, Any] async_hydrate_station_data(dict[str, Any] data)
bool async_unload_entry(HomeAssistant hass, AmbientStationConfigEntry entry)
bool async_migrate_entry(HomeAssistant hass, ConfigEntry entry)
web.Response get(self, web.Request request, str config_key)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)