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 c129fb2cb54..a580a474b68 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -417,7 +417,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 ea6cd6a144a..bdbe9ba1e7c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -318,7 +318,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 4b45a4016c0..909fb35a1e2 100644 --- a/tests/components/bond/common.py +++ b/tests/components/bond/common.py @@ -113,7 +113,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", @@ -246,3 +246,12 @@ async def help_test_entity_available( async_fire_time_changed(hass, utcnow() + timedelta(seconds=30)) await hass.async_block_till_done() assert hass.states.get(entity_id).state != STATE_UNAVAILABLE + + +def ceiling_fan(name: str): + """Create a ceiling fan with given name.""" + return { + "name": name, + "type": DeviceType.CEILING_FAN, + "actions": ["SetSpeed", "SetDirection"], + } diff --git a/tests/components/bond/test_config_flow.py b/tests/components/bond/test_config_flow.py index 5d3b357b9f7..519fa9dec9d 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", @@ -472,7 +472,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", @@ -497,7 +497,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 03eb490b65e..56087d4bf11 100644 --- a/tests/components/bond/test_init.py +++ b/tests/components/bond/test_init.py @@ -7,13 +7,15 @@ from bond_async import DeviceType 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 from homeassistant.setup import async_setup_component from .common import ( + ceiling_fan, patch_bond_bridge, patch_bond_device, patch_bond_device_ids, @@ -23,6 +25,7 @@ from .common import ( patch_setup_entry, patch_start_bpup, setup_bond_entity, + setup_platform, ) from tests.common import MockConfigEntry @@ -81,7 +84,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", @@ -99,11 +102,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" @@ -151,7 +154,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, @@ -164,7 +167,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", } @@ -185,7 +188,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 @@ -205,7 +208,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", } @@ -227,10 +230,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" @@ -251,7 +254,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", } @@ -273,9 +276,21 @@ 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" + + +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={}