Update Environment Canada platforms (#24884)

* Add support for French

* Move labels to env_canada

* Bump env_canada to 0.0.17, change update frequency to 1 minute

* Update requirements_all.txt

* Set entity IDs separate from labels

* Flake error

* Remove monitored conditions

* Use next hourly forecast for missing conditions

* Switch sensors to unique_id

* Flake error

* Requested changes

* Simplify setting location parameters
This commit is contained in:
michaeldavie 2019-07-13 12:14:29 -04:00 committed by Pascal Vizeli
parent 1e474bb5da
commit a147a189ca
5 changed files with 89 additions and 110 deletions

View File

@ -45,14 +45,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
if config.get(CONF_STATION): if config.get(CONF_STATION):
radar_object = ECRadar(station_id=config[CONF_STATION], radar_object = ECRadar(station_id=config[CONF_STATION],
precip_type=config.get(CONF_PRECIP_TYPE)) precip_type=config.get(CONF_PRECIP_TYPE))
elif config.get(CONF_LATITUDE) and config.get(CONF_LONGITUDE):
radar_object = ECRadar(coordinates=(config[CONF_LATITUDE],
config[CONF_LONGITUDE]),
precip_type=config.get(CONF_PRECIP_TYPE))
else: else:
radar_object = ECRadar(coordinates=(hass.config.latitude, lat = config.get(CONF_LATITUDE, hass.config.latitude)
hass.config.longitude), lon = config.get(CONF_LONGITUDE, hass.config.longitude)
precip_type=config.get(CONF_PRECIP_TYPE)) radar_object = ECRadar(coordinates=(lat, lon))
add_devices([ECCamera(radar_object, config.get(CONF_NAME))], True) add_devices([ECCamera(radar_object, config.get(CONF_NAME))], True)

View File

@ -3,7 +3,7 @@
"name": "Environment Canada", "name": "Environment Canada",
"documentation": "https://www.home-assistant.io/components/environment_canada", "documentation": "https://www.home-assistant.io/components/environment_canada",
"requirements": [ "requirements": [
"env_canada==0.0.10" "env_canada==0.0.18"
], ],
"dependencies": [], "dependencies": [],
"codeowners": [ "codeowners": [

View File

@ -4,7 +4,7 @@ Support for the Environment Canada weather 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.environment_canada/ https://home-assistant.io/components/sensor.environment_canada/
""" """
import datetime from datetime import datetime, timedelta
import logging import logging
import re import re
@ -12,11 +12,10 @@ import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import ( from homeassistant.const import (
CONF_MONITORED_CONDITIONS, TEMP_CELSIUS, CONF_NAME, CONF_LATITUDE, TEMP_CELSIUS, CONF_LATITUDE, CONF_LONGITUDE, ATTR_ATTRIBUTION,
CONF_LONGITUDE, ATTR_ATTRIBUTION, ATTR_LOCATION, ATTR_HIDDEN) ATTR_LOCATION)
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle from homeassistant.util import Throttle
import homeassistant.util.dt as dt
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -28,43 +27,9 @@ ATTR_TIME = 'alert time'
CONF_ATTRIBUTION = "Data provided by Environment Canada" CONF_ATTRIBUTION = "Data provided by Environment Canada"
CONF_STATION = 'station' CONF_STATION = 'station'
CONF_LANGUAGE = 'language'
MIN_TIME_BETWEEN_UPDATES = datetime.timedelta(minutes=10) MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
SENSOR_TYPES = {
'temperature': {'name': 'Temperature',
'unit': TEMP_CELSIUS},
'dewpoint': {'name': 'Dew Point',
'unit': TEMP_CELSIUS},
'wind_chill': {'name': 'Wind Chill',
'unit': TEMP_CELSIUS},
'humidex': {'name': 'Humidex',
'unit': TEMP_CELSIUS},
'pressure': {'name': 'Pressure',
'unit': 'kPa'},
'tendency': {'name': 'Tendency'},
'humidity': {'name': 'Humidity',
'unit': '%'},
'visibility': {'name': 'Visibility',
'unit': 'km'},
'condition': {'name': 'Condition'},
'wind_speed': {'name': 'Wind Speed',
'unit': 'km/h'},
'wind_gust': {'name': 'Wind Gust',
'unit': 'km/h'},
'wind_dir': {'name': 'Wind Direction'},
'high_temp': {'name': 'High Temperature',
'unit': TEMP_CELSIUS},
'low_temp': {'name': 'Low Temperature',
'unit': TEMP_CELSIUS},
'pop': {'name': 'Chance of Precip.',
'unit': '%'},
'warnings': {'name': 'Warnings'},
'watches': {'name': 'Watches'},
'advisories': {'name': 'Advisories'},
'statements': {'name': 'Statements'},
'endings': {'name': 'Ended'}
}
def validate_station(station): def validate_station(station):
@ -77,52 +42,58 @@ def validate_station(station):
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)): vol.Required(CONF_LANGUAGE, default='english'):
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), vol.In(['english', 'french']),
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_STATION): validate_station, vol.Optional(CONF_STATION): validate_station,
vol.Inclusive(CONF_LATITUDE, 'latlon'): cv.latitude, vol.Inclusive(CONF_LATITUDE, 'latlon'): cv.latitude,
vol.Inclusive(CONF_LONGITUDE, 'latlon'): cv.longitude, vol.Inclusive(CONF_LONGITUDE, 'latlon'): cv.longitude,
}) })
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Environment Canada sensor.""" """Set up the Environment Canada sensor."""
from env_canada import ECData from env_canada import ECData
if config.get(CONF_STATION): if config.get(CONF_STATION):
ec_data = ECData(station_id=config[CONF_STATION]) ec_data = ECData(station_id=config[CONF_STATION],
elif config.get(CONF_LATITUDE) and config.get(CONF_LONGITUDE): language=config.get(CONF_LANGUAGE))
ec_data = ECData(coordinates=(config[CONF_LATITUDE],
config[CONF_LONGITUDE]))
else: else:
ec_data = ECData(coordinates=(hass.config.latitude, lat = config.get(CONF_LATITUDE, hass.config.latitude)
hass.config.longitude)) lon = config.get(CONF_LONGITUDE, hass.config.longitude)
ec_data = ECData(coordinates=(lat, lon),
language=config.get(CONF_LANGUAGE))
add_devices([ECSensor(sensor_type, ec_data, config.get(CONF_NAME)) sensor_list = list(ec_data.conditions.keys()) + list(ec_data.alerts.keys())
for sensor_type in config[CONF_MONITORED_CONDITIONS]], sensor_list.remove('icon_code')
True) add_entities([ECSensor(sensor_type,
ec_data)
for sensor_type in sensor_list],
True)
class ECSensor(Entity): class ECSensor(Entity):
"""Implementation of an Environment Canada sensor.""" """Implementation of an Environment Canada sensor."""
def __init__(self, sensor_type, ec_data, platform_name): def __init__(self, sensor_type, ec_data):
"""Initialize the sensor.""" """Initialize the sensor."""
self.sensor_type = sensor_type self.sensor_type = sensor_type
self.ec_data = ec_data self.ec_data = ec_data
self.platform_name = platform_name
self._unique_id = None
self._name = None
self._state = None self._state = None
self._attr = None self._attr = None
self._unit = None
@property
def unique_id(self) -> str:
"""Return the unique ID of the sensor."""
return self._unique_id
@property @property
def name(self): def name(self):
"""Return the name of the sensor.""" """Return the name of the sensor."""
if self.platform_name is None: return self._name
return SENSOR_TYPES[self.sensor_type]['name']
return ' '.join([self.platform_name,
SENSOR_TYPES[self.sensor_type]['name']])
@property @property
def state(self): def state(self):
@ -137,7 +108,7 @@ class ECSensor(Entity):
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the units of measurement.""" """Return the units of measurement."""
return SENSOR_TYPES[self.sensor_type].get('unit') return self._unit
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self): def update(self):
@ -145,34 +116,43 @@ class ECSensor(Entity):
self.ec_data.update() self.ec_data.update()
self.ec_data.conditions.update(self.ec_data.alerts) self.ec_data.conditions.update(self.ec_data.alerts)
self._attr = {} conditions = self.ec_data.conditions
metadata = self.ec_data.metadata
sensor_data = conditions.get(self.sensor_type)
sensor_data = self.ec_data.conditions.get(self.sensor_type) self._unique_id = '{}-{}'.format(metadata['location'],
if isinstance(sensor_data, list): self.sensor_type)
self._attr = {}
self._name = sensor_data.get('label')
value = sensor_data.get('value')
if isinstance(value, list):
self._state = ' | '.join([str(s.get('title')) self._state = ' | '.join([str(s.get('title'))
for s in sensor_data]) for s in value])
self._attr.update({ self._attr.update({
ATTR_DETAIL: ' | '.join([str(s.get('detail')) ATTR_DETAIL: ' | '.join([str(s.get('detail'))
for s in sensor_data]), for s in value]),
ATTR_TIME: ' | '.join([str(s.get('date')) ATTR_TIME: ' | '.join([str(s.get('date'))
for s in sensor_data]) for s in value])
}) })
else: else:
self._state = sensor_data self._state = value
timestamp = self.ec_data.conditions.get('timestamp') if sensor_data.get('unit') == 'C':
if timestamp: self._unit = TEMP_CELSIUS
updated_utc = datetime.datetime.strptime(timestamp, '%Y%m%d%H%M%S')
updated_local = dt.as_local(updated_utc).isoformat()
else: else:
updated_local = None self._unit = sensor_data.get('unit')
hidden = bool(self._state is None or self._state == '') timestamp = metadata.get('timestamp')
if timestamp:
updated_utc = datetime.strptime(timestamp,
'%Y%m%d%H%M%S').isoformat()
else:
updated_utc = None
self._attr.update({ self._attr.update({
ATTR_ATTRIBUTION: CONF_ATTRIBUTION, ATTR_ATTRIBUTION: CONF_ATTRIBUTION,
ATTR_UPDATED: updated_local, ATTR_UPDATED: updated_utc,
ATTR_LOCATION: self.ec_data.conditions.get('location'), ATTR_LOCATION: metadata.get('location'),
ATTR_STATION: self.ec_data.conditions.get('station'), ATTR_STATION: metadata.get('station'),
ATTR_HIDDEN: hidden
}) })

