From 5854dfa84f7d575d0b96640a0b3cbacef7a2b869 Mon Sep 17 00:00:00 2001 From: Marcio Granzotto Rodrigues Date: Sun, 12 Jun 2022 22:27:18 -0300 Subject: [PATCH] Fix smart by bond detection with v3 firmware (#73414) --- homeassistant/components/bond/manifest.json | 2 +- homeassistant/components/bond/utils.py | 5 +-- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/bond/common.py | 2 +- tests/components/bond/test_config_flow.py | 24 ++++++------- tests/components/bond/test_diagnostics.py | 2 +- tests/components/bond/test_init.py | 38 ++++++++++++++------- tests/components/bond/test_light.py | 2 +- 9 files changed, 46 insertions(+), 33 deletions(-) diff --git a/homeassistant/components/bond/manifest.json b/homeassistant/components/bond/manifest.json index 52e9dd1763f..a5625d7b642 100644 --- a/homeassistant/components/bond/manifest.json +++ b/homeassistant/components/bond/manifest.json @@ -3,7 +3,7 @@ "name": "Bond", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/bond", - "requirements": ["bond-async==0.1.20"], + "requirements": ["bond-async==0.1.22"], "zeroconf": ["_bond._tcp.local."], "codeowners": ["@bdraco", "@prystupa", "@joshs85", "@marciogranzotto"], "quality_scale": "platinum", diff --git a/homeassistant/components/bond/utils.py b/homeassistant/components/bond/utils.py index cba213d9450..c426bf64577 100644 --- a/homeassistant/components/bond/utils.py +++ b/homeassistant/components/bond/utils.py @@ -5,7 +5,7 @@ import logging from typing import Any, cast from aiohttp import ClientResponseError -from bond_async import Action, Bond +from bond_async import Action, Bond, BondType from homeassistant.util.async_ import gather_with_concurrency @@ -224,4 +224,5 @@ class BondHub: @property def is_bridge(self) -> bool: """Return if the Bond is a Bond Bridge.""" - return bool(self._bridge) + bondid = self._version["bondid"] + return bool(BondType.is_bridge_from_serial(bondid)) diff --git a/requirements_all.txt b/requirements_all.txt index aa93ba61889..843680f5227 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -420,7 +420,7 @@ blockchain==1.4.4 # bluepy==1.3.0 # homeassistant.components.bond -bond-async==0.1.20 +bond-async==0.1.22 # homeassistant.components.bosch_shc boschshcpy==0.2.30 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f2bc79db670..151a427470b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -321,7 +321,7 @@ blebox_uniapi==1.3.3 blinkpy==0.19.0 # homeassistant.components.bond -bond-async==0.1.20 +bond-async==0.1.22 # homeassistant.components.bosch_shc boschshcpy==0.2.30 diff --git a/tests/components/bond/common.py b/tests/components/bond/common.py index c5a649ab30a..f14efcdf172 100644 --- a/tests/components/bond/common.py +++ b/tests/components/bond/common.py @@ -127,7 +127,7 @@ def patch_bond_version( return nullcontext() if return_value is None: - return_value = {"bondid": "test-bond-id"} + return_value = {"bondid": "ZXXX12345"} return patch( "homeassistant.components.bond.Bond.version", diff --git a/tests/components/bond/test_config_flow.py b/tests/components/bond/test_config_flow.py index 67910af7b6c..4f1e313a34a 100644 --- a/tests/components/bond/test_config_flow.py +++ b/tests/components/bond/test_config_flow.py @@ -35,7 +35,7 @@ async def test_user_form(hass: core.HomeAssistant): assert result["errors"] == {} with patch_bond_version( - return_value={"bondid": "test-bond-id"} + return_value={"bondid": "ZXXX12345"} ), patch_bond_device_ids( return_value=["f6776c11", "f6776c12"] ), patch_bond_bridge(), patch_bond_device_properties(), patch_bond_device(), _patch_async_setup_entry() as mock_setup_entry: @@ -64,7 +64,7 @@ async def test_user_form_with_non_bridge(hass: core.HomeAssistant): assert result["errors"] == {} with patch_bond_version( - return_value={"bondid": "test-bond-id"} + return_value={"bondid": "KXXX12345"} ), patch_bond_device_ids( return_value=["f6776c11"] ), patch_bond_device_properties(), patch_bond_device( @@ -96,7 +96,7 @@ async def test_user_form_invalid_auth(hass: core.HomeAssistant): ) with patch_bond_version( - return_value={"bond_id": "test-bond-id"} + return_value={"bond_id": "ZXXX12345"} ), patch_bond_bridge(), patch_bond_device_ids( side_effect=ClientResponseError(Mock(), Mock(), status=401), ): @@ -203,7 +203,7 @@ async def test_zeroconf_form(hass: core.HomeAssistant): host="test-host", addresses=["test-host"], hostname="mock_hostname", - name="test-bond-id.some-other-tail-info", + name="ZXXX12345.some-other-tail-info", port=None, properties={}, type="mock_type", @@ -213,7 +213,7 @@ async def test_zeroconf_form(hass: core.HomeAssistant): assert result["errors"] == {} with patch_bond_version( - return_value={"bondid": "test-bond-id"} + return_value={"bondid": "ZXXX12345"} ), patch_bond_bridge(), patch_bond_device_ids(), _patch_async_setup_entry() as mock_setup_entry: result2 = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -241,7 +241,7 @@ async def test_zeroconf_form_token_unavailable(hass: core.HomeAssistant): host="test-host", addresses=["test-host"], hostname="mock_hostname", - name="test-bond-id.some-other-tail-info", + name="ZXXX12345.some-other-tail-info", port=None, properties={}, type="mock_type", @@ -270,7 +270,7 @@ async def test_zeroconf_form_token_unavailable(hass: core.HomeAssistant): async def test_zeroconf_form_with_token_available(hass: core.HomeAssistant): """Test we get the discovery form when we can get the token.""" - with patch_bond_version(return_value={"bondid": "test-bond-id"}), patch_bond_token( + with patch_bond_version(return_value={"bondid": "ZXXX12345"}), patch_bond_token( return_value={"token": "discovered-token"} ), patch_bond_bridge( return_value={"name": "discovered-name"} @@ -282,7 +282,7 @@ async def test_zeroconf_form_with_token_available(hass: core.HomeAssistant): host="test-host", addresses=["test-host"], hostname="mock_hostname", - name="test-bond-id.some-other-tail-info", + name="ZXXX12345.some-other-tail-info", port=None, properties={}, type="mock_type", @@ -323,7 +323,7 @@ async def test_zeroconf_form_with_token_available_name_unavailable( host="test-host", addresses=["test-host"], hostname="mock_hostname", - name="test-bond-id.some-other-tail-info", + name="ZXXX12345.some-other-tail-info", port=None, properties={}, type="mock_type", @@ -341,7 +341,7 @@ async def test_zeroconf_form_with_token_available_name_unavailable( await hass.async_block_till_done() assert result2["type"] == "create_entry" - assert result2["title"] == "test-bond-id" + assert result2["title"] == "ZXXX12345" assert result2["data"] == { CONF_HOST: "test-host", CONF_ACCESS_TOKEN: "discovered-token", @@ -511,7 +511,7 @@ async def test_zeroconf_form_unexpected_error(hass: core.HomeAssistant): host="test-host", addresses=["test-host"], hostname="mock_hostname", - name="test-bond-id.some-other-tail-info", + name="ZXXX12345.some-other-tail-info", port=None, properties={}, type="mock_type", @@ -536,7 +536,7 @@ async def _help_test_form_unexpected_error( ) with patch_bond_version( - return_value={"bond_id": "test-bond-id"} + return_value={"bond_id": "ZXXX12345"} ), patch_bond_device_ids(side_effect=error): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], user_input diff --git a/tests/components/bond/test_diagnostics.py b/tests/components/bond/test_diagnostics.py index 88d33ff2cc0..b738c72ee8c 100644 --- a/tests/components/bond/test_diagnostics.py +++ b/tests/components/bond/test_diagnostics.py @@ -39,5 +39,5 @@ async def test_diagnostics(hass, hass_client): "data": {"access_token": "**REDACTED**", "host": "some host"}, "title": "Mock Title", }, - "hub": {"version": {"bondid": "test-bond-id"}}, + "hub": {"version": {"bondid": "ZXXX12345"}}, } diff --git a/tests/components/bond/test_init.py b/tests/components/bond/test_init.py index 5db5d8e65bf..d02e2bed4ec 100644 --- a/tests/components/bond/test_init.py +++ b/tests/components/bond/test_init.py @@ -9,7 +9,7 @@ import pytest from homeassistant.components.bond.const import DOMAIN from homeassistant.components.fan import DOMAIN as FAN_DOMAIN from homeassistant.config_entries import ConfigEntryState -from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST +from homeassistant.const import ATTR_ASSUMED_STATE, CONF_ACCESS_TOKEN, CONF_HOST from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.entity_registry import EntityRegistry @@ -86,7 +86,7 @@ async def test_async_setup_entry_sets_up_hub_and_supported_domains(hass: HomeAss with patch_bond_bridge(), patch_bond_version( return_value={ - "bondid": "test-bond-id", + "bondid": "ZXXX12345", "target": "test-model", "fw_ver": "test-version", "mcu_ver": "test-hw-version", @@ -104,11 +104,11 @@ async def test_async_setup_entry_sets_up_hub_and_supported_domains(hass: HomeAss assert config_entry.entry_id in hass.data[DOMAIN] assert config_entry.state is ConfigEntryState.LOADED - assert config_entry.unique_id == "test-bond-id" + assert config_entry.unique_id == "ZXXX12345" # verify hub device is registered correctly device_registry = dr.async_get(hass) - hub = device_registry.async_get_device(identifiers={(DOMAIN, "test-bond-id")}) + hub = device_registry.async_get_device(identifiers={(DOMAIN, "ZXXX12345")}) assert hub.name == "bond-name" assert hub.manufacturer == "Olibra" assert hub.model == "test-model" @@ -156,7 +156,7 @@ async def test_old_identifiers_are_removed(hass: HomeAssistant): ) old_identifers = (DOMAIN, "device_id") - new_identifiers = (DOMAIN, "test-bond-id", "device_id") + new_identifiers = (DOMAIN, "ZXXX12345", "device_id") device_registry = dr.async_get(hass) device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, @@ -169,7 +169,7 @@ async def test_old_identifiers_are_removed(hass: HomeAssistant): with patch_bond_bridge(), patch_bond_version( return_value={ - "bondid": "test-bond-id", + "bondid": "ZXXX12345", "target": "test-model", "fw_ver": "test-version", } @@ -190,7 +190,7 @@ async def test_old_identifiers_are_removed(hass: HomeAssistant): assert config_entry.entry_id in hass.data[DOMAIN] assert config_entry.state is ConfigEntryState.LOADED - assert config_entry.unique_id == "test-bond-id" + assert config_entry.unique_id == "ZXXX12345" # verify the device info is cleaned up assert device_registry.async_get_device(identifiers={old_identifers}) is None @@ -210,7 +210,7 @@ async def test_smart_by_bond_device_suggested_area(hass: HomeAssistant): side_effect=ClientResponseError(Mock(), Mock(), status=404) ), patch_bond_version( return_value={ - "bondid": "test-bond-id", + "bondid": "KXXX12345", "target": "test-model", "fw_ver": "test-version", } @@ -232,10 +232,10 @@ async def test_smart_by_bond_device_suggested_area(hass: HomeAssistant): assert config_entry.entry_id in hass.data[DOMAIN] assert config_entry.state is ConfigEntryState.LOADED - assert config_entry.unique_id == "test-bond-id" + assert config_entry.unique_id == "KXXX12345" device_registry = dr.async_get(hass) - device = device_registry.async_get_device(identifiers={(DOMAIN, "test-bond-id")}) + device = device_registry.async_get_device(identifiers={(DOMAIN, "KXXX12345")}) assert device is not None assert device.suggested_area == "Den" @@ -256,7 +256,7 @@ async def test_bridge_device_suggested_area(hass: HomeAssistant): } ), patch_bond_version( return_value={ - "bondid": "test-bond-id", + "bondid": "ZXXX12345", "target": "test-model", "fw_ver": "test-version", } @@ -278,10 +278,10 @@ async def test_bridge_device_suggested_area(hass: HomeAssistant): assert config_entry.entry_id in hass.data[DOMAIN] assert config_entry.state is ConfigEntryState.LOADED - assert config_entry.unique_id == "test-bond-id" + assert config_entry.unique_id == "ZXXX12345" device_registry = dr.async_get(hass) - device = device_registry.async_get_device(identifiers={(DOMAIN, "test-bond-id")}) + device = device_registry.async_get_device(identifiers={(DOMAIN, "ZXXX12345")}) assert device is not None assert device.suggested_area == "Office" @@ -343,3 +343,15 @@ async def test_device_remove_devices(hass, hass_ws_client): ) is False ) + + +async def test_smart_by_bond_v3_firmware(hass: HomeAssistant) -> None: + """Test we can detect smart by bond with the v3 firmware.""" + await setup_platform( + hass, + FAN_DOMAIN, + ceiling_fan("name-1"), + bond_version={"bondid": "KXXXX12345", "target": "breck-northstar"}, + bond_device_id="test-device-id", + ) + assert ATTR_ASSUMED_STATE not in hass.states.get("fan.name_1").attributes diff --git a/tests/components/bond/test_light.py b/tests/components/bond/test_light.py index c7d8f195423..7577b1d70ab 100644 --- a/tests/components/bond/test_light.py +++ b/tests/components/bond/test_light.py @@ -249,7 +249,7 @@ async def test_sbb_trust_state(hass: core.HomeAssistant): """Assumed state should be False if device is a Smart by Bond.""" version = { "model": "MR123A", - "bondid": "test-bond-id", + "bondid": "KXXX12345", } await setup_platform( hass, LIGHT_DOMAIN, ceiling_fan("name-1"), bond_version=version, bridge={}