Update waqi sensor (#8385)

This commit is contained in:
Andrey 2017-07-07 17:55:58 +03:00 committed by Paulus Schoutsen
parent f2267437df
commit cf924cd14d
2 changed files with 88 additions and 80 deletions

View File

@ -4,18 +4,22 @@ Support for the World Air Quality Index service.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.waqi/ https://home-assistant.io/components/sensor.waqi/
""" """
import asyncio
import logging import logging
from datetime import timedelta from datetime import timedelta
import aiohttp
import voluptuous as vol import voluptuous as vol
from homeassistant.exceptions import PlatformNotReady
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.const import ( from homeassistant.const import (
ATTR_ATTRIBUTION, ATTR_TIME, ATTR_TEMPERATURE, CONF_TOKEN) ATTR_ATTRIBUTION, ATTR_TIME, ATTR_TEMPERATURE, CONF_TOKEN)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['pwaqi==3.0'] REQUIREMENTS = ['waqiasync==1.0.0']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -27,6 +31,18 @@ ATTR_PM10 = 'pm_10'
ATTR_PM2_5 = 'pm_2_5' ATTR_PM2_5 = 'pm_2_5'
ATTR_PRESSURE = 'pressure' ATTR_PRESSURE = 'pressure'
ATTR_SULFUR_DIOXIDE = 'sulfur_dioxide' 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' ATTRIBUTION = 'Data provided by the World Air Quality Index project'
CONF_LOCATIONS = 'locations' CONF_LOCATIONS = 'locations'
@ -34,9 +50,7 @@ CONF_STATIONS = 'stations'
SCAN_INTERVAL = timedelta(minutes=5) SCAN_INTERVAL = timedelta(minutes=5)
SENSOR_TYPES = { TIMEOUT = 10
'aqi': ['AQI', '0-300+', 'mdi:cloud']
}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_STATIONS): cv.ensure_list, vol.Optional(CONF_STATIONS): cv.ensure_list,
@ -45,51 +59,65 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
}) })
def setup_platform(hass, config, add_devices, discovery_info=None): @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the requested World Air Quality Index locations.""" """Set up the requested World Air Quality Index locations."""
import pwaqi import waqiasync
token = config.get(CONF_TOKEN) token = config.get(CONF_TOKEN)
station_filter = config.get(CONF_STATIONS) station_filter = config.get(CONF_STATIONS)
locations = config.get(CONF_LOCATIONS) locations = config.get(CONF_LOCATIONS)
client = waqiasync.WaqiClient(
token, async_get_clientsession(hass), timeout=TIMEOUT)
dev = [] dev = []
for location_name in locations: try:
station_ids = pwaqi.findStationCodesByCity(location_name, token) for location_name in locations:
_LOGGER.info("The following stations were returned: %s", station_ids) stations = yield from client.search(location_name)
for station in station_ids: _LOGGER.debug("The following stations were returned: %s", stations)
waqi_sensor = WaqiSensor(WaqiData(station, token), station) for station in stations:
if (not station_filter) or \ waqi_sensor = WaqiSensor(client, station)
(waqi_sensor.station_name in station_filter): if not station_filter or \
dev.append(WaqiSensor(WaqiData(station, token), station)) {waqi_sensor.uid,
waqi_sensor.url,
add_devices(dev, True) waqi_sensor.station_name} & set(station_filter):
dev.append(waqi_sensor)
except (aiohttp.client_exceptions.ClientConnectorError,
asyncio.TimeoutError):
_LOGGER.exception('Failed to connct to WAQI servers.')
raise PlatformNotReady
async_add_devices(dev, True)
class WaqiSensor(Entity): class WaqiSensor(Entity):
"""Implementation of a WAQI sensor.""" """Implementation of a WAQI sensor."""
def __init__(self, data, station_id): def __init__(self, client, station):
"""Initialize the sensor.""" """Initialize the sensor."""
self.data = data self._client = client
self._station_id = station_id try:
self._details = None 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
@property @property
def name(self): def name(self):
"""Return the name of the sensor.""" """Return the name of the sensor."""
try: if self.station_name:
return 'WAQI {}'.format(self._details['city']['name']) return 'WAQI {}'.format(self.station_name)
except (KeyError, TypeError): return 'WAQI {}'.format(self.url if self.url else self.uid)
return 'WAQI {}'.format(self._station_id)
@property
def station_name(self):
"""Return the name of the station."""
try:
return self._details['city']['name']
except (KeyError, TypeError):
return None
@property @property
def icon(self): def icon(self):
@ -99,8 +127,8 @@ class WaqiSensor(Entity):
@property @property
def state(self): def state(self):
"""Return the state of the device.""" """Return the state of the device."""
if self._details is not None: if self._data is not None:
return self._details.get('aqi') return self._data.get('aqi')
return None return None
@property @property
@ -113,52 +141,32 @@ class WaqiSensor(Entity):
"""Return the state attributes of the last update.""" """Return the state attributes of the last update."""
attrs = {} attrs = {}
if self.data is not None: if self._data is not None:
try: try:
attrs[ATTR_ATTRIBUTION] = ATTRIBUTION attrs[ATTR_ATTRIBUTION] = ' and '.join(
attrs[ATTR_TIME] = self._details.get('time') [ATTRIBUTION] + [
attrs[ATTR_DOMINENTPOL] = self._details.get('dominentpol') v['name'] for v in self._data.get('attributions', [])])
for values in self._details['iaqi']:
if values['p'] == 'pm25': attrs[ATTR_TIME] = self._data['time']['s']
attrs[ATTR_PM2_5] = values['cur'] attrs[ATTR_DOMINENTPOL] = self._data.get('dominentpol')
elif values['p'] == 'pm10':
attrs[ATTR_PM10] = values['cur'] iaqi = self._data['iaqi']
elif values['p'] == 'h': for key in iaqi:
attrs[ATTR_HUMIDITY] = values['cur'] if key in KEY_TO_ATTR:
elif values['p'] == 'p': attrs[KEY_TO_ATTR[key]] = iaqi[key]['v']
attrs[ATTR_PRESSURE] = values['cur'] else:
elif values['p'] == 't': attrs[key] = iaqi[key]['v']
attrs[ATTR_TEMPERATURE] = values['cur']
elif values['p'] == 'o3':
attrs[ATTR_OZONE] = values['cur']
elif values['p'] == 'no2':
attrs[ATTR_NITROGEN_DIOXIDE] = values['cur']
elif values['p'] == 'so2':
attrs[ATTR_SULFUR_DIOXIDE] = values['cur']
return attrs return attrs
except (IndexError, KeyError): except (IndexError, KeyError):
return {ATTR_ATTRIBUTION: ATTRIBUTION} return {ATTR_ATTRIBUTION: ATTRIBUTION}
def update(self): @asyncio.coroutine
def async_update(self):
"""Get the latest data and updates the states.""" """Get the latest data and updates the states."""
self.data.update() if self.uid:
self._details = self.data.data result = yield from self._client.get_station_by_number(self.uid)
elif self.url:
result = yield from self._client.get_station_by_name(self.url)
class WaqiData(object): else:
"""Get the latest data and update the states.""" result = None
self._data = result
def __init__(self, station_id, token):
"""Initialize the data object."""
self._station_id = station_id
self._token = token
self.data = None
def update(self):
"""Get the data from World Air Quality Index and updates the states."""
import pwaqi
try:
self.data = pwaqi.get_station_observation(
self._station_id, self._token)
except AttributeError:
_LOGGER.exception("Unable to fetch data from WAQI")

View File

@ -489,9 +489,6 @@ pushbullet.py==0.10.0
# homeassistant.components.notify.pushetta # homeassistant.components.notify.pushetta
pushetta==1.0.15 pushetta==1.0.15
# homeassistant.components.sensor.waqi
pwaqi==3.0
# homeassistant.components.light.rpi_gpio_pwm # homeassistant.components.light.rpi_gpio_pwm
pwmled==1.1.1 pwmled==1.1.1
@ -924,6 +921,9 @@ vtjp==0.1.14
# homeassistant.components.switch.wake_on_lan # homeassistant.components.switch.wake_on_lan
wakeonlan==0.2.2 wakeonlan==0.2.2
# homeassistant.components.sensor.waqi
waqiasync==1.0.0
# homeassistant.components.media_player.gpmdp # homeassistant.components.media_player.gpmdp
websocket-client==0.37.0 websocket-client==0.37.0