View File

@ -67,12 +67,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Environment Canada weather.""" """Set up the Environment Canada weather."""
if config.get(CONF_STATION): if config.get(CONF_STATION):
ec_data = ECData(station_id=config[CONF_STATION]) ec_data = ECData(station_id=config[CONF_STATION])
elif config.get(CONF_LATITUDE) and config.get(CONF_LONGITUDE):
ec_data = ECData(coordinates=(config[CONF_LATITUDE],
config[CONF_LONGITUDE]))
else: else:
ec_data = ECData(coordinates=(hass.config.latitude, lat = config.get(CONF_LATITUDE, hass.config.latitude)
hass.config.longitude)) lon = config.get(CONF_LONGITUDE, hass.config.longitude)
ec_data = ECData(coordinates=(lat, lon))
add_devices([ECWeather(ec_data, config)]) add_devices([ECWeather(ec_data, config)])
@ -96,13 +94,15 @@ class ECWeather(WeatherEntity):
"""Return the name of the weather entity.""" """Return the name of the weather entity."""
if self.platform_name: if self.platform_name:
return self.platform_name return self.platform_name
return self.ec_data.conditions['location'] return self.ec_data.metadata.get('location')
@property @property
def temperature(self): def temperature(self):
"""Return the temperature.""" """Return the temperature."""
if self.ec_data.conditions.get('temperature'): if self.ec_data.conditions.get('temperature').get('value'):
return float(self.ec_data.conditions['temperature']) return float(self.ec_data.conditions['temperature']['value'])
if self.ec_data.hourly_forecasts[0].get('temperature'):
return float(self.ec_data.hourly_forecasts[0]['temperature'])
return None return None
@property @property
@ -113,48 +113,51 @@ class ECWeather(WeatherEntity):
@property @property
def humidity(self): def humidity(self):
"""Return the humidity.""" """Return the humidity."""
if self.ec_data.conditions.get('humidity'): if self.ec_data.conditions.get('humidity').get('value'):
return float(self.ec_data.conditions['humidity']) return float(self.ec_data.conditions['humidity']['value'])
return None return None
@property @property
def wind_speed(self): def wind_speed(self):
"""Return the wind speed.""" """Return the wind speed."""
if self.ec_data.conditions.get('wind_speed'): if self.ec_data.conditions.get('wind_speed').get('value'):
return float(self.ec_data.conditions['wind_speed']) return float(self.ec_data.conditions['wind_speed']['value'])
return None return None
@property @property
def wind_bearing(self): def wind_bearing(self):
"""Return the wind bearing.""" """Return the wind bearing."""
if self.ec_data.conditions.get('wind_bearing'): if self.ec_data.conditions.get('wind_bearing').get('value'):
return float(self.ec_data.conditions['wind_bearing']) return float(self.ec_data.conditions['wind_bearing']['value'])
return None return None
@property @property
def pressure(self): def pressure(self):
"""Return the pressure.""" """Return the pressure."""
if self.ec_data.conditions.get('pressure'): if self.ec_data.conditions.get('pressure').get('value'):
return 10 * float(self.ec_data.conditions['pressure']) return 10 * float(self.ec_data.conditions['pressure']['value'])
return None return None
@property @property
def visibility(self): def visibility(self):
"""Return the visibility.""" """Return the visibility."""
if self.ec_data.conditions.get('visibility'): if self.ec_data.conditions.get('visibility').get('value'):
return float(self.ec_data.conditions['visibility']) return float(self.ec_data.conditions['visibility']['value'])
return None return None
@property @property
def condition(self): def condition(self):
"""Return the weather condition.""" """Return the weather condition."""
icon_code = self.ec_data.conditions.get('icon_code') icon_code = None
if self.ec_data.conditions.get('icon_code').get('value'):
icon_code = self.ec_data.conditions['icon_code']['value']
elif self.ec_data.hourly_forecasts[0].get('icon_code'):
icon_code = self.ec_data.hourly_forecasts[0]['icon_code']
if icon_code: if icon_code:
return icon_code_to_condition(int(icon_code)) return icon_code_to_condition(int(icon_code))
condition = self.ec_data.conditions.get('condition') return ''
if condition:
return condition
return 'Condition not observed'
@property @property
def forecast(self): def forecast(self):

View File

@ -430,7 +430,7 @@ enocean==0.50
enturclient==0.2.0 enturclient==0.2.0
# homeassistant.components.environment_canada # homeassistant.components.environment_canada
env_canada==0.0.10 env_canada==0.0.18
# homeassistant.components.envirophat # homeassistant.components.envirophat
# envirophat==0.0.6 # envirophat==0.0.6