diff --git a/homeassistant/components/waqi/manifest.json b/homeassistant/components/waqi/manifest.json index e5630d5fd297799862615340f182c0e1324e296b..2022558a5006b28d1c40d16fe792d0a884c891ff 100644 --- a/homeassistant/components/waqi/manifest.json +++ b/homeassistant/components/waqi/manifest.json @@ -5,5 +5,5 @@ "documentation": "https://www.home-assistant.io/integrations/waqi", "iot_class": "cloud_polling", "loggers": ["waqiasync"], - "requirements": ["waqiasync==1.1.0"] + "requirements": ["aiowaqi==0.2.1"] } diff --git a/homeassistant/components/waqi/sensor.py b/homeassistant/components/waqi/sensor.py index 71ec703df3f66344819e69dfb86d56f3dd090caf..51b9acb8e59a8560be618512dbfeeaeeb0421c23 100644 --- a/homeassistant/components/waqi/sensor.py +++ b/homeassistant/components/waqi/sensor.py @@ -1,14 +1,11 @@ """Support for the World Air Quality Index service.""" from __future__ import annotations -import asyncio -from contextlib import suppress from datetime import timedelta import logging -import aiohttp +from aiowaqi import WAQIAirQuality, WAQIClient, WAQIConnectionError, WAQISearchResult import voluptuous as vol -from waqiasync import WaqiClient from homeassistant.components.sensor import ( SensorDeviceClass, @@ -39,17 +36,6 @@ ATTR_PM2_5 = "pm_2_5" ATTR_PRESSURE = "pressure" ATTR_SULFUR_DIOXIDE = "sulfur_dioxide" -KEY_TO_ATTR = { - "pm25": ATTR_PM2_5, - "pm10": ATTR_PM10, - "h": ATTR_HUMIDITY, - "p": ATTR_PRESSURE, - "t": ATTR_TEMPERATURE, - "o3": ATTR_OZONE, - "no2": ATTR_NITROGEN_DIOXIDE, - "so2": ATTR_SULFUR_DIOXIDE, -} - ATTRIBUTION = "Data provided by the World Air Quality Index project" ATTR_ICON = "mdi:cloud" @@ -82,7 +68,8 @@ async def async_setup_platform( station_filter = config.get(CONF_STATIONS) locations = config[CONF_LOCATIONS] - client = WaqiClient(token, async_get_clientsession(hass), timeout=TIMEOUT) + client = WAQIClient(session=async_get_clientsession(hass), request_timeout=TIMEOUT) + client.authenticate(token) dev = [] try: for location_name in locations: @@ -96,10 +83,7 @@ async def async_setup_platform( waqi_sensor.station_name, } & set(station_filter): dev.append(waqi_sensor) - except ( - aiohttp.client_exceptions.ClientConnectorError, - asyncio.TimeoutError, - ) as err: + except WAQIConnectionError as err: _LOGGER.exception("Failed to connect to WAQI servers") raise PlatformNotReady from err async_add_entities(dev, True) @@ -112,25 +96,14 @@ class WaqiSensor(SensorEntity): _attr_device_class = SensorDeviceClass.AQI _attr_state_class = SensorStateClass.MEASUREMENT - def __init__(self, client, station): + _data: WAQIAirQuality | None = None + + def __init__(self, client: WAQIClient, search_result: WAQISearchResult) -> None: """Initialize the sensor.""" self._client = client - try: - self.uid = station["uid"] - except (KeyError, TypeError): - self.uid = None - - try: - self.url = station["station"]["url"] - except (KeyError, TypeError): - self.url = None - - try: - self.station_name = station["station"]["name"] - except (KeyError, TypeError): - self.station_name = None - - self._data = None + self.uid = search_result.station_id + self.url = search_result.station.external_url + self.station_name = search_result.station.name @property def name(self): @@ -140,12 +113,10 @@ class WaqiSensor(SensorEntity): return f"WAQI {self.url if self.url else self.uid}" @property - def native_value(self): + def native_value(self) -> int | None: """Return the state of the device.""" - if (value := self._data.get("aqi")) is not None: - with suppress(ValueError): - return float(value) - return None + assert self._data + return self._data.air_quality_index @property def available(self): @@ -166,28 +137,35 @@ class WaqiSensor(SensorEntity): try: attrs[ATTR_ATTRIBUTION] = " and ".join( [ATTRIBUTION] - + [v["name"] for v in self._data.get("attributions", [])] + + [attribution.name for attribution in self._data.attributions] ) - attrs[ATTR_TIME] = self._data["time"]["s"] - attrs[ATTR_DOMINENTPOL] = self._data.get("dominentpol") - - iaqi = self._data["iaqi"] - for key in iaqi: - if key in KEY_TO_ATTR: - attrs[KEY_TO_ATTR[key]] = iaqi[key]["v"] - else: - attrs[key] = iaqi[key]["v"] - return attrs + attrs[ATTR_TIME] = self._data.measured_at + attrs[ATTR_DOMINENTPOL] = self._data.dominant_pollutant + + iaqi = self._data.extended_air_quality + + attribute = { + ATTR_PM2_5: iaqi.pm25, + ATTR_PM10: iaqi.pm10, + ATTR_HUMIDITY: iaqi.humidity, + ATTR_PRESSURE: iaqi.pressure, + ATTR_TEMPERATURE: iaqi.temperature, + ATTR_OZONE: iaqi.ozone, + ATTR_NITROGEN_DIOXIDE: iaqi.nitrogen_dioxide, + ATTR_SULFUR_DIOXIDE: iaqi.sulfur_dioxide, + } + res_attributes = {k: v for k, v in attribute.items() if v is not None} + return {**attrs, **res_attributes} except (IndexError, KeyError): return {ATTR_ATTRIBUTION: ATTRIBUTION} async def async_update(self) -> None: """Get the latest data and updates the states.""" if self.uid: - result = await self._client.get_station_by_number(self.uid) + result = await self._client.get_by_station_number(self.uid) elif self.url: - result = await self._client.get_station_by_name(self.url) + result = await self._client.get_by_name(self.url) else: result = None self._data = result diff --git a/requirements_all.txt b/requirements_all.txt index bdd5ebce16fc8b2ec20d4c902f1957dd1013b79e..7787e0e334f55efb0028a9d46d686a041cb7233d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -365,6 +365,9 @@ aiounifi==51 # homeassistant.components.vlc_telnet aiovlc==0.1.0 +# homeassistant.components.waqi +aiowaqi==0.2.1 + # homeassistant.components.watttime aiowatttime==0.1.1 @@ -2655,9 +2658,6 @@ wakeonlan==2.1.0 # homeassistant.components.wallbox wallbox==0.4.12 -# homeassistant.components.waqi -waqiasync==1.1.0 - # homeassistant.components.folder_watcher watchdog==2.3.1