From e2408cc804e5cdd0408f9bfd20c59f0c14f3dce0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 13 Feb 2018 22:03:06 -0800 Subject: [PATCH 1/6] Version bump to 0.63.2 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 6af7b885561..917292648c9 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 63 -PATCH_VERSION = '1' +PATCH_VERSION = '2' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) From e5f000f976c712e3639044bb2e4cc95976a64c5d Mon Sep 17 00:00:00 2001 From: Rene Nulsch <33263735+ReneNulschDE@users.noreply.github.com> Date: Tue, 13 Feb 2018 06:07:20 +0100 Subject: [PATCH 2/6] Fix MercedesMe - add check for unsupported features (#12342) * Add check for unsupported features * Lint fix * change to guard clause --- homeassistant/components/binary_sensor/mercedesme.py | 9 ++++++--- homeassistant/components/device_tracker/mercedesme.py | 7 +++++-- homeassistant/components/mercedesme.py | 2 ++ homeassistant/components/sensor/mercedesme.py | 10 +++++++--- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/binary_sensor/mercedesme.py b/homeassistant/components/binary_sensor/mercedesme.py index a6c8da56ce8..fcf2d7122e2 100644 --- a/homeassistant/components/binary_sensor/mercedesme.py +++ b/homeassistant/components/binary_sensor/mercedesme.py @@ -9,7 +9,7 @@ import datetime from homeassistant.components.binary_sensor import (BinarySensorDevice) from homeassistant.components.mercedesme import ( - DATA_MME, MercedesMeEntity, BINARY_SENSORS) + DATA_MME, FEATURE_NOT_AVAILABLE, MercedesMeEntity, BINARY_SENSORS) DEPENDENCIES = ['mercedesme'] @@ -27,8 +27,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None): devices = [] for car in data.cars: for key, value in sorted(BINARY_SENSORS.items()): - devices.append(MercedesMEBinarySensor( - data, key, value[0], car["vin"], None)) + if car['availabilities'].get(key, 'INVALID') == 'VALID': + devices.append(MercedesMEBinarySensor( + data, key, value[0], car["vin"], None)) + else: + _LOGGER.warning(FEATURE_NOT_AVAILABLE, key, car["license"]) add_devices(devices, True) diff --git a/homeassistant/components/device_tracker/mercedesme.py b/homeassistant/components/device_tracker/mercedesme.py index 0aa2be96290..dcc9e3ab2ec 100644 --- a/homeassistant/components/device_tracker/mercedesme.py +++ b/homeassistant/components/device_tracker/mercedesme.py @@ -49,10 +49,13 @@ class MercedesMEDeviceTracker(object): def update_info(self, now=None): """Update the device info.""" for device in self.data.cars: - _LOGGER.debug("Updating %s", device["vin"]) + if not device['services'].get('VEHICLE_FINDER', False): + continue + location = self.data.get_location(device["vin"]) if location is None: - return False + continue + dev_id = device["vin"] name = device["license"] diff --git a/homeassistant/components/mercedesme.py b/homeassistant/components/mercedesme.py index a228486e2c8..b809e46ec64 100644 --- a/homeassistant/components/mercedesme.py +++ b/homeassistant/components/mercedesme.py @@ -41,6 +41,8 @@ SENSORS = { DATA_MME = 'mercedesme' DOMAIN = 'mercedesme' +FEATURE_NOT_AVAILABLE = "The feature %s is not available for your car %s" + NOTIFICATION_ID = 'mercedesme_integration_notification' NOTIFICATION_TITLE = 'Mercedes me integration setup' diff --git a/homeassistant/components/sensor/mercedesme.py b/homeassistant/components/sensor/mercedesme.py index bc368745e40..bb7212678a7 100644 --- a/homeassistant/components/sensor/mercedesme.py +++ b/homeassistant/components/sensor/mercedesme.py @@ -8,7 +8,7 @@ import logging import datetime from homeassistant.components.mercedesme import ( - DATA_MME, MercedesMeEntity, SENSORS) + DATA_MME, FEATURE_NOT_AVAILABLE, MercedesMeEntity, SENSORS) DEPENDENCIES = ['mercedesme'] @@ -29,8 +29,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): devices = [] for car in data.cars: for key, value in sorted(SENSORS.items()): - devices.append( - MercedesMESensor(data, key, value[0], car["vin"], value[1])) + if car['availabilities'].get(key, 'INVALID') == 'VALID': + devices.append( + MercedesMESensor( + data, key, value[0], car["vin"], value[1])) + else: + _LOGGER.warning(FEATURE_NOT_AVAILABLE, key, car["license"]) add_devices(devices, True) From 9e4da3702248106bc8f15e9d19a0b1ce754a21b9 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Mon, 12 Feb 2018 22:15:28 +0100 Subject: [PATCH 3/6] Fix WUnderground names (#12346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 📝 Fix WUnderground names * 👻 Fix using event loop callback --- .../components/sensor/wunderground.py | 19 +++++++------- tests/components/sensor/test_wunderground.py | 26 +++++++++++++------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index d0d9758c13a..aa5d431a7b0 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -11,14 +11,14 @@ import re import requests import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.helpers.typing import HomeAssistantType +from homeassistant.components.sensor import PLATFORM_SCHEMA, ENTITY_ID_FORMAT from homeassistant.const import ( CONF_MONITORED_CONDITIONS, CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, TEMP_FAHRENHEIT, TEMP_CELSIUS, LENGTH_INCHES, LENGTH_KILOMETERS, - LENGTH_MILES, LENGTH_FEET, STATE_UNKNOWN, ATTR_ATTRIBUTION, - ATTR_FRIENDLY_NAME) + LENGTH_MILES, LENGTH_FEET, STATE_UNKNOWN, ATTR_ATTRIBUTION) from homeassistant.exceptions import PlatformNotReady -from homeassistant.helpers.entity import Entity +from homeassistant.helpers.entity import Entity, generate_entity_id from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv @@ -637,7 +637,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): config.get(CONF_LANG), latitude, longitude) sensors = [] for variable in config[CONF_MONITORED_CONDITIONS]: - sensors.append(WUndergroundSensor(rest, variable)) + sensors.append(WUndergroundSensor(hass, rest, variable)) rest.update() if not rest.data: @@ -651,7 +651,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class WUndergroundSensor(Entity): """Implementing the WUnderground sensor.""" - def __init__(self, rest, condition): + def __init__(self, hass: HomeAssistantType, rest, condition): """Initialize the sensor.""" self.rest = rest self._condition = condition @@ -663,6 +663,8 @@ class WUndergroundSensor(Entity): self._entity_picture = None self._unit_of_measurement = self._cfg_expand("unit_of_measurement") self.rest.request_feature(SENSOR_TYPES[condition].feature) + self.entity_id = generate_entity_id( + ENTITY_ID_FORMAT, "pws_" + condition, hass=hass) def _cfg_expand(self, what, default=None): """Parse and return sensor data.""" @@ -684,9 +686,6 @@ class WUndergroundSensor(Entity): """Parse and update device state attributes.""" attrs = self._cfg_expand("device_state_attributes", {}) - self._attributes[ATTR_FRIENDLY_NAME] = self._cfg_expand( - "friendly_name") - for (attr, callback) in attrs.items(): if callable(callback): try: @@ -701,7 +700,7 @@ class WUndergroundSensor(Entity): @property def name(self): """Return the name of the sensor.""" - return "PWS_" + self._condition + return self._cfg_expand("friendly_name") @property def state(self): diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py index 5f6028b1a14..c1508f49851 100644 --- a/tests/components/sensor/test_wunderground.py +++ b/tests/components/sensor/test_wunderground.py @@ -249,31 +249,41 @@ class TestWundergroundSetup(unittest.TestCase): None) for device in self.DEVICES: device.update() - self.assertTrue(str(device.name).startswith('PWS_')) - if device.name == 'PWS_weather': + entity_id = device.entity_id + friendly_name = device.name + self.assertTrue(entity_id.startswith('sensor.pws_')) + if entity_id == 'sensor.pws_weather': self.assertEqual(HTTPS_ICON_URL, device.entity_picture) self.assertEqual(WEATHER, device.state) self.assertIsNone(device.unit_of_measurement) - elif device.name == 'PWS_alerts': + self.assertEqual("Weather Summary", friendly_name) + elif entity_id == 'sensor.pws_alerts': self.assertEqual(1, device.state) self.assertEqual(ALERT_MESSAGE, device.device_state_attributes['Message']) self.assertEqual(ALERT_ICON, device.icon) self.assertIsNone(device.entity_picture) - elif device.name == 'PWS_location': + self.assertEqual('Alerts', friendly_name) + elif entity_id == 'sensor.pws_location': self.assertEqual('Holly Springs, NC', device.state) - elif device.name == 'PWS_elevation': + self.assertEqual('Location', friendly_name) + elif entity_id == 'sensor.pws_elevation': self.assertEqual('413', device.state) - elif device.name == 'PWS_feelslike_c': + self.assertEqual('Elevation', friendly_name) + elif entity_id == 'sensor.pws_feelslike_c': self.assertIsNone(device.entity_picture) self.assertEqual(FEELS_LIKE, device.state) self.assertEqual(TEMP_CELSIUS, device.unit_of_measurement) - elif device.name == 'PWS_weather_1d_metric': + self.assertEqual("Feels Like", friendly_name) + elif entity_id == 'sensor.pws_weather_1d_metric': self.assertEqual(FORECAST_TEXT, device.state) + self.assertEqual('Tuesday', friendly_name) else: - self.assertEqual(device.name, 'PWS_precip_1d_in') + self.assertEqual(entity_id, 'sensor.pws_precip_1d_in') self.assertEqual(PRECIP_IN, device.state) self.assertEqual(LENGTH_INCHES, device.unit_of_measurement) + self.assertEqual('Precipitation Intensity Today', + friendly_name) @unittest.mock.patch('requests.get', side_effect=ConnectionError('test exception')) From 72f100723f4cfef6febda00514d5517f72652e0b Mon Sep 17 00:00:00 2001 From: citruz Date: Tue, 13 Feb 2018 11:32:44 +0100 Subject: [PATCH 4/6] Updated beacontools (#12368) --- homeassistant/components/sensor/eddystone_temperature.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/eddystone_temperature.py b/homeassistant/components/sensor/eddystone_temperature.py index ef06458cd84..fb5fa2c1fba 100644 --- a/homeassistant/components/sensor/eddystone_temperature.py +++ b/homeassistant/components/sensor/eddystone_temperature.py @@ -18,7 +18,7 @@ from homeassistant.const import ( CONF_NAME, TEMP_CELSIUS, STATE_UNKNOWN, EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_START) -REQUIREMENTS = ['beacontools[scan]==1.0.1'] +REQUIREMENTS = ['beacontools[scan]==1.2.1'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 2a5f68791e0..9bd83bcbc69 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -118,7 +118,7 @@ basicmodem==0.7 batinfo==0.4.2 # homeassistant.components.sensor.eddystone_temperature -# beacontools[scan]==1.0.1 +# beacontools[scan]==1.2.1 # homeassistant.components.device_tracker.linksys_ap # homeassistant.components.sensor.geizhals From c414ecd4f05c871e5cd487a460a9c04b90fda60e Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Tue, 13 Feb 2018 17:24:03 -0500 Subject: [PATCH 5/6] Introduce zone_id to identify player+zone (#12382) The yamaha component previously used a property named unique_id to ensure that exactly 1 media_player was discovered per zone per control_url. This was introduced so that hard coded devices wouldn't be duplicated by automatically discovered devices. In HA 0.63 unique_id became a reserved concept as part of the new device registry, and the property was removed from the component. But the default returns None, which had the side effect of only ever registering a single unit + zone, the first one discovered. This was typically the Main_Zone of the unit, but there is actually no guaruntee of that. This fix brings back the logic under a different property called zone_id. This is not guarunteed to be globally stable like unique_id is supposed to be, but it is suitable for the deduplication for yamaha media players. --- homeassistant/components/media_player/yamaha.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/media_player/yamaha.py b/homeassistant/components/media_player/yamaha.py index f102d8a490d..5b8ac2ad236 100644 --- a/homeassistant/components/media_player/yamaha.py +++ b/homeassistant/components/media_player/yamaha.py @@ -60,7 +60,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): import rxv # Keep track of configured receivers so that we don't end up # discovering a receiver dynamically that we have static config - # for. Map each device from its unique_id to an instance since + # for. Map each device from its zone_id to an instance since # YamahaDevice is not hashable (thus not possible to add to a set). if hass.data.get(DATA_YAMAHA) is None: hass.data[DATA_YAMAHA] = {} @@ -100,8 +100,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): source_names, zone_names) # Only add device if it's not already added - if device.unique_id not in hass.data[DATA_YAMAHA]: - hass.data[DATA_YAMAHA][device.unique_id] = device + if device.zone_id not in hass.data[DATA_YAMAHA]: + hass.data[DATA_YAMAHA][device.zone_id] = device devices.append(device) else: _LOGGER.debug('Ignoring duplicate receiver %s', name) @@ -220,6 +220,11 @@ class YamahaDevice(MediaPlayerDevice): """List of available input sources.""" return self._source_list + @property + def zone_id(self): + """Return an zone_id to ensure 1 media player per zone.""" + return '{0}:{1}'.format(self.receiver.ctrl_url, self._zone) + @property def supported_features(self): """Flag media player features that are supported.""" From c82ca62820246b802cdad83abff86ae0c28f3021 Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Wed, 14 Feb 2018 07:58:31 +0100 Subject: [PATCH 6/6] Downgrade limitlessled to 1.0.8 (#12403) --- homeassistant/components/light/limitlessled.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/light/limitlessled.py b/homeassistant/components/light/limitlessled.py index 0c6b1143bbd..aad2abdd183 100644 --- a/homeassistant/components/light/limitlessled.py +++ b/homeassistant/components/light/limitlessled.py @@ -16,7 +16,7 @@ from homeassistant.components.light import ( SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['limitlessled==1.0.9'] +REQUIREMENTS = ['limitlessled==1.0.8'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 9bd83bcbc69..6c1282ce8a7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -454,7 +454,7 @@ liffylights==0.9.4 lightify==1.0.6.1 # homeassistant.components.light.limitlessled -limitlessled==1.0.9 +limitlessled==1.0.8 # homeassistant.components.linode linode-api==4.1.4b2