From 03bce84c32e4d1962e07c39f0afab2c78971efda Mon Sep 17 00:00:00 2001 From: GP8x <GP8x@users.noreply.github.com> Date: Tue, 25 Sep 2018 10:14:42 +0100 Subject: [PATCH] Add additional Netatmo public data sensors (#16671) Update deps --- homeassistant/components/netatmo.py | 2 +- .../components/sensor/netatmo_public.py | 114 ++++++++++++------ requirements_all.txt | 2 +- 3 files changed, 81 insertions(+), 37 deletions(-) diff --git a/homeassistant/components/netatmo.py b/homeassistant/components/netatmo.py index 59b0a64f6e9..d8924c6c301 100644 --- a/homeassistant/components/netatmo.py +++ b/homeassistant/components/netatmo.py @@ -16,7 +16,7 @@ from homeassistant.helpers import discovery import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle -REQUIREMENTS = ['pyatmo==1.1.1'] +REQUIREMENTS = ['pyatmo==1.2'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/sensor/netatmo_public.py b/homeassistant/components/sensor/netatmo_public.py index d1c6e03d1b0..59b0b317ed1 100644 --- a/homeassistant/components/sensor/netatmo_public.py +++ b/homeassistant/components/sensor/netatmo_public.py @@ -10,7 +10,9 @@ import logging import voluptuous as vol from homeassistant.components.sensor import PLATFORM_SCHEMA -from homeassistant.const import (CONF_NAME, CONF_TYPE) +from homeassistant.const import ( + CONF_NAME, CONF_MODE, CONF_MONITORED_CONDITIONS, TEMP_CELSIUS, + DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_HUMIDITY, STATE_UNKNOWN) from homeassistant.helpers import config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle @@ -26,13 +28,22 @@ CONF_LAT_SW = 'lat_sw' CONF_LON_SW = 'lon_sw' DEFAULT_NAME = 'Netatmo Public Data' -DEFAULT_TYPE = 'max' -SENSOR_TYPES = {'max', 'avg'} +DEFAULT_MODE = 'avg' +MODE_TYPES = {'max', 'avg'} + +SENSOR_TYPES = { + 'temperature': ['Temperature', TEMP_CELSIUS, 'mdi:thermometer', + DEVICE_CLASS_TEMPERATURE], + 'pressure': ['Pressure', 'mbar', 'mdi:gauge', None], + 'humidity': ['Humidity', '%', 'mdi:water-percent', DEVICE_CLASS_HUMIDITY], + 'rain': ['Rain', 'mm', 'mdi:weather-rainy', None], + 'windstrength': ['Wind Strength', 'km/h', 'mdi:weather-windy', None], + 'guststrength': ['Gust Strength', 'km/h', 'mdi:weather-windy', None], +} # NetAtmo Data is uploaded to server every 10 minutes MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=600) - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_AREAS): vol.All(cv.ensure_list, [ { @@ -40,9 +51,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_LAT_SW): cv.latitude, vol.Required(CONF_LON_NE): cv.longitude, vol.Required(CONF_LON_SW): cv.longitude, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_TYPE, default=DEFAULT_TYPE): - vol.In(SENSOR_TYPES) + vol.Required(CONF_MONITORED_CONDITIONS): [vol.In(SENSOR_TYPES)], + vol.Optional(CONF_MODE, default=DEFAULT_MODE): vol.In(MODE_TYPES), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string } ]), }) @@ -59,20 +70,29 @@ def setup_platform(hass, config, add_entities, discovery_info=None): lat_ne=area_conf.get(CONF_LAT_NE), lon_ne=area_conf.get(CONF_LON_NE), lat_sw=area_conf.get(CONF_LAT_SW), - lon_sw=area_conf.get(CONF_LON_SW), - calculation=area_conf.get(CONF_TYPE)) - sensors.append(NetatmoPublicSensor(area_conf.get(CONF_NAME), data)) - add_entities(sensors) + lon_sw=area_conf.get(CONF_LON_SW)) + for sensor_type in area_conf.get(CONF_MONITORED_CONDITIONS): + sensors.append(NetatmoPublicSensor(area_conf.get(CONF_NAME), + data, sensor_type, + area_conf.get(CONF_MODE))) + add_entities(sensors, True) class NetatmoPublicSensor(Entity): """Represent a single sensor in a Netatmo.""" - def __init__(self, name, data): + def __init__(self, area_name, data, sensor_type, mode): """Initialize the sensor.""" self.netatmo_data = data - self._name = name + self.type = sensor_type + self._mode = mode + self._name = '{} {}'.format(area_name, + SENSOR_TYPES[self.type][0]) + self._area_name = area_name self._state = None + self._device_class = SENSOR_TYPES[self.type][3] + self._icon = SENSOR_TYPES[self.type][2] + self._unit_of_measurement = SENSOR_TYPES[self.type][1] @property def name(self): @@ -82,33 +102,63 @@ class NetatmoPublicSensor(Entity): @property def icon(self): """Icon to use in the frontend.""" - return 'mdi:weather-rainy' + return self._icon @property def device_class(self): """Return the device class of the sensor.""" - return None + return self._device_class @property def state(self): - """Return true if binary sensor is on.""" + """Return the state of the device.""" return self._state @property def unit_of_measurement(self): """Return the unit of measurement of this entity.""" - return 'mm' + return self._unit_of_measurement def update(self): """Get the latest data from NetAtmo API and updates the states.""" self.netatmo_data.update() - self._state = self.netatmo_data.data + + if self.netatmo_data.data is None: + _LOGGER.warning("No data found for %s", self._name) + self._state = STATE_UNKNOWN + return + + data = None + + if self.type == 'temperature': + data = self.netatmo_data.data.getLatestTemperatures() + elif self.type == 'pressure': + data = self.netatmo_data.data.getLatestPressures() + elif self.type == 'humidity': + data = self.netatmo_data.data.getLatestHumidities() + elif self.type == 'rain': + data = self.netatmo_data.data.getLatestRain() + elif self.type == 'windstrength': + data = self.netatmo_data.data.getLatestWindStrengths() + elif self.type == 'guststrength': + data = self.netatmo_data.data.getLatestGustStrengths() + + if not data: + _LOGGER.warning("No station provides %s data in the area %s", + self.type, self._area_name) + self._state = STATE_UNKNOWN + return + + if self._mode == 'avg': + self._state = round(sum(data.values()) / len(data), 1) + elif self._mode == 'max': + self._state = max(data.values()) class NetatmoPublicData: """Get the latest data from NetAtmo.""" - def __init__(self, auth, lat_ne, lon_ne, lat_sw, lon_sw, calculation): + def __init__(self, auth, lat_ne, lon_ne, lat_sw, lon_sw): """Initialize the data object.""" self.auth = auth self.data = None @@ -116,26 +166,20 @@ class NetatmoPublicData: self.lon_ne = lon_ne self.lat_sw = lat_sw self.lon_sw = lon_sw - self.calculation = calculation @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Request an update from the Netatmo API.""" import pyatmo - raindata = pyatmo.PublicData(self.auth, - LAT_NE=self.lat_ne, - LON_NE=self.lon_ne, - LAT_SW=self.lat_sw, - LON_SW=self.lon_sw, - required_data_type="rain") - - if raindata.CountStationInArea() == 0: - _LOGGER.warning('No Rain Station available in this area.') + data = pyatmo.PublicData(self.auth, + LAT_NE=self.lat_ne, + LON_NE=self.lon_ne, + LAT_SW=self.lat_sw, + LON_SW=self.lon_sw, + filtering=True) + + if data.CountStationInArea() == 0: + _LOGGER.warning('No Stations available in this area.') return - raindata_live = raindata.getLive() - - if self.calculation == 'avg': - self.data = sum(raindata_live.values()) / len(raindata_live) - else: - self.data = max(raindata_live.values()) + self.data = data diff --git a/requirements_all.txt b/requirements_all.txt index e009f2e21a0..cfb17e64a7a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -794,7 +794,7 @@ pyasn1-modules==0.1.5 pyasn1==0.3.7 # homeassistant.components.netatmo -pyatmo==1.1.1 +pyatmo==1.2 # homeassistant.components.apple_tv pyatv==0.3.10 -- GitLab