diff --git a/homeassistant/components/cloud/google_config.py b/homeassistant/components/cloud/google_config.py index 3df06c140a0..6753d74ba45 100644 --- a/homeassistant/components/cloud/google_config.py +++ b/homeassistant/components/cloud/google_config.py @@ -77,6 +77,12 @@ class CloudGoogleConfig(AbstractConfig): """Return Cloud User account.""" return self._user + async def async_initialize(self): + """Perform async initialization of config.""" + await super().async_initialize() + # Remove bad data that was there until 0.103.6 - Jan 6, 2020 + self._store.pop_agent_user_id(self._user) + def should_expose(self, state): """If a state object should be exposed.""" return self._should_expose_entity_id(state.entity_id) @@ -93,6 +99,15 @@ class CloudGoogleConfig(AbstractConfig): entity_config = entity_configs.get(entity_id, {}) return entity_config.get(PREF_SHOULD_EXPOSE, DEFAULT_SHOULD_EXPOSE) + @property + def agent_user_id(self): + """Return Agent User Id to use for query responses.""" + return self._cloud.username + + def get_agent_user_id(self, context): + """Get agent user ID making request.""" + return self.agent_user_id + def should_2fa(self, state): """If an entity should be checked for 2FA.""" entity_configs = self._prefs.google_entity_configs diff --git a/homeassistant/components/cloud/http_api.py b/homeassistant/components/cloud/http_api.py index c68f24172f0..d808fe72d39 100644 --- a/homeassistant/components/cloud/http_api.py +++ b/homeassistant/components/cloud/http_api.py @@ -175,7 +175,7 @@ class GoogleActionsSyncView(HomeAssistantView): hass = request.app["hass"] cloud: Cloud = hass.data[DOMAIN] gconf = await cloud.client.get_google_config() - status = await gconf.async_sync_entities(gconf.cloud_user) + status = await gconf.async_sync_entities(gconf.agent_user_id) return self.json({}, status_code=status) diff --git a/homeassistant/components/environment_canada/manifest.json b/homeassistant/components/environment_canada/manifest.json index 8ad13b39251..bfe0aa5d2cb 100644 --- a/homeassistant/components/environment_canada/manifest.json +++ b/homeassistant/components/environment_canada/manifest.json @@ -3,7 +3,7 @@ "name": "Environment Canada", "documentation": "https://www.home-assistant.io/integrations/environment_canada", "requirements": [ - "env_canada==0.0.30" + "env_canada==0.0.31" ], "dependencies": [], "codeowners": [ diff --git a/homeassistant/components/google_assistant/helpers.py b/homeassistant/components/google_assistant/helpers.py index 09859c5d3d0..64375beaf0d 100644 --- a/homeassistant/components/google_assistant/helpers.py +++ b/homeassistant/components/google_assistant/helpers.py @@ -1,4 +1,5 @@ """Helper classes for Google Assistant integration.""" +from abc import ABC, abstractmethod from asyncio import gather from collections.abc import Mapping import logging @@ -35,7 +36,7 @@ SYNC_DELAY = 15 _LOGGER = logging.getLogger(__name__) -class AbstractConfig: +class AbstractConfig(ABC): """Hold the configuration for Google Assistant.""" _unsub_report_state = None @@ -95,9 +96,13 @@ class AbstractConfig: """Return the user ID to be used for actions received via the local SDK.""" raise NotImplementedError + @abstractmethod + def get_agent_user_id(self, context): + """Get agent user ID from context.""" + + @abstractmethod def should_expose(self, state) -> bool: """Return if entity should be exposed.""" - raise NotImplementedError def should_2fa(self, state): """If an entity should have 2FA checked.""" diff --git a/homeassistant/components/google_assistant/http.py b/homeassistant/components/google_assistant/http.py index c3d0dd493a8..3b3c5f1a2c1 100644 --- a/homeassistant/components/google_assistant/http.py +++ b/homeassistant/components/google_assistant/http.py @@ -121,6 +121,10 @@ class GoogleConfig(AbstractConfig): return is_default_exposed or explicit_expose + def get_agent_user_id(self, context): + """Get agent user ID making request.""" + return context.user_id + def should_2fa(self, state): """If an entity should have 2FA checked.""" return True diff --git a/homeassistant/components/google_assistant/smart_home.py b/homeassistant/components/google_assistant/smart_home.py index 0e5037ce13a..680a6f7ecf1 100644 --- a/homeassistant/components/google_assistant/smart_home.py +++ b/homeassistant/components/google_assistant/smart_home.py @@ -79,7 +79,7 @@ async def async_devices_sync(hass, data, payload): EVENT_SYNC_RECEIVED, {"request_id": data.request_id}, context=data.context ) - agent_user_id = data.context.user_id + agent_user_id = data.config.get_agent_user_id(data.context) devices = await asyncio.gather( *( diff --git a/homeassistant/components/smartthings/manifest.json b/homeassistant/components/smartthings/manifest.json index 0ab71382fad..9fa156e0b28 100644 --- a/homeassistant/components/smartthings/manifest.json +++ b/homeassistant/components/smartthings/manifest.json @@ -3,7 +3,7 @@ "name": "Smartthings", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/smartthings", - "requirements": ["pysmartapp==0.3.2", "pysmartthings==0.6.9"], + "requirements": ["pysmartapp==0.3.2", "pysmartthings==0.7.0"], "dependencies": ["webhook"], "after_dependencies": ["cloud"], "codeowners": ["@andrewsayre"] diff --git a/homeassistant/components/unifi/device_tracker.py b/homeassistant/components/unifi/device_tracker.py index 086393b85d2..e449d5035b7 100644 --- a/homeassistant/components/unifi/device_tracker.py +++ b/homeassistant/components/unifi/device_tracker.py @@ -131,6 +131,9 @@ class UniFiClientTracker(ScannerEntity): self.is_wired = self.client.mac not in controller.wireless_clients self.wired_bug = None + if self.is_wired != self.client.is_wired: + self.wired_bug = dt_util.utcnow() - self.controller.option_detection_time + @property def entity_registry_enabled_default(self): """Return if the entity should be enabled when first added to the entity registry.""" diff --git a/homeassistant/const.py b/homeassistant/const.py index 306c4ded067..8c002853436 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 103 -PATCH_VERSION = "5" +PATCH_VERSION = "6" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 6, 1) diff --git a/requirements_all.txt b/requirements_all.txt index 01492591988..8544f140ca1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -475,7 +475,7 @@ enocean==0.50 enturclient==0.2.1 # homeassistant.components.environment_canada -env_canada==0.0.30 +env_canada==0.0.31 # homeassistant.components.envirophat # envirophat==0.0.6 @@ -1485,7 +1485,7 @@ pysma==0.3.4 pysmartapp==0.3.2 # homeassistant.components.smartthings -pysmartthings==0.6.9 +pysmartthings==0.7.0 # homeassistant.components.smarty pysmarty==0.8 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 79691bb3cf2..0da2b298bc2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -490,7 +490,7 @@ pysma==0.3.4 pysmartapp==0.3.2 # homeassistant.components.smartthings -pysmartthings==0.6.9 +pysmartthings==0.7.0 # homeassistant.components.soma pysoma==0.0.10 diff --git a/tests/components/cloud/test_client.py b/tests/components/cloud/test_client.py index 955923c1e68..6e127efe04c 100644 --- a/tests/components/cloud/test_client.py +++ b/tests/components/cloud/test_client.py @@ -102,13 +102,17 @@ async def test_handler_google_actions(hass): reqid = "5711642932632160983" data = {"requestId": reqid, "inputs": [{"intent": "action.devices.SYNC"}]} - config = await cloud.client.get_google_config() - resp = await cloud.client.async_google_message(data) + with patch( + "hass_nabucasa.Cloud._decode_claims", + return_value={"cognito:username": "myUserName"}, + ): + await cloud.client.get_google_config() + resp = await cloud.client.async_google_message(data) assert resp["requestId"] == reqid payload = resp["payload"] - assert payload["agentUserId"] == config.cloud_user + assert payload["agentUserId"] == "myUserName" devices = payload["devices"] assert len(devices) == 1 diff --git a/tests/components/google_assistant/__init__.py b/tests/components/google_assistant/__init__.py index 657bf930ed6..32363313f11 100644 --- a/tests/components/google_assistant/__init__.py +++ b/tests/components/google_assistant/__init__.py @@ -63,6 +63,10 @@ class MockConfig(helpers.AbstractConfig): """Return local SDK webhook id.""" return self._local_sdk_user_id + def get_agent_user_id(self, context): + """Get agent user ID making request.""" + return context.user_id + def should_expose(self, state): """Expose it all.""" return self._should_expose is None or self._should_expose(state) diff --git a/tests/components/unifi/test_controller.py b/tests/components/unifi/test_controller.py index 2b64e56cd99..1080dde6cfb 100644 --- a/tests/components/unifi/test_controller.py +++ b/tests/components/unifi/test_controller.py @@ -60,6 +60,7 @@ async def setup_unifi_integration( clients_response, devices_response, clients_all_response, + known_wireless_clients=None, ): """Create the UniFi controller.""" if UNIFI_CONFIG not in hass.data: @@ -77,6 +78,11 @@ async def setup_unifi_integration( entry_id=1, ) + if known_wireless_clients: + hass.data[UNIFI_WIRELESS_CLIENTS].update_data( + known_wireless_clients, config_entry + ) + mock_client_responses = deque() mock_client_responses.append(clients_response) diff --git a/tests/components/unifi/test_device_tracker.py b/tests/components/unifi/test_device_tracker.py index 580365bb8bd..a7f64cf572a 100644 --- a/tests/components/unifi/test_device_tracker.py +++ b/tests/components/unifi/test_device_tracker.py @@ -44,6 +44,14 @@ CLIENT_3 = { "last_seen": 1562600145, "mac": "00:00:00:00:00:03", } +CLIENT_4 = { + "essid": "ssid", + "hostname": "client_4", + "ip": "10.0.0.4", + "is_wired": True, + "last_seen": 1562600145, + "mac": "00:00:00:00:00:04", +} DEVICE_1 = { "board_rev": 3, @@ -103,16 +111,20 @@ async def test_no_clients(hass): async def test_tracked_devices(hass): """Test the update_items function with some clients.""" + client_4_copy = copy(CLIENT_4) + client_4_copy["last_seen"] = dt_util.as_timestamp(dt_util.utcnow()) + controller = await setup_unifi_integration( hass, ENTRY_CONFIG, options={CONF_SSID_FILTER: ["ssid"]}, sites=SITES, - clients_response=[CLIENT_1, CLIENT_2, CLIENT_3], + clients_response=[CLIENT_1, CLIENT_2, CLIENT_3, client_4_copy], devices_response=[DEVICE_1, DEVICE_2], clients_all_response={}, + known_wireless_clients=(CLIENT_4["mac"],), ) - assert len(hass.states.async_all()) == 5 + assert len(hass.states.async_all()) == 6 client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None @@ -125,6 +137,11 @@ async def test_tracked_devices(hass): client_3 = hass.states.get("device_tracker.client_3") assert client_3 is None + # Wireless client with wired bug, if bug active on restart mark device away + client_4 = hass.states.get("device_tracker.client_4") + assert client_4 is not None + assert client_4.state == "not_home" + device_1 = hass.states.get("device_tracker.device_1") assert device_1 is not None assert device_1.state == "not_home"