Buienradar improvements: continuous sensors and unique ID's (#13249)

* Force update continuous sensors when new measurement available.

* Added unique ID's based on coordinates, sensor type and client name.

* Fixed over-indentation (hound review)

* Revert "Added unique ID's based on coordinates, sensor type and client name."

This reverts commit 3345e67a15.

* Fix lint errors.

* Re-added unique ID's based on location.

* Removed wrong error logging.

* Removed creating UUID from unique id

* Lint
This commit is contained in:
corneyl 2018-05-01 21:06:41 +02:00 committed by Paulus Schoutsen
parent 83d300fd11
commit 2f0fc0934f

View file

@ -161,7 +161,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
dev = [] dev = []
for sensor_type in config[CONF_MONITORED_CONDITIONS]: for sensor_type in config[CONF_MONITORED_CONDITIONS]:
dev.append(BrSensor(sensor_type, config.get(CONF_NAME, 'br'))) dev.append(BrSensor(sensor_type, config.get(CONF_NAME, 'br'),
coordinates))
async_add_devices(dev) async_add_devices(dev)
data = BrData(hass, coordinates, timeframe, dev) data = BrData(hass, coordinates, timeframe, dev)
@ -172,9 +173,9 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class BrSensor(Entity): class BrSensor(Entity):
"""Representation of an Buienradar sensor.""" """Representation of an Buienradar sensor."""
def __init__(self, sensor_type, client_name): def __init__(self, sensor_type, client_name, coordinates):
"""Initialize the sensor.""" """Initialize the sensor."""
from buienradar.buienradar import (PRECIPITATION_FORECAST) from buienradar.buienradar import (PRECIPITATION_FORECAST, CONDITION)
self.client_name = client_name self.client_name = client_name
self._name = SENSOR_TYPES[sensor_type][0] self._name = SENSOR_TYPES[sensor_type][0]
@ -185,10 +186,22 @@ class BrSensor(Entity):
self._attribution = None self._attribution = None
self._measured = None self._measured = None
self._stationname = None self._stationname = None
self._unique_id = self.uid(coordinates)
# All continuous sensors should be forced to be updated
self._force_update = self.type != SYMBOL and \
not self.type.startswith(CONDITION)
if self.type.startswith(PRECIPITATION_FORECAST): if self.type.startswith(PRECIPITATION_FORECAST):
self._timeframe = None self._timeframe = None
def uid(self, coordinates):
"""Generate a unique id using coordinates and sensor type."""
# The combination of the location, name an sensor type is unique
return "%2.6f%2.6f%s" % (coordinates[CONF_LATITUDE],
coordinates[CONF_LONGITUDE],
self.type)
def load_data(self, data): def load_data(self, data):
"""Load the sensor with relevant data.""" """Load the sensor with relevant data."""
# Find sensor # Find sensor
@ -198,6 +211,11 @@ class BrSensor(Entity):
PRECIPITATION_FORECAST, STATIONNAME, PRECIPITATION_FORECAST, STATIONNAME,
TIMEFRAME) TIMEFRAME)
# Check if we have a new measurement,
# otherwise we do not have to update the sensor
if self._measured == data.get(MEASURED):
return False
self._attribution = data.get(ATTRIBUTION) self._attribution = data.get(ATTRIBUTION)
self._stationname = data.get(STATIONNAME) self._stationname = data.get(STATIONNAME)
self._measured = data.get(MEASURED) self._measured = data.get(MEASURED)
@ -246,18 +264,12 @@ class BrSensor(Entity):
return False return False
else: else:
try: try:
new_state = data.get(FORECAST)[fcday].get(self.type[:-3]) self._state = data.get(FORECAST)[fcday].get(self.type[:-3])
return True
except IndexError: except IndexError:
_LOGGER.warning("No forecast for fcday=%s...", fcday) _LOGGER.warning("No forecast for fcday=%s...", fcday)
return False return False
if new_state != self._state:
self._state = new_state
return True
return False
return False
if self.type == SYMBOL or self.type.startswith(CONDITION): if self.type == SYMBOL or self.type.startswith(CONDITION):
# update weather symbol & status text # update weather symbol & status text
condition = data.get(CONDITION, None) condition = data.get(CONDITION, None)
@ -286,27 +298,26 @@ class BrSensor(Entity):
if self.type.startswith(PRECIPITATION_FORECAST): if self.type.startswith(PRECIPITATION_FORECAST):
# update nested precipitation forecast sensors # update nested precipitation forecast sensors
nested = data.get(PRECIPITATION_FORECAST) nested = data.get(PRECIPITATION_FORECAST)
new_state = nested.get(self.type[len(PRECIPITATION_FORECAST)+1:])
self._timeframe = nested.get(TIMEFRAME) self._timeframe = nested.get(TIMEFRAME)
# pylint: disable=protected-access # pylint: disable=protected-access
if new_state != self._state: self._state = nested.get(self.type[len(PRECIPITATION_FORECAST)+1:])
self._state = new_state return True
return True
return False
# update all other sensors # update all other sensors
new_state = data.get(self.type)
# pylint: disable=protected-access # pylint: disable=protected-access
if new_state != self._state: self._state = data.get(self.type)
self._state = new_state return True
return True
return False
@property @property
def attribution(self): def attribution(self):
"""Return the attribution.""" """Return the attribution."""
return self._attribution return self._attribution
@property
def unique_id(self):
"""Return the unique id."""
return self._unique_id
@property @property
def name(self): def name(self):
"""Return the name of the sensor.""" """Return the name of the sensor."""
@ -360,6 +371,11 @@ class BrSensor(Entity):
"""Return possible sensor specific icon.""" """Return possible sensor specific icon."""
return SENSOR_TYPES[self.type][2] return SENSOR_TYPES[self.type][2]
@property
def force_update(self):
"""Return true for continuous sensors, false for discrete sensors."""
return self._force_update
class BrData(object): class BrData(object):
"""Get the latest data and updates the states.""" """Get the latest data and updates the states."""