mirror of
https://github.com/home-assistant/core
synced 2024-09-25 00:41:32 +02:00
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:
parent
1e474bb5da
commit
a147a189ca
@ -45,14 +45,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
if config.get(CONF_STATION):
|
||||
radar_object = ECRadar(station_id=config[CONF_STATION],
|
||||
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:
|
||||
radar_object = ECRadar(coordinates=(hass.config.latitude,
|
||||
hass.config.longitude),
|
||||
precip_type=config.get(CONF_PRECIP_TYPE))
|
||||
lat = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
lon = config.get(CONF_LONGITUDE, hass.config.longitude)
|
||||
radar_object = ECRadar(coordinates=(lat, lon))
|
||||
|
||||
add_devices([ECCamera(radar_object, config.get(CONF_NAME))], True)
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Environment Canada",
|
||||
"documentation": "https://www.home-assistant.io/components/environment_canada",
|
||||
"requirements": [
|
||||
"env_canada==0.0.10"
|
||||
"env_canada==0.0.18"
|
||||
],
|
||||
"dependencies": [],
|
||||
"codeowners": [
|
||||
|
@ -4,7 +4,7 @@ Support for the Environment Canada weather service.
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/sensor.environment_canada/
|
||||
"""
|
||||
import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
import re
|
||||
|
||||
@ -12,11 +12,10 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||
from homeassistant.const import (
|
||||
CONF_MONITORED_CONDITIONS, TEMP_CELSIUS, CONF_NAME, CONF_LATITUDE,
|
||||
CONF_LONGITUDE, ATTR_ATTRIBUTION, ATTR_LOCATION, ATTR_HIDDEN)
|
||||
TEMP_CELSIUS, CONF_LATITUDE, CONF_LONGITUDE, ATTR_ATTRIBUTION,
|
||||
ATTR_LOCATION)
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
import homeassistant.util.dt as dt
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -28,43 +27,9 @@ ATTR_TIME = 'alert time'
|
||||
|
||||
CONF_ATTRIBUTION = "Data provided by Environment Canada"
|
||||
CONF_STATION = 'station'
|
||||
CONF_LANGUAGE = 'language'
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = datetime.timedelta(minutes=10)
|
||||
|
||||
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'}
|
||||
}
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
|
||||
|
||||
|
||||
def validate_station(station):
|
||||
@ -77,52 +42,58 @@ def validate_station(station):
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)):
|
||||
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Required(CONF_LANGUAGE, default='english'):
|
||||
vol.In(['english', 'french']),
|
||||
vol.Optional(CONF_STATION): validate_station,
|
||||
vol.Inclusive(CONF_LATITUDE, 'latlon'): cv.latitude,
|
||||
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."""
|
||||
from env_canada import ECData
|
||||
|
||||
if config.get(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]))
|
||||
ec_data = ECData(station_id=config[CONF_STATION],
|
||||
language=config.get(CONF_LANGUAGE))
|
||||
else:
|
||||
ec_data = ECData(coordinates=(hass.config.latitude,
|
||||
hass.config.longitude))
|
||||
lat = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
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))
|
||||
for sensor_type in config[CONF_MONITORED_CONDITIONS]],
|
||||
True)
|
||||
sensor_list = list(ec_data.conditions.keys()) + list(ec_data.alerts.keys())
|
||||
sensor_list.remove('icon_code')
|
||||
add_entities([ECSensor(sensor_type,
|
||||
ec_data)
|
||||
for sensor_type in sensor_list],
|
||||
True)
|
||||
|
||||
|
||||
class ECSensor(Entity):
|
||||
"""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."""
|
||||
self.sensor_type = sensor_type
|
||||
self.ec_data = ec_data
|
||||
self.platform_name = platform_name
|
||||
|
||||
self._unique_id = None
|
||||
self._name = None
|
||||
self._state = 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
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
if self.platform_name is None:
|
||||
return SENSOR_TYPES[self.sensor_type]['name']
|
||||
|
||||
return ' '.join([self.platform_name,
|
||||
SENSOR_TYPES[self.sensor_type]['name']])
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
@ -137,7 +108,7 @@ class ECSensor(Entity):
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the units of measurement."""
|
||||
return SENSOR_TYPES[self.sensor_type].get('unit')
|
||||
return self._unit
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
@ -145,34 +116,43 @@ class ECSensor(Entity):
|
||||
self.ec_data.update()
|
||||
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)
|
||||
if isinstance(sensor_data, list):
|
||||
self._unique_id = '{}-{}'.format(metadata['location'],
|
||||
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'))
|
||||
for s in sensor_data])
|
||||
for s in value])
|
||||
self._attr.update({
|
||||
ATTR_DETAIL: ' | '.join([str(s.get('detail'))
|
||||
for s in sensor_data]),
|
||||
for s in value]),
|
||||
ATTR_TIME: ' | '.join([str(s.get('date'))
|
||||
for s in sensor_data])
|
||||
for s in value])
|
||||
})
|
||||
else:
|
||||
self._state = sensor_data
|
||||
self._state = value
|
||||
|
||||
timestamp = self.ec_data.conditions.get('timestamp')
|
||||
if timestamp:
|
||||
updated_utc = datetime.datetime.strptime(timestamp, '%Y%m%d%H%M%S')
|
||||
updated_local = dt.as_local(updated_utc).isoformat()
|
||||
if sensor_data.get('unit') == 'C':
|
||||
self._unit = TEMP_CELSIUS
|
||||
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({
|
||||
ATTR_ATTRIBUTION: CONF_ATTRIBUTION,
|
||||
ATTR_UPDATED: updated_local,
|
||||
ATTR_LOCATION: self.ec_data.conditions.get('location'),
|
||||
ATTR_STATION: self.ec_data.conditions.get('station'),
|
||||
ATTR_HIDDEN: hidden
|
||||
ATTR_UPDATED: updated_utc,
|
||||
ATTR_LOCATION: metadata.get('location'),
|
||||
ATTR_STATION: metadata.get('station'),
|
||||
})
|
||||
|
@ -67,12 +67,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up the Environment Canada weather."""
|
||||
if config.get(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:
|
||||
ec_data = ECData(coordinates=(hass.config.latitude,
|
||||
hass.config.longitude))
|
||||
lat = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
lon = config.get(CONF_LONGITUDE, hass.config.longitude)
|
||||
ec_data = ECData(coordinates=(lat, lon))
|
||||
|
||||
add_devices([ECWeather(ec_data, config)])
|
||||
|
||||
@ -96,13 +94,15 @@ class ECWeather(WeatherEntity):
|
||||
"""Return the name of the weather entity."""
|
||||
if self.platform_name:
|
||||
return self.platform_name
|
||||
return self.ec_data.conditions['location']
|
||||
return self.ec_data.metadata.get('location')
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
"""Return the temperature."""
|
||||
if self.ec_data.conditions.get('temperature'):
|
||||
return float(self.ec_data.conditions['temperature'])
|
||||
if self.ec_data.conditions.get('temperature').get('value'):
|
||||
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
|
||||
|
||||
@property
|
||||
@ -113,48 +113,51 @@ class ECWeather(WeatherEntity):
|
||||
@property
|
||||
def humidity(self):
|
||||
"""Return the humidity."""
|
||||
if self.ec_data.conditions.get('humidity'):
|
||||
return float(self.ec_data.conditions['humidity'])
|
||||
if self.ec_data.conditions.get('humidity').get('value'):
|
||||
return float(self.ec_data.conditions['humidity']['value'])
|
||||
return None
|
||||
|
||||
@property
|
||||
def wind_speed(self):
|
||||
"""Return the wind speed."""
|
||||
if self.ec_data.conditions.get('wind_speed'):
|
||||
return float(self.ec_data.conditions['wind_speed'])
|
||||
if self.ec_data.conditions.get('wind_speed').get('value'):
|
||||
return float(self.ec_data.conditions['wind_speed']['value'])
|
||||
return None
|
||||
|
||||
@property
|
||||
def wind_bearing(self):
|
||||
"""Return the wind bearing."""
|
||||
if self.ec_data.conditions.get('wind_bearing'):
|
||||
return float(self.ec_data.conditions['wind_bearing'])
|
||||
if self.ec_data.conditions.get('wind_bearing').get('value'):
|
||||
return float(self.ec_data.conditions['wind_bearing']['value'])
|
||||
return None
|
||||
|
||||
@property
|
||||
def pressure(self):
|
||||
"""Return the pressure."""
|
||||
if self.ec_data.conditions.get('pressure'):
|
||||
return 10 * float(self.ec_data.conditions['pressure'])
|
||||
if self.ec_data.conditions.get('pressure').get('value'):
|
||||
return 10 * float(self.ec_data.conditions['pressure']['value'])
|
||||
return None
|
||||
|
||||
@property
|
||||
def visibility(self):
|
||||
"""Return the visibility."""
|
||||
if self.ec_data.conditions.get('visibility'):
|
||||
return float(self.ec_data.conditions['visibility'])
|
||||
if self.ec_data.conditions.get('visibility').get('value'):
|
||||
return float(self.ec_data.conditions['visibility']['value'])
|
||||
return None
|
||||
|
||||
@property
|
||||
def condition(self):
|
||||
"""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:
|
||||
return icon_code_to_condition(int(icon_code))
|
||||
condition = self.ec_data.conditions.get('condition')
|
||||
if condition:
|
||||
return condition
|
||||
return 'Condition not observed'
|
||||
return ''
|
||||
|
||||
@property
|
||||
def forecast(self):
|
||||
|
@ -430,7 +430,7 @@ enocean==0.50
|
||||
enturclient==0.2.0
|
||||
|
||||
# homeassistant.components.environment_canada
|
||||
env_canada==0.0.10
|
||||
env_canada==0.0.18
|
||||
|
||||
# homeassistant.components.envirophat
|
||||
# envirophat==0.0.6
|
||||
|
Loading…
Reference in New Issue
Block a user