From 1af723f8ce9a380660a3165eac443db180c61f32 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Wed, 26 Jul 2017 21:03:35 +0200 Subject: [PATCH 01/18] Added DWD WarnApp Sensor --- .../components/sensor/dwd_warnapp.py | 240 ++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 homeassistant/components/sensor/dwd_warnapp.py diff --git a/homeassistant/components/sensor/dwd_warnapp.py b/homeassistant/components/sensor/dwd_warnapp.py new file mode 100644 index 00000000000000..7226b6500466df --- /dev/null +++ b/homeassistant/components/sensor/dwd_warnapp.py @@ -0,0 +1,240 @@ +""" +Support for getting statistical data from a DWD-Warnapp system. +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.dwd_warnapp/ + +Data is fetched from DWD: +https://rcccm.dwd.de/DE/wetter/warnungen_aktuell/objekt_einbindung/objekteinbindung.html + +Warnungen vor extremem Unwetter (Stufe 4) +Unwetterwarnungen (Stufe 3) +Warnungen vor markantem Wetter (Stufe 2) +Wetterwarnungen (Stufe 1) +""" +import logging +import json +import time +import datetime +from datetime import timedelta + +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity import Entity +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_NAME, CONF_HOST, CONF_SSL, CONF_VERIFY_SSL, CONF_MONITORED_CONDITIONS) +import homeassistant.util.dt as dt_util + +_LOGGER = logging.getLogger(__name__) +_ENDPOINT = '/DWD/warnungen/warnapp_landkreise/json/warnings.json?jsonp=loadWarnings' + +DEFAULT_HOST = 'www.dwd.de' + +DEFAULT_METHOD = 'GET' +DEFAULT_NAME = 'DWD-Warnapp' +DEFAULT_SSL = True +DEFAULT_VERIFY_SSL = True + +CONF_REGION_NAME = 'region_name' +DEFAULT_REGION_NAME = 'Hansestadt Hamburg' + +SCAN_INTERVAL = timedelta(minutes=15) + +MONITORED_CONDITIONS = { + 'current_warning_level': ['Current Warning Level', + None, 'mdi:close-octagon-outline'], + 'advance_warning_level': ['Advance Warning Level', + None, 'mdi:close-octagon-outline'], +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_REGION_NAME, default=DEFAULT_REGION_NAME): cv.string, + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean, + vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, + vol.Optional(CONF_MONITORED_CONDITIONS, default=MONITORED_CONDITIONS): + vol.All(cv.ensure_list, [vol.In(MONITORED_CONDITIONS)]), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the DWD-Warnapp sensor.""" + name = config.get(CONF_NAME) + host = config.get(CONF_HOST) + use_ssl = config.get(CONF_SSL) + verify_ssl = config.get(CONF_VERIFY_SSL) + region_name = config.get(CONF_REGION_NAME) + + api = DwdWarnappAPI(host, use_ssl, verify_ssl, region_name) + + sensors = [DwdWarnappSensor(hass, api, name, condition) + for condition in config[CONF_MONITORED_CONDITIONS]] + + add_devices(sensors, True) + + +class DwdWarnappSensor(Entity): + """Representation of a DWD-Warnapp sensor.""" + + def __init__(self, hass, api, name, variable): + """Initialize a DWD-Warnapp sensor.""" + self._hass = hass + self._api = api + self._name = name + self._var_id = variable + + variable_info = MONITORED_CONDITIONS[variable] + self._var_name = variable_info[0] + self._var_units = variable_info[1] + self._var_icon = variable_info[2] + + @property + def name(self): + """Return the name of the sensor.""" + return "{} {}".format(self._name, self._var_name) + + @property + def icon(self): + """Icon to use in the frontend, if any.""" + return self._var_icon + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return self._var_units + + # pylint: disable=no-member + @property + def state(self): + """Return the state of the device.""" + try: + return round(self._api.data[self._var_id], 2) + except TypeError: + return self._api.data[self._var_id] + + # pylint: disable=no-member + @property + def device_state_attributes(self): + """Return the state attributes of the DWD-Warnapp.""" + + data = {} + data['region_name'] = self._api.region_name + + if self._api.region_id is not None: + data['region_id'] = self._api.region_id + + if self._api.region_state is not None: + data['region_state'] = self._api.region_state + # data['region_map_url'] = 'https://www.dwd.de/DWD/warnungen/warnapp_gemeinden/json/warnungen_gemeinde_map_' + str(data['region_state'].lower()) + '.png' + + if self._api.data['time'] is not None: + data['last_update'] = dt_util.as_local(dt_util.utc_from_timestamp(self._api.data['time'] / 1000)) + + if self._var_id == 'current_warning_level': + prefix = 'current' + elif self._var_id == 'advance_warning_level': + prefix = 'advance' + + data['warning_count'] = self._api.data[prefix + '_warning_count'] + i = 0 + for event in self._api.data[prefix + '_warnings']: + i = i + 1 + + data['warning_{}_name'.format(i)] = event['event'] + data['warning_{}_level'.format(i)] = event['level'] + data['warning_{}_type'.format(i)] = event['type'] + if len(event['headline']) > 0: + data['warning_{}_headline'.format(i)] = event['headline'] + if len(event['description']) > 0: + data['warning_{}_description'.format(i)] = event['description'] + if len(event['instruction']) > 0: + data['warning_{}_instruction'.format(i)] = event['instruction'] + + if event['start'] is not None: + data['warning_{}_start'.format(i)] = dt_util.as_local(dt_util.utc_from_timestamp(event['start'] / 1000)) + + if event['end'] is not None: + data['warning_{}_end'.format(i)] = dt_util.as_local(dt_util.utc_from_timestamp(event['end'] / 1000)) + + return data + + @property + def available(self): + """Could the device be accessed during the last update call.""" + return self._api.available + + def update(self): + """Get the latest data from the DWD-Warnapp API.""" + self._api.update() + + +class DwdWarnappAPI(object): + """Get the latest data and update the states.""" + + def __init__(self, host, use_ssl, verify_ssl, region_name): + """Initialize the data object.""" + from homeassistant.components.sensor.rest import RestData + + uri_scheme = 'https://' if use_ssl else 'http://' + resource = "{}{}{}".format(uri_scheme, host, _ENDPOINT) + + self._rest = RestData('GET', resource, None, None, None, verify_ssl) + self.region_name = region_name + self.region_id = None + self.region_state = None + self.data = None + self.available = True + self.update() + + #@Throttle(SCAN_INTERVAL) + def update(self): + """Get the latest data from the DWD-Warnapp.""" + try: + self._rest.update() + + json_string = self._rest.data[24:len(self._rest.data) - 2] + json_obj = json.loads(json_string) + + data = {} + + data['time'] = json_obj['time'] + + for mykey, myvalue in {'current': 'warnings', 'advance': 'vorabInformation'}.items(): + + _LOGGER.debug("Found {} {} global DWD warnings".format(len(json_obj[myvalue]), mykey)) + + data['{}_warning_level'.format(mykey)] = 0 + my_warnings = [] + + if self.region_id is not None: + # get a specific region_id + if self.region_id in json_obj[myvalue]: + my_warnings = json_obj[myvalue][self.region_id] + + else: + # loop through all items to find warnings, region_id and region_state for region_name + for key in json_obj[myvalue]: + if json_obj[myvalue][key][0]['regionName'] != self.region_name: + continue + my_warnings = json_obj[myvalue][key] + self.region_id = key + self.region_state = json_obj[myvalue][key][0]['stateShort'] + break + + # Get max warning level + for event in my_warnings: + if(event['level'] >= data['{}_warning_level'.format(mykey)]): + data['{}_warning_level'.format(mykey)] = event['level'] + + data['{}_warning_count'.format(mykey)] = len(my_warnings) + data['{}_warnings'.format(mykey)] = my_warnings + + _LOGGER.debug("Found {} {} local DWD warnings".format(len(my_warnings), mykey)) + + self.data = data + self.available = True + except TypeError: + _LOGGER.error("Unable to fetch data from DWD-Warnapp") + self.available = False From 7cb7924f85d67ae0b455d38e014bcd8f3afac647 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Wed, 26 Jul 2017 21:26:27 +0200 Subject: [PATCH 02/18] Fixed some idents and spaces --- .coveragerc | 1 + .../components/sensor/dwd_warnapp.py | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.coveragerc b/.coveragerc index 3ec0b119cb8e93..d68deaff82922d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -419,6 +419,7 @@ omit = homeassistant/components/sensor/dovado.py homeassistant/components/sensor/dte_energy_bridge.py homeassistant/components/sensor/dublin_bus_transport.py + homeassistant/components/sensor/dwdwarnapp.py homeassistant/components/sensor/ebox.py homeassistant/components/sensor/eddystone_temperature.py homeassistant/components/sensor/eliqonline.py diff --git a/homeassistant/components/sensor/dwd_warnapp.py b/homeassistant/components/sensor/dwd_warnapp.py index 7226b6500466df..2994f049693918 100644 --- a/homeassistant/components/sensor/dwd_warnapp.py +++ b/homeassistant/components/sensor/dwd_warnapp.py @@ -43,9 +43,9 @@ MONITORED_CONDITIONS = { 'current_warning_level': ['Current Warning Level', - None, 'mdi:close-octagon-outline'], + None, 'mdi:close-octagon-outline'], 'advance_warning_level': ['Advance Warning Level', - None, 'mdi:close-octagon-outline'], + None, 'mdi:close-octagon-outline'], } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -122,15 +122,16 @@ def device_state_attributes(self): data = {} data['region_name'] = self._api.region_name - if self._api.region_id is not None: + if self._api.region_id is not None: data['region_id'] = self._api.region_id - if self._api.region_state is not None: + if self._api.region_state is not None: data['region_state'] = self._api.region_state # data['region_map_url'] = 'https://www.dwd.de/DWD/warnungen/warnapp_gemeinden/json/warnungen_gemeinde_map_' + str(data['region_state'].lower()) + '.png' if self._api.data['time'] is not None: - data['last_update'] = dt_util.as_local(dt_util.utc_from_timestamp(self._api.data['time'] / 1000)) + data['last_update'] = dt_util.as_local( + dt_util.utc_from_timestamp(self._api.data['time'] / 1000)) if self._var_id == 'current_warning_level': prefix = 'current' @@ -153,10 +154,12 @@ def device_state_attributes(self): data['warning_{}_instruction'.format(i)] = event['instruction'] if event['start'] is not None: - data['warning_{}_start'.format(i)] = dt_util.as_local(dt_util.utc_from_timestamp(event['start'] / 1000)) + data['warning_{}_start'.format(i)] = dt_util.as_local( + dt_util.utc_from_timestamp(event['start'] / 1000)) if event['end'] is not None: - data['warning_{}_end'.format(i)] = dt_util.as_local(dt_util.utc_from_timestamp(event['end'] / 1000)) + data['warning_{}_end'.format(i)] = dt_util.as_local( + dt_util.utc_from_timestamp(event['end'] / 1000)) return data @@ -203,12 +206,13 @@ def update(self): for mykey, myvalue in {'current': 'warnings', 'advance': 'vorabInformation'}.items(): - _LOGGER.debug("Found {} {} global DWD warnings".format(len(json_obj[myvalue]), mykey)) + _LOGGER.debug("Found {} {} global DWD warnings".format( + len(json_obj[myvalue]), mykey)) data['{}_warning_level'.format(mykey)] = 0 my_warnings = [] - if self.region_id is not None: + if self.region_id is not None: # get a specific region_id if self.region_id in json_obj[myvalue]: my_warnings = json_obj[myvalue][self.region_id] @@ -231,7 +235,8 @@ def update(self): data['{}_warning_count'.format(mykey)] = len(my_warnings) data['{}_warnings'.format(mykey)] = my_warnings - _LOGGER.debug("Found {} {} local DWD warnings".format(len(my_warnings), mykey)) + _LOGGER.debug("Found {} {} local DWD warnings".format( + len(my_warnings), mykey)) self.data = data self.available = True From 17cc1a7d6ee0f10bf4c84d9ee5ceff05e1b25b0f Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Wed, 26 Jul 2017 21:39:26 +0200 Subject: [PATCH 03/18] Removed unused imports --- homeassistant/components/sensor/dwd_warnapp.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/homeassistant/components/sensor/dwd_warnapp.py b/homeassistant/components/sensor/dwd_warnapp.py index 2994f049693918..54f913fcb69e19 100644 --- a/homeassistant/components/sensor/dwd_warnapp.py +++ b/homeassistant/components/sensor/dwd_warnapp.py @@ -13,8 +13,6 @@ """ import logging import json -import time -import datetime from datetime import timedelta import voluptuous as vol From 7b3e84c40fa76524614da1222623dd5058724867 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Wed, 26 Jul 2017 21:40:39 +0200 Subject: [PATCH 04/18] Removed comment --- homeassistant/components/sensor/dwd_warnapp.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/sensor/dwd_warnapp.py b/homeassistant/components/sensor/dwd_warnapp.py index 54f913fcb69e19..1b51441739ed6c 100644 --- a/homeassistant/components/sensor/dwd_warnapp.py +++ b/homeassistant/components/sensor/dwd_warnapp.py @@ -125,7 +125,6 @@ def device_state_attributes(self): if self._api.region_state is not None: data['region_state'] = self._api.region_state - # data['region_map_url'] = 'https://www.dwd.de/DWD/warnungen/warnapp_gemeinden/json/warnungen_gemeinde_map_' + str(data['region_state'].lower()) + '.png' if self._api.data['time'] is not None: data['last_update'] = dt_util.as_local( From a85e8d5de43450a13e42eef3bc0f9f462c7e82d8 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sat, 5 Aug 2017 00:17:01 +0200 Subject: [PATCH 05/18] Some fixes --- .../components/sensor/dwd_warnapp.py | 55 ++++++++----------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/sensor/dwd_warnapp.py b/homeassistant/components/sensor/dwd_warnapp.py index 1b51441739ed6c..11ddddd5012290 100644 --- a/homeassistant/components/sensor/dwd_warnapp.py +++ b/homeassistant/components/sensor/dwd_warnapp.py @@ -1,7 +1,7 @@ """ -Support for getting statistical data from a DWD-Warnapp system. +Support for getting statistical data from a DWD Weather Warnings. For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/sensor.dwd_warnapp/ +https://home-assistant.io/components/sensor.dwd_weather_warnings/ Data is fetched from DWD: https://rcccm.dwd.de/DE/wetter/warnungen_aktuell/objekt_einbindung/objekteinbindung.html @@ -25,14 +25,8 @@ import homeassistant.util.dt as dt_util _LOGGER = logging.getLogger(__name__) -_ENDPOINT = '/DWD/warnungen/warnapp_landkreise/json/warnings.json?jsonp=loadWarnings' -DEFAULT_HOST = 'www.dwd.de' - -DEFAULT_METHOD = 'GET' -DEFAULT_NAME = 'DWD-Warnapp' -DEFAULT_SSL = True -DEFAULT_VERIFY_SSL = True +DEFAULT_NAME = 'DWD-Wetter-Warnungen' CONF_REGION_NAME = 'region_name' DEFAULT_REGION_NAME = 'Hansestadt Hamburg' @@ -48,36 +42,30 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_REGION_NAME, default=DEFAULT_REGION_NAME): cv.string, - vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean, - vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, vol.Optional(CONF_MONITORED_CONDITIONS, default=MONITORED_CONDITIONS): vol.All(cv.ensure_list, [vol.In(MONITORED_CONDITIONS)]), }) def setup_platform(hass, config, add_devices, discovery_info=None): - """Set up the DWD-Warnapp sensor.""" + """Set up the DWD-Weather-Warnings sensor.""" name = config.get(CONF_NAME) - host = config.get(CONF_HOST) - use_ssl = config.get(CONF_SSL) - verify_ssl = config.get(CONF_VERIFY_SSL) region_name = config.get(CONF_REGION_NAME) - api = DwdWarnappAPI(host, use_ssl, verify_ssl, region_name) + api = DwdWeatherWarningsAPI(region_name) - sensors = [DwdWarnappSensor(hass, api, name, condition) + sensors = [DwdWeatherWarningsSensor(hass, api, name, condition) for condition in config[CONF_MONITORED_CONDITIONS]] add_devices(sensors, True) -class DwdWarnappSensor(Entity): - """Representation of a DWD-Warnapp sensor.""" +class DwdWeatherWarningsSensor(Entity): + """Representation of a DWD-Weather-Warnings sensor.""" def __init__(self, hass, api, name, variable): - """Initialize a DWD-Warnapp sensor.""" + """Initialize a DWD-Weather-Warnings sensor.""" self._hass = hass self._api = api self._name = name @@ -115,7 +103,7 @@ def state(self): # pylint: disable=no-member @property def device_state_attributes(self): - """Return the state attributes of the DWD-Warnapp.""" + """Return the state attributes of the DWD-Weather-Warnings.""" data = {} data['region_name'] = self._api.region_name @@ -125,6 +113,7 @@ def device_state_attributes(self): if self._api.region_state is not None: data['region_state'] = self._api.region_state + # data['region_map_url'] = 'https://www.dwd.de/DWD/warnungen/warnapp_gemeinden/json/warnungen_gemeinde_map_' + str(data['region_state'].lower()) + '.png' if self._api.data['time'] is not None: data['last_update'] = dt_util.as_local( @@ -166,21 +155,25 @@ def available(self): return self._api.available def update(self): - """Get the latest data from the DWD-Warnapp API.""" + """Get the latest data from the DWD-Weather-Warnings API.""" self._api.update() -class DwdWarnappAPI(object): +class DwdWeatherWarningsAPI(object): """Get the latest data and update the states.""" - def __init__(self, host, use_ssl, verify_ssl, region_name): + def __init__(self, region_name): """Initialize the data object.""" from homeassistant.components.sensor.rest import RestData - uri_scheme = 'https://' if use_ssl else 'http://' - resource = "{}{}{}".format(uri_scheme, host, _ENDPOINT) + resource = "{}{}{}?{}".format( + 'https://', + 'www.dwd.de', + '/DWD/warnungen/warnapp_landkreise/json/warnings.json', + 'jsonp=loadWarnings' + ) - self._rest = RestData('GET', resource, None, None, None, verify_ssl) + self._rest = RestData('GET', resource, None, None, None, True) self.region_name = region_name self.region_id = None self.region_state = None @@ -188,9 +181,9 @@ def __init__(self, host, use_ssl, verify_ssl, region_name): self.available = True self.update() - #@Throttle(SCAN_INTERVAL) + @Throttle(SCAN_INTERVAL) def update(self): - """Get the latest data from the DWD-Warnapp.""" + """Get the latest data from the DWD-Weather-Warnings.""" try: self._rest.update() @@ -238,5 +231,5 @@ def update(self): self.data = data self.available = True except TypeError: - _LOGGER.error("Unable to fetch data from DWD-Warnapp") + _LOGGER.error("Unable to fetch data from DWD-Weather-Warnings") self.available = False From d9da925e2dd91e786d4174b36b199db26b1985ac Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sat, 5 Aug 2017 00:20:26 +0200 Subject: [PATCH 06/18] Added throttle --- homeassistant/components/sensor/dwd_warnapp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/dwd_warnapp.py b/homeassistant/components/sensor/dwd_warnapp.py index 11ddddd5012290..8714ed13c74e07 100644 --- a/homeassistant/components/sensor/dwd_warnapp.py +++ b/homeassistant/components/sensor/dwd_warnapp.py @@ -21,7 +21,8 @@ from homeassistant.helpers.entity import Entity from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import ( - CONF_NAME, CONF_HOST, CONF_SSL, CONF_VERIFY_SSL, CONF_MONITORED_CONDITIONS) + CONF_NAME, CONF_MONITORED_CONDITIONS) +from homeassistant.util import Throttle import homeassistant.util.dt as dt_util _LOGGER = logging.getLogger(__name__) From d2f6676fa3092f4e5d5a0e53c6a22fc6879a89c4 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sat, 5 Aug 2017 00:22:23 +0200 Subject: [PATCH 07/18] Renamed sensor to dwd weather warnings --- .../components/sensor/{dwd_warnapp.py => dwd_weather_warnings.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename homeassistant/components/sensor/{dwd_warnapp.py => dwd_weather_warnings.py} (100%) diff --git a/homeassistant/components/sensor/dwd_warnapp.py b/homeassistant/components/sensor/dwd_weather_warnings.py similarity index 100% rename from homeassistant/components/sensor/dwd_warnapp.py rename to homeassistant/components/sensor/dwd_weather_warnings.py From df60b1a4d9fe3580d616c9dc3f19c4a1f87e3782 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sat, 5 Aug 2017 00:29:03 +0200 Subject: [PATCH 08/18] Renamed test file --- .coveragerc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index d68deaff82922d..47113fa22f3da1 100644 --- a/.coveragerc +++ b/.coveragerc @@ -419,7 +419,7 @@ omit = homeassistant/components/sensor/dovado.py homeassistant/components/sensor/dte_energy_bridge.py homeassistant/components/sensor/dublin_bus_transport.py - homeassistant/components/sensor/dwdwarnapp.py + homeassistant/components/sensor/dwd_weather_warnings.py homeassistant/components/sensor/ebox.py homeassistant/components/sensor/eddystone_temperature.py homeassistant/components/sensor/eliqonline.py From deb31e7b2cd6df8ee19ad56d6f40341dbcde05d1 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sun, 6 Aug 2017 21:47:34 +0200 Subject: [PATCH 09/18] shorten lines --- homeassistant/components/sensor/dwd_weather_warnings.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index 8714ed13c74e07..d52f78c91ee1f7 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -114,7 +114,6 @@ def device_state_attributes(self): if self._api.region_state is not None: data['region_state'] = self._api.region_state - # data['region_map_url'] = 'https://www.dwd.de/DWD/warnungen/warnapp_gemeinden/json/warnungen_gemeinde_map_' + str(data['region_state'].lower()) + '.png' if self._api.data['time'] is not None: data['last_update'] = dt_util.as_local( @@ -195,7 +194,10 @@ def update(self): data['time'] = json_obj['time'] - for mykey, myvalue in {'current': 'warnings', 'advance': 'vorabInformation'}.items(): + for mykey, myvalue in { + 'current': 'warnings', + 'advance': 'vorabInformation' + }.items(): _LOGGER.debug("Found {} {} global DWD warnings".format( len(json_obj[myvalue]), mykey)) @@ -209,7 +211,8 @@ def update(self): my_warnings = json_obj[myvalue][self.region_id] else: - # loop through all items to find warnings, region_id and region_state for region_name + # loop through all items to find warnings, region_id + # and region_state for region_name for key in json_obj[myvalue]: if json_obj[myvalue][key][0]['regionName'] != self.region_name: continue From 5c270a4995f9a565e560dd9d034141bad7f0cb86 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sun, 6 Aug 2017 21:56:40 +0200 Subject: [PATCH 10/18] shorten lines --- homeassistant/components/sensor/dwd_weather_warnings.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index d52f78c91ee1f7..ed7913c49c11a7 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -214,16 +214,19 @@ def update(self): # loop through all items to find warnings, region_id # and region_state for region_name for key in json_obj[myvalue]: - if json_obj[myvalue][key][0]['regionName'] != self.region_name: + my_region = json_obj[myvalue][key][0]['regionName'] + if my_region != self.region_name: continue my_warnings = json_obj[myvalue][key] + my_state = json_obj[myvalue][key][0]['stateShort'] self.region_id = key - self.region_state = json_obj[myvalue][key][0]['stateShort'] + self.region_state = my_state break # Get max warning level for event in my_warnings: - if(event['level'] >= data['{}_warning_level'.format(mykey)]): + if(event['level'] >= + data['{}_warning_level'.format(mykey)]): data['{}_warning_level'.format(mykey)] = event['level'] data['{}_warning_count'.format(mykey)] = len(my_warnings) From 7426e3e22a10e54c2c942f0e76f2b301e412f31f Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Tue, 8 Aug 2017 22:54:26 +0200 Subject: [PATCH 11/18] Implemented changes requested by fabaff --- .../components/sensor/dwd_weather_warnings.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index ed7913c49c11a7..ad06a2edc1274a 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -24,13 +24,13 @@ CONF_NAME, CONF_MONITORED_CONDITIONS) from homeassistant.util import Throttle import homeassistant.util.dt as dt_util +from homeassistant.components.sensor.rest import RestData _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = 'DWD-Wetter-Warnungen' +DEFAULT_NAME = 'DWD-Weather-Warnings' CONF_REGION_NAME = 'region_name' -DEFAULT_REGION_NAME = 'Hansestadt Hamburg' SCAN_INTERVAL = timedelta(minutes=15) @@ -42,7 +42,7 @@ } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_REGION_NAME, default=DEFAULT_REGION_NAME): cv.string, + vol.Optional(CONF_REGION_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_MONITORED_CONDITIONS, default=MONITORED_CONDITIONS): vol.All(cv.ensure_list, [vol.In(MONITORED_CONDITIONS)]), @@ -56,7 +56,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): api = DwdWeatherWarningsAPI(region_name) - sensors = [DwdWeatherWarningsSensor(hass, api, name, condition) + sensors = [DwdWeatherWarningsSensor(api, name, condition) for condition in config[CONF_MONITORED_CONDITIONS]] add_devices(sensors, True) @@ -65,9 +65,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class DwdWeatherWarningsSensor(Entity): """Representation of a DWD-Weather-Warnings sensor.""" - def __init__(self, hass, api, name, variable): + def __init__(self, api, name, variable): """Initialize a DWD-Weather-Warnings sensor.""" - self._hass = hass self._api = api self._name = name self._var_id = variable @@ -164,7 +163,6 @@ class DwdWeatherWarningsAPI(object): def __init__(self, region_name): """Initialize the data object.""" - from homeassistant.components.sensor.rest import RestData resource = "{}{}{}?{}".format( 'https://', From 43cc842d04eb6f5d07e19da457ceff84ab5b8587 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Fri, 18 Aug 2017 20:04:31 +0200 Subject: [PATCH 12/18] added ATTRIBUTION --- .../components/sensor/dwd_weather_warnings.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index ad06a2edc1274a..5c38356897295d 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -21,13 +21,15 @@ from homeassistant.helpers.entity import Entity from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import ( - CONF_NAME, CONF_MONITORED_CONDITIONS) + ATTR_ATTRIBUTION, CONF_NAME, CONF_MONITORED_CONDITIONS) from homeassistant.util import Throttle import homeassistant.util.dt as dt_util from homeassistant.components.sensor.rest import RestData _LOGGER = logging.getLogger(__name__) +ATTRIBUTION = "Data provided by DWD" + DEFAULT_NAME = 'DWD-Weather-Warnings' CONF_REGION_NAME = 'region_name' @@ -91,6 +93,13 @@ def unit_of_measurement(self): """Return the unit the value is expressed in.""" return self._var_units + @property + def device_state_attributes(self): + """Return the state attributes of the sensor.""" + return { + ATTR_ATTRIBUTION: ATTRIBUTION, + } + # pylint: disable=no-member @property def state(self): From 8a510f73b04d8c60e9500f0f76f12ffcb32d879f Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Fri, 18 Aug 2017 20:09:32 +0200 Subject: [PATCH 13/18] move ATTRIBUTION to existing method --- homeassistant/components/sensor/dwd_weather_warnings.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index 5c38356897295d..cba71cc428e91f 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -93,13 +93,6 @@ def unit_of_measurement(self): """Return the unit the value is expressed in.""" return self._var_units - @property - def device_state_attributes(self): - """Return the state attributes of the sensor.""" - return { - ATTR_ATTRIBUTION: ATTRIBUTION, - } - # pylint: disable=no-member @property def state(self): @@ -115,6 +108,7 @@ def device_state_attributes(self): """Return the state attributes of the DWD-Weather-Warnings.""" data = {} + data[ATTR_ATTRIBUTION] = ATTRIBUTION data['region_name'] = self._api.region_name if self._api.region_id is not None: From 339b09785a4f1b692b472e56a772654f658a25b8 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Fri, 18 Aug 2017 21:00:49 +0200 Subject: [PATCH 14/18] fixed lint tests --- homeassistant/components/sensor/dwd_weather_warnings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index cba71cc428e91f..a44c0e828fcaa5 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -1,5 +1,6 @@ """ Support for getting statistical data from a DWD Weather Warnings. + For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.dwd_weather_warnings/ @@ -106,7 +107,6 @@ def state(self): @property def device_state_attributes(self): """Return the state attributes of the DWD-Weather-Warnings.""" - data = {} data[ATTR_ATTRIBUTION] = ATTRIBUTION data['region_name'] = self._api.region_name From 809576188548f3691e7129690579bb321b07a976 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sat, 2 Sep 2017 22:09:26 +0200 Subject: [PATCH 15/18] Fix linter issues --- homeassistant/components/sensor/dwd_weather_warnings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index a44c0e828fcaa5..94267474fc72e0 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -196,8 +196,8 @@ def update(self): data['time'] = json_obj['time'] for mykey, myvalue in { - 'current': 'warnings', - 'advance': 'vorabInformation' + 'current': 'warnings', + 'advance': 'vorabInformation' }.items(): _LOGGER.debug("Found {} {} global DWD warnings".format( @@ -225,9 +225,9 @@ def update(self): break # Get max warning level + maxlevel = data['{}_warning_level'.format(mykey)] for event in my_warnings: - if(event['level'] >= - data['{}_warning_level'.format(mykey)]): + if(event['level'] >= maxlevel): data['{}_warning_level'.format(mykey)] = event['level'] data['{}_warning_count'.format(mykey)] = len(my_warnings) From 0e0a9e9f40e406421c374ba0432a9224e9059666 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sat, 2 Sep 2017 22:13:31 +0200 Subject: [PATCH 16/18] Fix linter issues --- homeassistant/components/sensor/dwd_weather_warnings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index 94267474fc72e0..c76cec5e2a4cd9 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -200,8 +200,8 @@ def update(self): 'advance': 'vorabInformation' }.items(): - _LOGGER.debug("Found {} {} global DWD warnings".format( - len(json_obj[myvalue]), mykey)) + _LOGGER.debug("Found %d %s global DWD warnings", + len(json_obj[myvalue]), mykey) data['{}_warning_level'.format(mykey)] = 0 my_warnings = [] @@ -233,8 +233,8 @@ def update(self): data['{}_warning_count'.format(mykey)] = len(my_warnings) data['{}_warnings'.format(mykey)] = my_warnings - _LOGGER.debug("Found {} {} local DWD warnings".format( - len(my_warnings), mykey)) + _LOGGER.debug("Found %d %s local DWD warnings", + len(my_warnings), mykey) self.data = data self.available = True From 70d019593b2d2dfa6b0f72f029d207b018b0d1a1 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sun, 3 Sep 2017 00:12:03 +0200 Subject: [PATCH 17/18] Fix linter --- homeassistant/components/sensor/dwd_weather_warnings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index c76cec5e2a4cd9..dc40a5e56f35aa 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -201,7 +201,7 @@ def update(self): }.items(): _LOGGER.debug("Found %d %s global DWD warnings", - len(json_obj[myvalue]), mykey) + len(json_obj[myvalue]), mykey) data['{}_warning_level'.format(mykey)] = 0 my_warnings = [] @@ -227,14 +227,14 @@ def update(self): # Get max warning level maxlevel = data['{}_warning_level'.format(mykey)] for event in my_warnings: - if(event['level'] >= maxlevel): + if event['level'] >= maxlevel: data['{}_warning_level'.format(mykey)] = event['level'] data['{}_warning_count'.format(mykey)] = len(my_warnings) data['{}_warnings'.format(mykey)] = my_warnings _LOGGER.debug("Found %d %s local DWD warnings", - len(my_warnings), mykey) + len(my_warnings), mykey) self.data = data self.available = True From 0940766bc3a0f37cfa4e5402edb266941ec065b3 Mon Sep 17 00:00:00 2001 From: Philipp Hellmich Date: Sun, 3 Sep 2017 11:21:07 +0200 Subject: [PATCH 18/18] Fixed linter --- .../components/sensor/dwd_weather_warnings.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/sensor/dwd_weather_warnings.py b/homeassistant/components/sensor/dwd_weather_warnings.py index dc40a5e56f35aa..0eeaa9424e8228 100644 --- a/homeassistant/components/sensor/dwd_weather_warnings.py +++ b/homeassistant/components/sensor/dwd_weather_warnings.py @@ -107,9 +107,10 @@ def state(self): @property def device_state_attributes(self): """Return the state attributes of the DWD-Weather-Warnings.""" - data = {} - data[ATTR_ATTRIBUTION] = ATTRIBUTION - data['region_name'] = self._api.region_name + data = { + ATTR_ATTRIBUTION: ATTRIBUTION, + 'region_name': self._api.region_name + } if self._api.region_id is not None: data['region_id'] = self._api.region_id @@ -125,6 +126,8 @@ def device_state_attributes(self): prefix = 'current' elif self._var_id == 'advance_warning_level': prefix = 'advance' + else: + raise Exception('Unknown warning type') data['warning_count'] = self._api.data[prefix + '_warning_count'] i = 0 @@ -166,7 +169,6 @@ class DwdWeatherWarningsAPI(object): def __init__(self, region_name): """Initialize the data object.""" - resource = "{}{}{}?{}".format( 'https://', 'www.dwd.de', @@ -191,9 +193,7 @@ def update(self): json_string = self._rest.data[24:len(self._rest.data) - 2] json_obj = json.loads(json_string) - data = {} - - data['time'] = json_obj['time'] + data = {'time': json_obj['time']} for mykey, myvalue in { 'current': 'warnings',