From 39749952eeaa08b6d5546e97541c5cf6a6e01ccc Mon Sep 17 00:00:00 2001 From: Andrew Sayre <6730289+andrewsayre@users.noreply.github.com> Date: Fri, 8 Mar 2019 23:20:07 -0600 Subject: [PATCH 1/5] Update dependencies to receive data on webhook callbacks (#21838) --- homeassistant/components/smartthings/__init__.py | 9 ++++++--- requirements_all.txt | 4 ++-- requirements_test_all.txt | 4 ++-- tests/components/smartthings/conftest.py | 3 ++- tests/components/smartthings/test_init.py | 16 ++++++++++++---- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/smartthings/__init__.py b/homeassistant/components/smartthings/__init__.py index 64e717cbc92..88035e3cc79 100644 --- a/homeassistant/components/smartthings/__init__.py +++ b/homeassistant/components/smartthings/__init__.py @@ -27,7 +27,7 @@ from .smartapp import ( setup_smartapp, setup_smartapp_endpoint, smartapp_sync_subscriptions, validate_installed_app) -REQUIREMENTS = ['pysmartapp==0.3.0', 'pysmartthings==0.6.3'] +REQUIREMENTS = ['pysmartapp==0.3.1', 'pysmartthings==0.6.7'] DEPENDENCIES = ['webhook'] _LOGGER = logging.getLogger(__name__) @@ -290,7 +290,8 @@ class DeviceBroker: if not device: continue device.status.apply_attribute_update( - evt.component_id, evt.capability, evt.attribute, evt.value) + evt.component_id, evt.capability, evt.attribute, evt.value, + data=evt.data) # Fire events for buttons if evt.capability == Capability.button and \ @@ -300,7 +301,8 @@ class DeviceBroker: 'device_id': evt.device_id, 'location_id': evt.location_id, 'value': evt.value, - 'name': device.label + 'name': device.label, + 'data': evt.data } self._hass.bus.async_fire(EVENT_BUTTON, data) _LOGGER.debug("Fired button event: %s", data) @@ -312,6 +314,7 @@ class DeviceBroker: 'capability': evt.capability, 'attribute': evt.attribute, 'value': evt.value, + 'data': evt.data } _LOGGER.debug("Push update received: %s", data) diff --git a/requirements_all.txt b/requirements_all.txt index 765bf4d0e35..aa1f78ab701 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1256,10 +1256,10 @@ pysher==1.0.1 pysma==0.3.1 # homeassistant.components.smartthings -pysmartapp==0.3.0 +pysmartapp==0.3.1 # homeassistant.components.smartthings -pysmartthings==0.6.3 +pysmartthings==0.6.7 # homeassistant.components.device_tracker.snmp # homeassistant.components.sensor.snmp diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 7f69e2a500a..073768d0cf2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -224,10 +224,10 @@ pyps4-homeassistant==0.3.0 pyqwikswitch==0.8 # homeassistant.components.smartthings -pysmartapp==0.3.0 +pysmartapp==0.3.1 # homeassistant.components.smartthings -pysmartthings==0.6.3 +pysmartthings==0.6.7 # homeassistant.components.sonos pysonos==0.0.8 diff --git a/tests/components/smartthings/conftest.py b/tests/components/smartthings/conftest.py index 27e833bff25..67c35ba8232 100644 --- a/tests/components/smartthings/conftest.py +++ b/tests/components/smartthings/conftest.py @@ -326,7 +326,7 @@ def scene_fixture(scene_factory): def event_factory_fixture(): """Fixture for creating mock devices.""" def _factory(device_id, event_type="DEVICE_EVENT", capability='', - attribute='Updated', value='Value'): + attribute='Updated', value='Value', data=None): event = Mock() event.event_type = event_type event.device_id = device_id @@ -334,6 +334,7 @@ def event_factory_fixture(): event.capability = capability event.attribute = attribute event.value = value + event.data = data event.location_id = str(uuid4()) return event return _factory diff --git a/tests/components/smartthings/test_init.py b/tests/components/smartthings/test_init.py index ec0b3982517..1f648c7716a 100644 --- a/tests/components/smartthings/test_init.py +++ b/tests/components/smartthings/test_init.py @@ -235,16 +235,21 @@ async def test_broker_regenerates_token( async def test_event_handler_dispatches_updated_devices( - hass, config_entry, device_factory, event_request_factory): + hass, config_entry, device_factory, event_request_factory, + event_factory): """Test the event handler dispatches updated devices.""" devices = [ device_factory('Bedroom 1 Switch', ['switch']), device_factory('Bathroom 1', ['switch']), device_factory('Sensor', ['motionSensor']), + device_factory('Lock', ['lock']) ] device_ids = [devices[0].device_id, devices[1].device_id, - devices[2].device_id] - request = event_request_factory(device_ids) + devices[2].device_id, devices[3].device_id] + event = event_factory(devices[3].device_id, capability='lock', + attribute='lock', value='locked', + data={'codeId': '1'}) + request = event_request_factory(device_ids=device_ids, events=[event]) config_entry.data[CONF_INSTALLED_APP_ID] = request.installed_app_id called = False @@ -265,6 +270,8 @@ async def test_event_handler_dispatches_updated_devices( assert called for device in devices: assert device.status.values['Updated'] == 'Value' + assert devices[3].status.attributes['lock'].value == 'locked' + assert devices[3].status.attributes['lock'].data == {'codeId': '1'} async def test_event_handler_ignores_other_installed_app( @@ -308,7 +315,8 @@ async def test_event_handler_fires_button_events( 'device_id': device.device_id, 'location_id': event.location_id, 'value': 'pushed', - 'name': device.label + 'name': device.label, + 'data': None } hass.bus.async_listen(EVENT_BUTTON, handler) broker = smartthings.DeviceBroker( From 1b4905ae5a5b1df36a854b8cba91838a101fae13 Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Fri, 8 Mar 2019 23:56:37 -0800 Subject: [PATCH 2/5] Override http.trusted_networks by auth_provider.trusted_networks (#21844) --- homeassistant/components/http/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index 4928ae2ab17..93afbc04396 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -211,6 +211,14 @@ class HomeAssistantHTTP: "legacy_api_password support has been enabled. If you don't " "require it, remove the 'api_password' from your http config.") + for prv in hass.auth.auth_providers: + if prv.type == 'trusted_networks': + # auth_provider.trusted_networks will override + # http.trusted_networks, http.trusted_networks will be + # removed from future release + trusted_networks = prv.trusted_networks + break + setup_auth(app, trusted_networks, api_password if hass.auth.support_legacy else None) From 00d01865cf0b06100d119ae94eaf7ede9906a15d Mon Sep 17 00:00:00 2001 From: Daniel Shokouhi Date: Sat, 9 Mar 2019 14:06:35 -0800 Subject: [PATCH 3/5] Fix botvac when no map exists (#21877) --- homeassistant/components/neato/vacuum.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/neato/vacuum.py b/homeassistant/components/neato/vacuum.py index 990c79552b4..2f2f3904947 100644 --- a/homeassistant/components/neato/vacuum.py +++ b/homeassistant/components/neato/vacuum.py @@ -187,10 +187,12 @@ class NeatoConnectedVacuum(StateVacuumDevice): if self._robot_has_map: if self._state['availableServices']['maps'] != "basic-1": - robot_map_id = self._robot_maps[self._robot_serial][0]['id'] + if self._robot_maps[self._robot_serial]: + robot_map_id = ( + self._robot_maps[self._robot_serial][0]['id']) - self._robot_boundaries = self.robot.get_map_boundaries( - robot_map_id).json() + self._robot_boundaries = self.robot.get_map_boundaries( + robot_map_id).json() @property def name(self): From 1f3e4c5776d1d2b05b6f0934f1d7aa0b3bc729ef Mon Sep 17 00:00:00 2001 From: Klaudiusz Staniek Date: Mon, 11 Mar 2019 21:27:41 +0100 Subject: [PATCH 4/5] Fixes issues #21821 and #21819 (#21911) * Fix #21821 * datetime fix * local time to utc conversion fix * Test cases update * date import removed * Update tod.py --- homeassistant/components/binary_sensor/tod.py | 20 ++++--- tests/components/binary_sensor/test_tod.py | 59 ++++++++++--------- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/binary_sensor/tod.py b/homeassistant/components/binary_sensor/tod.py index 7dc6e5ebe81..8e29bbd4678 100644 --- a/homeassistant/components/binary_sensor/tod.py +++ b/homeassistant/components/binary_sensor/tod.py @@ -119,6 +119,17 @@ class TodSensor(BinarySensorDevice): self.hass.config.time_zone).isoformat(), } + def _naive_time_to_utc_datetime(self, naive_time): + """Convert naive time from config to utc_datetime with current day.""" + # get the current local date from utc time + current_local_date = self.current_datetime.astimezone( + self.hass.config.time_zone).date() + # calcuate utc datetime corecponding to local time + utc_datetime = self.hass.config.time_zone.localize( + datetime.combine( + current_local_date, naive_time)).astimezone(tz=pytz.UTC) + return utc_datetime + def _calculate_initial_boudary_time(self): """Calculate internal absolute time boudaries.""" nowutc = self.current_datetime @@ -134,9 +145,7 @@ class TodSensor(BinarySensorDevice): # datetime.combine(date, time, tzinfo) is not supported # in python 3.5. The self._after is provided # with hass configured TZ not system wide - after_event_date = datetime.combine( - nowutc, self._after.replace( - tzinfo=self.hass.config.time_zone)).astimezone(tz=pytz.UTC) + after_event_date = self._naive_time_to_utc_datetime(self._after) self._time_after = after_event_date @@ -154,9 +163,7 @@ class TodSensor(BinarySensorDevice): self.hass, self._before, after_event_date) else: # Convert local time provided to UTC today, see above - before_event_date = datetime.combine( - nowutc, self._before.replace( - tzinfo=self.hass.config.time_zone)).astimezone(tz=pytz.UTC) + before_event_date = self._naive_time_to_utc_datetime(self._before) # It is safe to add timedelta days=1 to UTC as there is no DST if before_event_date < after_event_date + self._after_offset: @@ -190,7 +197,6 @@ class TodSensor(BinarySensorDevice): async def async_added_to_hass(self): """Call when entity about to be added to Home Assistant.""" - await super().async_added_to_hass() self._calculate_initial_boudary_time() self._calculate_next_update() self._point_in_time_listener(dt_util.now()) diff --git a/tests/components/binary_sensor/test_tod.py b/tests/components/binary_sensor/test_tod.py index 3c083141962..7af6ef95bfa 100644 --- a/tests/components/binary_sensor/test_tod.py +++ b/tests/components/binary_sensor/test_tod.py @@ -110,8 +110,8 @@ class TestBinarySensorTod(unittest.TestCase): def test_midnight_turnover_after_midnight_inside_period(self): """Test midnight turnover setting before midnight inside period .""" - test_time = datetime( - 2019, 1, 10, 21, 00, 0, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2019, 1, 10, 21, 0, 0)).astimezone(pytz.UTC) config = { 'binary_sensor': [ { @@ -143,8 +143,8 @@ class TestBinarySensorTod(unittest.TestCase): def test_midnight_turnover_before_midnight_outside_period(self): """Test midnight turnover setting before midnight outside period.""" - test_time = datetime( - 2019, 1, 10, 20, 30, 0, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2019, 1, 10, 20, 30, 0)).astimezone(pytz.UTC) config = { 'binary_sensor': [ { @@ -165,8 +165,9 @@ class TestBinarySensorTod(unittest.TestCase): def test_midnight_turnover_after_midnight_outside_period(self): """Test midnight turnover setting before midnight inside period .""" - test_time = datetime( - 2019, 1, 10, 20, 0, 0, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2019, 1, 10, 20, 0, 0)).astimezone(pytz.UTC) + config = { 'binary_sensor': [ { @@ -185,8 +186,8 @@ class TestBinarySensorTod(unittest.TestCase): state = self.hass.states.get('binary_sensor.night') assert state.state == STATE_OFF - switchover_time = datetime( - 2019, 1, 11, 4, 59, 0, tzinfo=self.hass.config.time_zone) + switchover_time = self.hass.config.time_zone.localize( + datetime(2019, 1, 11, 4, 59, 0)).astimezone(pytz.UTC) with patch('homeassistant.components.binary_sensor.tod.dt_util.utcnow', return_value=switchover_time): @@ -210,8 +211,8 @@ class TestBinarySensorTod(unittest.TestCase): def test_from_sunrise_to_sunset(self): """Test period from sunrise to sunset.""" - test_time = datetime( - 2019, 1, 12, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2019, 1, 12)).astimezone(pytz.UTC) sunrise = dt_util.as_local(get_astral_event_date( self.hass, 'sunrise', dt_util.as_utc(test_time))) sunset = dt_util.as_local(get_astral_event_date( @@ -299,8 +300,8 @@ class TestBinarySensorTod(unittest.TestCase): def test_from_sunset_to_sunrise(self): """Test period from sunset to sunrise.""" - test_time = datetime( - 2019, 1, 12, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2019, 1, 12)).astimezone(pytz.UTC) sunset = dt_util.as_local(get_astral_event_date( self.hass, 'sunset', test_time)) sunrise = dt_util.as_local(get_astral_event_next( @@ -385,14 +386,14 @@ class TestBinarySensorTod(unittest.TestCase): def test_offset(self): """Test offset.""" - after = datetime( - 2019, 1, 10, 18, 0, 0, - tzinfo=self.hass.config.time_zone) + \ + after = self.hass.config.time_zone.localize( + datetime(2019, 1, 10, 18, 0, 0)).astimezone(pytz.UTC) + \ timedelta(hours=1, minutes=34) - before = datetime( - 2019, 1, 10, 22, 0, 0, - tzinfo=self.hass.config.time_zone) + \ + + before = self.hass.config.time_zone.localize( + datetime(2019, 1, 10, 22, 0, 0)).astimezone(pytz.UTC) + \ timedelta(hours=1, minutes=45) + entity_id = 'binary_sensor.evening' config = { 'binary_sensor': [ @@ -457,9 +458,8 @@ class TestBinarySensorTod(unittest.TestCase): def test_offset_overnight(self): """Test offset overnight.""" - after = datetime( - 2019, 1, 10, 18, 0, 0, - tzinfo=self.hass.config.time_zone) + \ + after = self.hass.config.time_zone.localize( + datetime(2019, 1, 10, 18, 0, 0)).astimezone(pytz.UTC) + \ timedelta(hours=1, minutes=34) entity_id = 'binary_sensor.evening' config = { @@ -498,7 +498,8 @@ class TestBinarySensorTod(unittest.TestCase): self.hass.config.latitude = 69.6 self.hass.config.longitude = 18.8 - test_time = datetime(2010, 1, 1, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2010, 1, 1)).astimezone(pytz.UTC) sunrise = dt_util.as_local(get_astral_event_next( self.hass, 'sunrise', dt_util.as_utc(test_time))) sunset = dt_util.as_local(get_astral_event_next( @@ -600,13 +601,13 @@ class TestBinarySensorTod(unittest.TestCase): self.hass.config.latitude = 69.6 self.hass.config.longitude = 18.8 - test_time = datetime(2010, 6, 1, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2010, 6, 1)).astimezone(pytz.UTC) + sunrise = dt_util.as_local(get_astral_event_next( self.hass, 'sunrise', dt_util.as_utc(test_time))) sunset = dt_util.as_local(get_astral_event_next( self.hass, 'sunset', dt_util.as_utc(test_time))) - print(sunrise) - print(sunset) config = { 'binary_sensor': [ { @@ -701,8 +702,8 @@ class TestBinarySensorTod(unittest.TestCase): def test_sun_offset(self): """Test sun event with offset.""" - test_time = datetime( - 2019, 1, 12, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2019, 1, 12)).astimezone(pytz.UTC) sunrise = dt_util.as_local(get_astral_event_date( self.hass, 'sunrise', dt_util.as_utc(test_time)) + timedelta(hours=-1, minutes=-30)) @@ -810,8 +811,8 @@ class TestBinarySensorTod(unittest.TestCase): def test_dst(self): """Test sun event with offset.""" self.hass.config.time_zone = pytz.timezone('CET') - test_time = datetime( - 2019, 3, 30, 3, 0, 0, tzinfo=self.hass.config.time_zone) + test_time = self.hass.config.time_zone.localize( + datetime(2019, 3, 30, 3, 0, 0)).astimezone(pytz.UTC) config = { 'binary_sensor': [ { From 737c7e871dc811dea7865f86cd71ea1c41c7bda9 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 12 Mar 2019 11:51:09 -0700 Subject: [PATCH 5/5] Bumped version to 0.89.2 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index c1ec2da41c7..a740bdd441e 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 89 -PATCH_VERSION = '1' +PATCH_VERSION = '2' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 5, 3)