mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
buienradar==0.7, fix winddirection/azimuth, logging (#8281)
* buienradar==0.7, fix winddirection/azimuth, logging * prevent multiple update cycles * prevent multiple update cycles * prevent multiple sensor updates for precipitation forecast * prevent multiple sensor updates for precipitation forecast * Update comments * Adapted logging * Adapted logging
This commit is contained in:
parent
db8bb53984
commit
5e71e9b826
@ -23,11 +23,18 @@ from homeassistant.helpers.event import (
|
|||||||
async_track_point_in_utc_time)
|
async_track_point_in_utc_time)
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
REQUIREMENTS = ['buienradar==0.6']
|
REQUIREMENTS = ['buienradar==0.7']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
TIMEFRAME_LABEL = 'Timeframe'
|
||||||
|
# Schedule next call after (minutes):
|
||||||
|
SCHEDULE_OK = 10
|
||||||
|
# When an error occurred, new call after (minutes):
|
||||||
|
SCHEDULE_NOK = 2
|
||||||
|
|
||||||
# Supported sensor types:
|
# Supported sensor types:
|
||||||
|
# Key: ['label', unit, icon]
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
'stationname': ['Stationname', None, None],
|
'stationname': ['Stationname', None, None],
|
||||||
'symbol': ['Symbol', None, None],
|
'symbol': ['Symbol', None, None],
|
||||||
@ -47,7 +54,7 @@ SENSOR_TYPES = {
|
|||||||
'precipitation_forecast_average': ['Precipitation forecast average',
|
'precipitation_forecast_average': ['Precipitation forecast average',
|
||||||
'mm/h', 'mdi:weather-pouring'],
|
'mm/h', 'mdi:weather-pouring'],
|
||||||
'precipitation_forecast_total': ['Precipitation forecast total',
|
'precipitation_forecast_total': ['Precipitation forecast total',
|
||||||
'mm/h', 'mdi:weather-pouring']
|
'mm', 'mdi:weather-pouring']
|
||||||
}
|
}
|
||||||
|
|
||||||
CONF_TIMEFRAME = 'timeframe'
|
CONF_TIMEFRAME = 'timeframe'
|
||||||
@ -61,13 +68,14 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
'Latitude and longitude must exist together'): cv.latitude,
|
'Latitude and longitude must exist together'): cv.latitude,
|
||||||
vol.Inclusive(CONF_LONGITUDE, 'coordinates',
|
vol.Inclusive(CONF_LONGITUDE, 'coordinates',
|
||||||
'Latitude and longitude must exist together'): cv.longitude,
|
'Latitude and longitude must exist together'): cv.longitude,
|
||||||
vol.Optional(CONF_TIMEFRAME): cv.positive_int
|
vol.Optional(CONF_TIMEFRAME, default=60):
|
||||||
|
vol.All(vol.Coerce(int), vol.Range(min=5, max=120)),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup the buienradar sensor."""
|
"""Create the buienradar sensor."""
|
||||||
from homeassistant.components.weather.buienradar import DEFAULT_TIMEFRAME
|
from homeassistant.components.weather.buienradar import DEFAULT_TIMEFRAME
|
||||||
|
|
||||||
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
|
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||||
@ -81,6 +89,9 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
coordinates = {CONF_LATITUDE: float(latitude),
|
coordinates = {CONF_LATITUDE: float(latitude),
|
||||||
CONF_LONGITUDE: float(longitude)}
|
CONF_LONGITUDE: float(longitude)}
|
||||||
|
|
||||||
|
_LOGGER.debug("Initializing buienradar sensor coordinate %s, timeframe %s",
|
||||||
|
coordinates, timeframe)
|
||||||
|
|
||||||
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')))
|
||||||
@ -88,7 +99,6 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
|
|
||||||
data = BrData(hass, coordinates, timeframe, dev)
|
data = BrData(hass, coordinates, timeframe, dev)
|
||||||
# schedule the first update in 1 minute from now:
|
# schedule the first update in 1 minute from now:
|
||||||
_LOGGER.debug("Start running....")
|
|
||||||
yield from data.schedule_update(1)
|
yield from data.schedule_update(1)
|
||||||
|
|
||||||
|
|
||||||
@ -97,6 +107,8 @@ class BrSensor(Entity):
|
|||||||
|
|
||||||
def __init__(self, sensor_type, client_name):
|
def __init__(self, sensor_type, client_name):
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
|
from buienradar.buienradar import (PRECIPITATION_FORECAST)
|
||||||
|
|
||||||
self.client_name = client_name
|
self.client_name = client_name
|
||||||
self._name = SENSOR_TYPES[sensor_type][0]
|
self._name = SENSOR_TYPES[sensor_type][0]
|
||||||
self.type = sensor_type
|
self.type = sensor_type
|
||||||
@ -104,16 +116,22 @@ class BrSensor(Entity):
|
|||||||
self._unit_of_measurement = SENSOR_TYPES[self.type][1]
|
self._unit_of_measurement = SENSOR_TYPES[self.type][1]
|
||||||
self._entity_picture = None
|
self._entity_picture = None
|
||||||
self._attribution = None
|
self._attribution = None
|
||||||
|
self._measured = None
|
||||||
self._stationname = None
|
self._stationname = None
|
||||||
|
|
||||||
|
if self.type.startswith(PRECIPITATION_FORECAST):
|
||||||
|
self._timeframe = None
|
||||||
|
|
||||||
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
|
||||||
from buienradar.buienradar import (ATTRIBUTION, IMAGE, STATIONNAME,
|
from buienradar.buienradar import (ATTRIBUTION, IMAGE, MEASURED,
|
||||||
SYMBOL, PRECIPITATION_FORECAST)
|
PRECIPITATION_FORECAST, STATIONNAME,
|
||||||
|
SYMBOL, TIMEFRAME)
|
||||||
|
|
||||||
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)
|
||||||
if self.type == SYMBOL:
|
if self.type == SYMBOL:
|
||||||
# update weather symbol & status text
|
# update weather symbol & status text
|
||||||
new_state = data.get(self.type)
|
new_state = data.get(self.type)
|
||||||
@ -124,21 +142,26 @@ class BrSensor(Entity):
|
|||||||
self._state = new_state
|
self._state = new_state
|
||||||
self._entity_picture = img
|
self._entity_picture = img
|
||||||
return True
|
return True
|
||||||
elif self.type.startswith(PRECIPITATION_FORECAST):
|
return False
|
||||||
|
|
||||||
|
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:])
|
new_state = nested.get(self.type[len(PRECIPITATION_FORECAST)+1:])
|
||||||
|
self._timeframe = nested.get(TIMEFRAME)
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
if new_state != self._state:
|
if new_state != self._state:
|
||||||
self._state = new_state
|
self._state = new_state
|
||||||
return True
|
return True
|
||||||
else:
|
return False
|
||||||
|
|
||||||
# update all other sensors
|
# update all other sensors
|
||||||
new_state = data.get(self.type)
|
new_state = data.get(self.type)
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
if new_state != self._state:
|
if new_state != self._state:
|
||||||
self._state = new_state
|
self._state = new_state
|
||||||
return True
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def attribution(self):
|
def attribution(self):
|
||||||
@ -173,6 +196,15 @@ class BrSensor(Entity):
|
|||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes."""
|
"""Return the state attributes."""
|
||||||
|
from buienradar.buienradar import (PRECIPITATION_FORECAST)
|
||||||
|
|
||||||
|
if self.type.startswith(PRECIPITATION_FORECAST):
|
||||||
|
result = {ATTR_ATTRIBUTION: self._attribution}
|
||||||
|
if self._timeframe is not None:
|
||||||
|
result[TIMEFRAME_LABEL] = "%d min" % (self._timeframe)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ATTR_ATTRIBUTION: self._attribution,
|
ATTR_ATTRIBUTION: self._attribution,
|
||||||
SENSOR_TYPES['stationname'][0]: self._stationname,
|
SENSOR_TYPES['stationname'][0]: self._stationname,
|
||||||
@ -223,7 +255,7 @@ class BrData(object):
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def get_data(self, url):
|
def get_data(self, url):
|
||||||
"""Load xmpl data from specified url."""
|
"""Load data from specified url."""
|
||||||
from buienradar.buienradar import (CONTENT,
|
from buienradar.buienradar import (CONTENT,
|
||||||
MESSAGE, STATUS_CODE, SUCCESS)
|
MESSAGE, STATUS_CODE, SUCCESS)
|
||||||
|
|
||||||
@ -235,14 +267,20 @@ class BrData(object):
|
|||||||
with async_timeout.timeout(10, loop=self.hass.loop):
|
with async_timeout.timeout(10, loop=self.hass.loop):
|
||||||
resp = yield from websession.get(url)
|
resp = yield from websession.get(url)
|
||||||
|
|
||||||
result[SUCCESS] = (resp.status == 200)
|
|
||||||
result[STATUS_CODE] = resp.status
|
result[STATUS_CODE] = resp.status
|
||||||
result[CONTENT] = yield from resp.text()
|
result[CONTENT] = yield from resp.text()
|
||||||
|
if resp.status == 200:
|
||||||
|
result[SUCCESS] = True
|
||||||
|
else:
|
||||||
|
result[MESSAGE] = "Got http statuscode: %d" % (resp.status)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
except (asyncio.TimeoutError, aiohttp.ClientError) as err:
|
except (asyncio.TimeoutError, aiohttp.ClientError) as err:
|
||||||
result[MESSAGE] = "%s" % err
|
result[MESSAGE] = "%s" % err
|
||||||
return result
|
return result
|
||||||
|
finally:
|
||||||
|
if resp is not None:
|
||||||
|
yield from resp.release()
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_update(self, *_):
|
def async_update(self, *_):
|
||||||
@ -254,6 +292,16 @@ class BrData(object):
|
|||||||
if not content.get(SUCCESS, False):
|
if not content.get(SUCCESS, False):
|
||||||
content = yield from self.get_data('http://api.buienradar.nl')
|
content = yield from self.get_data('http://api.buienradar.nl')
|
||||||
|
|
||||||
|
if content.get(SUCCESS) is not True:
|
||||||
|
# unable to get the data
|
||||||
|
_LOGGER.warning("Unable to retrieve xml data from Buienradar."
|
||||||
|
"(Msg: %s, status: %s,)",
|
||||||
|
content.get(MESSAGE),
|
||||||
|
content.get(STATUS_CODE),)
|
||||||
|
# schedule new call
|
||||||
|
yield from self.schedule_update(SCHEDULE_NOK)
|
||||||
|
return
|
||||||
|
|
||||||
# rounding coordinates prevents unnecessary redirects/calls
|
# rounding coordinates prevents unnecessary redirects/calls
|
||||||
rainurl = 'http://gadgets.buienradar.nl/data/raintext/?lat={}&lon={}'
|
rainurl = 'http://gadgets.buienradar.nl/data/raintext/?lat={}&lon={}'
|
||||||
rainurl = rainurl.format(
|
rainurl = rainurl.format(
|
||||||
@ -262,28 +310,33 @@ class BrData(object):
|
|||||||
)
|
)
|
||||||
raincontent = yield from self.get_data(rainurl)
|
raincontent = yield from self.get_data(rainurl)
|
||||||
|
|
||||||
if content.get(SUCCESS) and raincontent.get(SUCCESS):
|
if raincontent.get(SUCCESS) is not True:
|
||||||
|
# unable to get the data
|
||||||
|
_LOGGER.warning("Unable to retrieve raindata from Buienradar."
|
||||||
|
"(Msg: %s, status: %s,)",
|
||||||
|
raincontent.get(MESSAGE),
|
||||||
|
raincontent.get(STATUS_CODE),)
|
||||||
|
# schedule new call
|
||||||
|
yield from self.schedule_update(SCHEDULE_NOK)
|
||||||
|
return
|
||||||
|
|
||||||
result = parse_data(content.get(CONTENT),
|
result = parse_data(content.get(CONTENT),
|
||||||
raincontent.get(CONTENT),
|
raincontent.get(CONTENT),
|
||||||
self.coordinates[CONF_LATITUDE],
|
self.coordinates[CONF_LATITUDE],
|
||||||
self.coordinates[CONF_LONGITUDE],
|
self.coordinates[CONF_LONGITUDE],
|
||||||
self.timeframe)
|
self.timeframe)
|
||||||
if result.get(SUCCESS):
|
|
||||||
|
_LOGGER.debug("Buienradar parsed data: %s", result)
|
||||||
|
if result.get(SUCCESS) is not True:
|
||||||
|
_LOGGER.warning("Unable to parse data from Buienradar."
|
||||||
|
"(Msg: %s)",
|
||||||
|
result.get(MESSAGE),)
|
||||||
|
yield from self.schedule_update(SCHEDULE_NOK)
|
||||||
|
return
|
||||||
|
|
||||||
self.data = result.get(DATA)
|
self.data = result.get(DATA)
|
||||||
|
|
||||||
yield from self.update_devices()
|
yield from self.update_devices()
|
||||||
|
yield from self.schedule_update(SCHEDULE_OK)
|
||||||
yield from self.schedule_update(10)
|
|
||||||
else:
|
|
||||||
yield from self.schedule_update(2)
|
|
||||||
else:
|
|
||||||
# unable to get the data
|
|
||||||
_LOGGER.warning("Unable to retrieve data from Buienradar."
|
|
||||||
"(Msg: %s, status: %s,)",
|
|
||||||
result.get(MESSAGE),
|
|
||||||
result.get(STATUS_CODE),)
|
|
||||||
# schedule new call
|
|
||||||
yield from self.schedule_update(2)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def attribution(self):
|
def attribution(self):
|
||||||
|
@ -6,7 +6,6 @@ https://home-assistant.io/components/weather.buienradar/
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import timedelta
|
|
||||||
from homeassistant.components.weather import (
|
from homeassistant.components.weather import (
|
||||||
WeatherEntity, PLATFORM_SCHEMA)
|
WeatherEntity, PLATFORM_SCHEMA)
|
||||||
from homeassistant.const import \
|
from homeassistant.const import \
|
||||||
@ -15,10 +14,10 @@ from homeassistant.helpers import config_validation as cv
|
|||||||
# Reuse data and API logic from the sensor implementation
|
# Reuse data and API logic from the sensor implementation
|
||||||
from homeassistant.components.sensor.buienradar import (
|
from homeassistant.components.sensor.buienradar import (
|
||||||
BrData)
|
BrData)
|
||||||
from homeassistant.helpers.event import (
|
|
||||||
async_track_time_interval)
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
REQUIREMENTS = ['buienradar==0.7']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_TIMEFRAME = 60
|
DEFAULT_TIMEFRAME = 60
|
||||||
@ -49,14 +48,13 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
# create weather data:
|
# create weather data:
|
||||||
data = BrData(hass, coordinates, DEFAULT_TIMEFRAME, None)
|
data = BrData(hass, coordinates, DEFAULT_TIMEFRAME, None)
|
||||||
# create weather device:
|
# create weather device:
|
||||||
|
_LOGGER.debug("Initializing buienradar weather: coordinates %s",
|
||||||
|
coordinates)
|
||||||
async_add_devices([BrWeather(data, config.get(CONF_FORECAST, True),
|
async_add_devices([BrWeather(data, config.get(CONF_FORECAST, True),
|
||||||
config.get(CONF_NAME, None))])
|
config.get(CONF_NAME, None))])
|
||||||
|
|
||||||
# Update weather every 10 minutes, since
|
|
||||||
# the data gets updated every 10 minutes
|
|
||||||
async_track_time_interval(hass, data.async_update, timedelta(minutes=10))
|
|
||||||
# schedule the first update in 1 minute from now:
|
# schedule the first update in 1 minute from now:
|
||||||
data.schedule_update(1)
|
yield from data.schedule_update(1)
|
||||||
|
|
||||||
|
|
||||||
class BrWeather(WeatherEntity):
|
class BrWeather(WeatherEntity):
|
||||||
|
@ -118,7 +118,8 @@ boto3==1.4.3
|
|||||||
broadlink==0.3
|
broadlink==0.3
|
||||||
|
|
||||||
# homeassistant.components.sensor.buienradar
|
# homeassistant.components.sensor.buienradar
|
||||||
buienradar==0.6
|
# homeassistant.components.weather.buienradar
|
||||||
|
buienradar==0.7
|
||||||
|
|
||||||
# homeassistant.components.notify.ciscospark
|
# homeassistant.components.notify.ciscospark
|
||||||
ciscosparkapi==0.4.2
|
ciscosparkapi==0.4.2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user