Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Environment Canada platforms #24884

Merged
merged 12 commits into from Jul 13, 2019
10 changes: 3 additions & 7 deletions homeassistant/components/environment_canada/camera.py
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/environment_canada/manifest.json
Expand Up @@ -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": [
Expand Down
134 changes: 57 additions & 77 deletions homeassistant/components/environment_canada/sensor.py
Expand Up @@ -4,19 +4,18 @@
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

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__)
Expand All @@ -28,43 +27,9 @@

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):
Expand All @@ -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'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we ok with this config option? @balloob?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be happy to pull this value from the front end configuration, if that's possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On sensor, yes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But yeah, we should add a core language config flag

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))
michaeldavie marked this conversation as resolved.
Show resolved Hide resolved

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):
Expand All @@ -137,42 +108,51 @@ def device_state_attributes(self):
@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):
"""Update current conditions."""
self.ec_data.update()
self.ec_data.conditions.update(self.ec_data.alerts)

conditions = self.ec_data.conditions
metadata = self.ec_data.metadata
sensor_data = conditions.get(self.sensor_type)

self._unique_id = '{}-{}'.format(metadata['location'],
self.sensor_type)
self._attr = {}
self._name = sensor_data.get('label')
value = sensor_data.get('value')

sensor_data = self.ec_data.conditions.get(self.sensor_type)
if isinstance(sensor_data, list):
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'),
})
49 changes: 26 additions & 23 deletions homeassistant/components/environment_canada/weather.py
Expand Up @@ -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)])

Expand All @@ -96,13 +94,15 @@ def name(self):
"""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
Expand All @@ -113,48 +113,51 @@ def temperature_unit(self):
@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):
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Expand Up @@ -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
Expand Down