diff --git a/homeassistant/components/homeassistant_sky_connect/__init__.py b/homeassistant/components/homeassistant_sky_connect/__init__.py index 763c421350f..1ee4710769b 100644 --- a/homeassistant/components/homeassistant_sky_connect/__init__.py +++ b/homeassistant/components/homeassistant_sky_connect/__init__.py @@ -14,7 +14,7 @@ from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError from homeassistant.helpers import discovery_flow from .const import DOMAIN -from .util import get_usb_service_info +from .util import get_hardware_variant, get_usb_service_info async def _async_usb_scan_done(hass: HomeAssistant, entry: ConfigEntry) -> None: @@ -46,8 +46,9 @@ async def _async_usb_scan_done(hass: HomeAssistant, entry: ConfigEntry) -> None: ) return + hw_variant = get_hardware_variant(entry) hw_discovery_data = { - "name": "SkyConnect Multiprotocol", + "name": f"{hw_variant.short_name} Multiprotocol", "port": { "path": get_zigbee_socket(), }, diff --git a/homeassistant/components/homeassistant_sky_connect/config_flow.py b/homeassistant/components/homeassistant_sky_connect/config_flow.py index 4e4cbfe0a03..3a3d32c2888 100644 --- a/homeassistant/components/homeassistant_sky_connect/config_flow.py +++ b/homeassistant/components/homeassistant_sky_connect/config_flow.py @@ -9,8 +9,8 @@ from homeassistant.components.homeassistant_hardware import silabs_multiprotocol from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult from homeassistant.core import callback -from .const import DOMAIN -from .util import get_usb_service_info +from .const import DOMAIN, HardwareVariant +from .util import get_hardware_variant, get_usb_service_info class HomeAssistantSkyConnectConfigFlow(ConfigFlow, domain=DOMAIN): @@ -39,8 +39,12 @@ class HomeAssistantSkyConnectConfigFlow(ConfigFlow, domain=DOMAIN): unique_id = f"{vid}:{pid}_{serial_number}_{manufacturer}_{description}" if await self.async_set_unique_id(unique_id): self._abort_if_unique_id_configured(updates={"device": device}) + + assert description is not None + hw_variant = HardwareVariant.from_usb_product_name(description) + return self.async_create_entry( - title="Home Assistant SkyConnect", + title=hw_variant.full_name, data={ "device": device, "vid": vid, @@ -76,10 +80,15 @@ class HomeAssistantSkyConnectOptionsFlow(silabs_multiprotocol_addon.OptionsFlowH """ return {"usb": get_usb_service_info(self.config_entry)} + @property + def _hw_variant(self) -> HardwareVariant: + """Return the hardware variant.""" + return get_hardware_variant(self.config_entry) + def _zha_name(self) -> str: """Return the ZHA name.""" - return "SkyConnect Multiprotocol" + return f"{self._hw_variant.short_name} Multiprotocol" def _hardware_name(self) -> str: """Return the name of the hardware.""" - return "Home Assistant SkyConnect" + return self._hw_variant.full_name diff --git a/homeassistant/components/homeassistant_sky_connect/const.py b/homeassistant/components/homeassistant_sky_connect/const.py index c504cead9cb..1dd1471c470 100644 --- a/homeassistant/components/homeassistant_sky_connect/const.py +++ b/homeassistant/components/homeassistant_sky_connect/const.py @@ -1,3 +1,41 @@ """Constants for the Home Assistant SkyConnect integration.""" +import dataclasses +import enum +from typing import Self + DOMAIN = "homeassistant_sky_connect" + + +@dataclasses.dataclass(frozen=True) +class VariantInfo: + """Hardware variant information.""" + + usb_product_name: str + short_name: str + full_name: str + + +class HardwareVariant(VariantInfo, enum.Enum): + """Hardware variants.""" + + SKYCONNECT = ( + "SkyConnect v1.0", + "SkyConnect", + "Home Assistant SkyConnect", + ) + + CONNECT_ZBT1 = ( + "Home Assistant Connect ZBT-1", + "Connect ZBT-1", + "Home Assistant Connect ZBT-1", + ) + + @classmethod + def from_usb_product_name(cls, usb_product_name: str) -> Self: + """Get the hardware variant from the USB product name.""" + for variant in cls: + if variant.value.usb_product_name == usb_product_name: + return variant + + raise ValueError(f"Unknown SkyConnect product name: {usb_product_name}") diff --git a/homeassistant/components/homeassistant_sky_connect/hardware.py b/homeassistant/components/homeassistant_sky_connect/hardware.py index 1c32bce531b..a9abeb27737 100644 --- a/homeassistant/components/homeassistant_sky_connect/hardware.py +++ b/homeassistant/components/homeassistant_sky_connect/hardware.py @@ -6,9 +6,9 @@ from homeassistant.components.hardware.models import HardwareInfo, USBInfo from homeassistant.core import HomeAssistant, callback from .const import DOMAIN +from .util import get_hardware_variant DOCUMENTATION_URL = "https://skyconnect.home-assistant.io/documentation/" -DONGLE_NAME = "Home Assistant SkyConnect" @callback @@ -27,7 +27,7 @@ def async_info(hass: HomeAssistant) -> list[HardwareInfo]: manufacturer=entry.data["manufacturer"], description=entry.data["description"], ), - name=DONGLE_NAME, + name=get_hardware_variant(entry).full_name, url=DOCUMENTATION_URL, ) for entry in entries diff --git a/homeassistant/components/homeassistant_sky_connect/manifest.json b/homeassistant/components/homeassistant_sky_connect/manifest.json index 31685183a61..f56fd24de61 100644 --- a/homeassistant/components/homeassistant_sky_connect/manifest.json +++ b/homeassistant/components/homeassistant_sky_connect/manifest.json @@ -12,6 +12,12 @@ "pid": "EA60", "description": "*skyconnect v1.0*", "known_devices": ["SkyConnect v1.0"] + }, + { + "vid": "10C4", + "pid": "EA60", + "description": "*home assistant connect zbt-1*", + "known_devices": ["Home Assistant Connect ZBT-1"] } ] } diff --git a/homeassistant/components/homeassistant_sky_connect/util.py b/homeassistant/components/homeassistant_sky_connect/util.py index 84aa858c847..e1de1d3b442 100644 --- a/homeassistant/components/homeassistant_sky_connect/util.py +++ b/homeassistant/components/homeassistant_sky_connect/util.py @@ -5,6 +5,8 @@ from __future__ import annotations from homeassistant.components import usb from homeassistant.config_entries import ConfigEntry +from .const import HardwareVariant + def get_usb_service_info(config_entry: ConfigEntry) -> usb.UsbServiceInfo: """Return UsbServiceInfo.""" @@ -16,3 +18,8 @@ def get_usb_service_info(config_entry: ConfigEntry) -> usb.UsbServiceInfo: manufacturer=config_entry.data["manufacturer"], description=config_entry.data["description"], ) + + +def get_hardware_variant(config_entry: ConfigEntry) -> HardwareVariant: + """Get the hardware variant from the config entry.""" + return HardwareVariant.from_usb_product_name(config_entry.data["description"]) diff --git a/homeassistant/components/otbr/config_flow.py b/homeassistant/components/otbr/config_flow.py index 9a70970bdb6..8342a965bd3 100644 --- a/homeassistant/components/otbr/config_flow.py +++ b/homeassistant/components/otbr/config_flow.py @@ -59,6 +59,9 @@ async def _title(hass: HomeAssistant, discovery_info: HassioServiceInfo) -> str: if device and "SkyConnect" in device: return f"Home Assistant SkyConnect ({discovery_info.name})" + if device and "Connect_ZBT-1" in device: + return f"Home Assistant Connect ZBT-1 ({discovery_info.name})" + return discovery_info.name diff --git a/homeassistant/generated/usb.py b/homeassistant/generated/usb.py index faf8abb775c..e66a5861d18 100644 --- a/homeassistant/generated/usb.py +++ b/homeassistant/generated/usb.py @@ -10,6 +10,12 @@ USB = [ "pid": "EA60", "vid": "10C4", }, + { + "description": "*home assistant connect zbt-1*", + "domain": "homeassistant_sky_connect", + "pid": "EA60", + "vid": "10C4", + }, { "domain": "insteon", "vid": "10BF", diff --git a/tests/components/homeassistant_sky_connect/test_config_flow.py b/tests/components/homeassistant_sky_connect/test_config_flow.py index 9374cbc9457..957a407cc0e 100644 --- a/tests/components/homeassistant_sky_connect/test_config_flow.py +++ b/tests/components/homeassistant_sky_connect/test_config_flow.py @@ -19,13 +19,22 @@ from homeassistant.setup import async_setup_component from tests.common import MockConfigEntry, MockModule, mock_integration -USB_DATA = usb.UsbServiceInfo( - device="bla_device", - vid="bla_vid", - pid="bla_pid", - serial_number="bla_serial_number", - manufacturer="bla_manufacturer", - description="bla_description", +USB_DATA_SKY = usb.UsbServiceInfo( + device="/dev/serial/by-id/usb-Nabu_Casa_SkyConnect_v1.0_9e2adbd75b8beb119fe564a0f320645d-if00-port0", + vid="10C4", + pid="EA60", + serial_number="9e2adbd75b8beb119fe564a0f320645d", + manufacturer="Nabu Casa", + description="SkyConnect v1.0", +) + +USB_DATA_ZBT1 = usb.UsbServiceInfo( + device="/dev/serial/by-id/usb-Nabu_Casa_Home_Assistant_Connect_ZBT-1_9e2adbd75b8beb119fe564a0f320645d-if00-port0", + vid="10C4", + pid="EA60", + serial_number="9e2adbd75b8beb119fe564a0f320645d", + manufacturer="Nabu Casa", + description="Home Assistant Connect ZBT-1", ) @@ -38,27 +47,36 @@ def config_flow_handler(hass: HomeAssistant) -> Generator[None, None, None]: yield -async def test_config_flow(hass: HomeAssistant) -> None: - """Test the config flow.""" +@pytest.mark.parametrize( + ("usb_data", "title"), + [ + (USB_DATA_SKY, "Home Assistant SkyConnect"), + (USB_DATA_ZBT1, "Home Assistant Connect ZBT-1"), + ], +) +async def test_config_flow( + usb_data: usb.UsbServiceInfo, title: str, hass: HomeAssistant +) -> None: + """Test the config flow for SkyConnect.""" with patch( "homeassistant.components.homeassistant_sky_connect.async_setup_entry", return_value=True, ) as mock_setup_entry: result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": "usb"}, data=USB_DATA + DOMAIN, context={"source": "usb"}, data=usb_data ) expected_data = { - "device": USB_DATA.device, - "vid": USB_DATA.vid, - "pid": USB_DATA.pid, - "serial_number": USB_DATA.serial_number, - "manufacturer": USB_DATA.manufacturer, - "description": USB_DATA.description, + "device": usb_data.device, + "vid": usb_data.vid, + "pid": usb_data.pid, + "serial_number": usb_data.serial_number, + "manufacturer": usb_data.manufacturer, + "description": usb_data.description, } assert result["type"] == FlowResultType.CREATE_ENTRY - assert result["title"] == "Home Assistant SkyConnect" + assert result["title"] == title assert result["data"] == expected_data assert result["options"] == {} assert len(mock_setup_entry.mock_calls) == 1 @@ -66,51 +84,35 @@ async def test_config_flow(hass: HomeAssistant) -> None: config_entry = hass.config_entries.async_entries(DOMAIN)[0] assert config_entry.data == expected_data assert config_entry.options == {} - assert config_entry.title == "Home Assistant SkyConnect" + assert config_entry.title == title assert ( config_entry.unique_id - == f"{USB_DATA.vid}:{USB_DATA.pid}_{USB_DATA.serial_number}_{USB_DATA.manufacturer}_{USB_DATA.description}" + == f"{usb_data.vid}:{usb_data.pid}_{usb_data.serial_number}_{usb_data.manufacturer}_{usb_data.description}" ) -async def test_config_flow_unique_id(hass: HomeAssistant) -> None: - """Test only a single entry is allowed for a dongle.""" - # Setup an existing config entry - config_entry = MockConfigEntry( - data={}, - domain=DOMAIN, - options={}, - title="Home Assistant SkyConnect", - unique_id=f"{USB_DATA.vid}:{USB_DATA.pid}_{USB_DATA.serial_number}_{USB_DATA.manufacturer}_{USB_DATA.description}", - ) - config_entry.add_to_hass(hass) - - with patch( - "homeassistant.components.homeassistant_sky_connect.async_setup_entry", - return_value=True, - ) as mock_setup_entry: - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": "usb"}, data=USB_DATA - ) - - assert result["type"] == FlowResultType.ABORT - assert result["reason"] == "already_configured" - mock_setup_entry.assert_not_called() - - -async def test_config_flow_multiple_entries(hass: HomeAssistant) -> None: +@pytest.mark.parametrize( + ("usb_data", "title"), + [ + (USB_DATA_SKY, "Home Assistant SkyConnect"), + (USB_DATA_ZBT1, "Home Assistant Connect ZBT-1"), + ], +) +async def test_config_flow_multiple_entries( + usb_data: usb.UsbServiceInfo, title: str, hass: HomeAssistant +) -> None: """Test multiple entries are allowed.""" # Setup an existing config entry config_entry = MockConfigEntry( data={}, domain=DOMAIN, options={}, - title="Home Assistant SkyConnect", - unique_id=f"{USB_DATA.vid}:{USB_DATA.pid}_{USB_DATA.serial_number}_{USB_DATA.manufacturer}_{USB_DATA.description}", + title=title, + unique_id=f"{usb_data.vid}:{usb_data.pid}_{usb_data.serial_number}_{usb_data.manufacturer}_{usb_data.description}", ) config_entry.add_to_hass(hass) - usb_data = copy.copy(USB_DATA) + usb_data = copy.copy(usb_data) usb_data.serial_number = "bla_serial_number_2" with patch( @@ -124,19 +126,28 @@ async def test_config_flow_multiple_entries(hass: HomeAssistant) -> None: assert result["type"] == FlowResultType.CREATE_ENTRY -async def test_config_flow_update_device(hass: HomeAssistant) -> None: +@pytest.mark.parametrize( + ("usb_data", "title"), + [ + (USB_DATA_SKY, "Home Assistant SkyConnect"), + (USB_DATA_ZBT1, "Home Assistant Connect ZBT-1"), + ], +) +async def test_config_flow_update_device( + usb_data: usb.UsbServiceInfo, title: str, hass: HomeAssistant +) -> None: """Test updating device path.""" # Setup an existing config entry config_entry = MockConfigEntry( data={}, domain=DOMAIN, options={}, - title="Home Assistant SkyConnect", - unique_id=f"{USB_DATA.vid}:{USB_DATA.pid}_{USB_DATA.serial_number}_{USB_DATA.manufacturer}_{USB_DATA.description}", + title=title, + unique_id=f"{usb_data.vid}:{usb_data.pid}_{usb_data.serial_number}_{usb_data.manufacturer}_{usb_data.description}", ) config_entry.add_to_hass(hass) - usb_data = copy.copy(USB_DATA) + usb_data = copy.copy(usb_data) usb_data.device = "bla_device_2" with patch( @@ -167,7 +178,16 @@ async def test_config_flow_update_device(hass: HomeAssistant) -> None: assert len(mock_unload_entry.mock_calls) == 1 +@pytest.mark.parametrize( + ("usb_data", "title"), + [ + (USB_DATA_SKY, "Home Assistant SkyConnect"), + (USB_DATA_ZBT1, "Home Assistant ZBT-1"), + ], +) async def test_option_flow_install_multi_pan_addon( + usb_data: usb.UsbServiceInfo, + title: str, hass: HomeAssistant, addon_store_info, addon_info, @@ -182,17 +202,17 @@ async def test_option_flow_install_multi_pan_addon( # Setup the config entry config_entry = MockConfigEntry( data={ - "device": USB_DATA.device, - "vid": USB_DATA.vid, - "pid": USB_DATA.pid, - "serial_number": USB_DATA.serial_number, - "manufacturer": USB_DATA.manufacturer, - "description": USB_DATA.description, + "device": usb_data.device, + "vid": usb_data.vid, + "pid": usb_data.pid, + "serial_number": usb_data.serial_number, + "manufacturer": usb_data.manufacturer, + "description": usb_data.description, }, domain=DOMAIN, options={}, - title="Home Assistant SkyConnect", - unique_id=f"{USB_DATA.vid}:{USB_DATA.pid}_{USB_DATA.serial_number}_{USB_DATA.manufacturer}_{USB_DATA.description}", + title=title, + unique_id=f"{usb_data.vid}:{usb_data.pid}_{usb_data.serial_number}_{usb_data.manufacturer}_{usb_data.description}", ) config_entry.add_to_hass(hass) @@ -226,7 +246,7 @@ async def test_option_flow_install_multi_pan_addon( { "options": { "autoflash_firmware": True, - "device": "bla_device", + "device": usb_data.device, "baudrate": "115200", "flow_control": True, } @@ -254,11 +274,20 @@ def mock_detect_radio_type(radio_type=RadioType.ezsp, ret=True): return detect +@pytest.mark.parametrize( + ("usb_data", "title"), + [ + (USB_DATA_SKY, "Home Assistant SkyConnect"), + (USB_DATA_ZBT1, "Home Assistant Connect ZBT-1"), + ], +) @patch( "homeassistant.components.zha.radio_manager.ZhaRadioManager.detect_radio_type", mock_detect_radio_type(), ) async def test_option_flow_install_multi_pan_addon_zha( + usb_data: usb.UsbServiceInfo, + title: str, hass: HomeAssistant, addon_store_info, addon_info, @@ -273,22 +302,22 @@ async def test_option_flow_install_multi_pan_addon_zha( # Setup the config entry config_entry = MockConfigEntry( data={ - "device": USB_DATA.device, - "vid": USB_DATA.vid, - "pid": USB_DATA.pid, - "serial_number": USB_DATA.serial_number, - "manufacturer": USB_DATA.manufacturer, - "description": USB_DATA.description, + "device": usb_data.device, + "vid": usb_data.vid, + "pid": usb_data.pid, + "serial_number": usb_data.serial_number, + "manufacturer": usb_data.manufacturer, + "description": usb_data.description, }, domain=DOMAIN, options={}, - title="Home Assistant SkyConnect", - unique_id=f"{USB_DATA.vid}:{USB_DATA.pid}_{USB_DATA.serial_number}_{USB_DATA.manufacturer}_{USB_DATA.description}", + title=title, + unique_id=f"{usb_data.vid}:{usb_data.pid}_{usb_data.serial_number}_{usb_data.manufacturer}_{usb_data.description}", ) config_entry.add_to_hass(hass) zha_config_entry = MockConfigEntry( - data={"device": {"path": "bla_device"}, "radio_type": "ezsp"}, + data={"device": {"path": usb_data.device}, "radio_type": "ezsp"}, domain=ZHA_DOMAIN, options={}, title="Yellow", @@ -325,7 +354,7 @@ async def test_option_flow_install_multi_pan_addon_zha( { "options": { "autoflash_firmware": True, - "device": "bla_device", + "device": usb_data.device, "baudrate": "115200", "flow_control": True, } diff --git a/tests/components/homeassistant_sky_connect/test_const.py b/tests/components/homeassistant_sky_connect/test_const.py new file mode 100644 index 00000000000..24a39270061 --- /dev/null +++ b/tests/components/homeassistant_sky_connect/test_const.py @@ -0,0 +1,27 @@ +"""Test the Home Assistant SkyConnect constants.""" + +import pytest + +from homeassistant.components.homeassistant_sky_connect.const import HardwareVariant + + +@pytest.mark.parametrize( + ("usb_product_name", "expected_variant"), + [ + ("SkyConnect v1.0", HardwareVariant.SKYCONNECT), + ("Home Assistant Connect ZBT-1", HardwareVariant.CONNECT_ZBT1), + ], +) +def test_hardware_variant( + usb_product_name: str, expected_variant: HardwareVariant +) -> None: + """Test hardware variant parsing.""" + assert HardwareVariant.from_usb_product_name(usb_product_name) == expected_variant + + +def test_hardware_variant_invalid(): + """Test hardware variant parsing with an invalid product.""" + with pytest.raises( + ValueError, match=r"^Unknown SkyConnect product name: Some other product$" + ): + HardwareVariant.from_usb_product_name("Some other product") diff --git a/tests/components/homeassistant_sky_connect/test_hardware.py b/tests/components/homeassistant_sky_connect/test_hardware.py index 079b03bbb92..6b283378045 100644 --- a/tests/components/homeassistant_sky_connect/test_hardware.py +++ b/tests/components/homeassistant_sky_connect/test_hardware.py @@ -10,21 +10,21 @@ from tests.common import MockConfigEntry from tests.typing import WebSocketGenerator CONFIG_ENTRY_DATA = { - "device": "bla_device", - "vid": "bla_vid", - "pid": "bla_pid", - "serial_number": "bla_serial_number", - "manufacturer": "bla_manufacturer", - "description": "bla_description", + "device": "/dev/serial/by-id/usb-Nabu_Casa_SkyConnect_v1.0_9e2adbd75b8beb119fe564a0f320645d-if00-port0", + "vid": "10C4", + "pid": "EA60", + "serial_number": "9e2adbd75b8beb119fe564a0f320645d", + "manufacturer": "Nabu Casa", + "description": "SkyConnect v1.0", } CONFIG_ENTRY_DATA_2 = { - "device": "bla_device_2", - "vid": "bla_vid_2", - "pid": "bla_pid_2", - "serial_number": "bla_serial_number_2", - "manufacturer": "bla_manufacturer_2", - "description": "bla_description_2", + "device": "/dev/serial/by-id/usb-Nabu_Casa_Home_Assistant_Connect_ZBT-1_9e2adbd75b8beb119fe564a0f320645d-if00-port0", + "vid": "10C4", + "pid": "EA60", + "serial_number": "9e2adbd75b8beb119fe564a0f320645d", + "manufacturer": "Nabu Casa", + "description": "Home Assistant Connect ZBT-1", } @@ -48,7 +48,7 @@ async def test_hardware_info( data=CONFIG_ENTRY_DATA_2, domain=DOMAIN, options={}, - title="Home Assistant SkyConnect", + title="Home Assistant Connect ZBT-1", unique_id="unique_2", ) config_entry_2.add_to_hass(hass) @@ -72,11 +72,11 @@ async def test_hardware_info( "board": None, "config_entries": [config_entry.entry_id], "dongle": { - "vid": "bla_vid", - "pid": "bla_pid", - "serial_number": "bla_serial_number", - "manufacturer": "bla_manufacturer", - "description": "bla_description", + "vid": "10C4", + "pid": "EA60", + "serial_number": "9e2adbd75b8beb119fe564a0f320645d", + "manufacturer": "Nabu Casa", + "description": "SkyConnect v1.0", }, "name": "Home Assistant SkyConnect", "url": "https://skyconnect.home-assistant.io/documentation/", @@ -85,13 +85,13 @@ async def test_hardware_info( "board": None, "config_entries": [config_entry_2.entry_id], "dongle": { - "vid": "bla_vid_2", - "pid": "bla_pid_2", - "serial_number": "bla_serial_number_2", - "manufacturer": "bla_manufacturer_2", - "description": "bla_description_2", + "vid": "10C4", + "pid": "EA60", + "serial_number": "9e2adbd75b8beb119fe564a0f320645d", + "manufacturer": "Nabu Casa", + "description": "Home Assistant Connect ZBT-1", }, - "name": "Home Assistant SkyConnect", + "name": "Home Assistant Connect ZBT-1", "url": "https://skyconnect.home-assistant.io/documentation/", }, ] diff --git a/tests/components/otbr/test_config_flow.py b/tests/components/otbr/test_config_flow.py index e9ad5681549..81dcb894be6 100644 --- a/tests/components/otbr/test_config_flow.py +++ b/tests/components/otbr/test_config_flow.py @@ -280,8 +280,25 @@ async def test_hassio_discovery_flow_yellow( assert config_entry.unique_id == HASSIO_DATA.uuid +@pytest.mark.parametrize( + ("device", "title"), + [ + ( + "/dev/serial/by-id/usb-Nabu_Casa_SkyConnect_v1.0_9e2adbd75b8beb119fe564a0f320645d-if00-port0", + "Home Assistant SkyConnect (Silicon Labs Multiprotocol)", + ), + ( + "/dev/serial/by-id/usb-Nabu_Casa_Home_Assistant_Connect_ZBT-1_9e2adbd75b8beb119fe564a0f320645d-if00-port0", + "Home Assistant Connect ZBT-1 (Silicon Labs Multiprotocol)", + ), + ], +) async def test_hassio_discovery_flow_sky_connect( - hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, addon_info + device: str, + title: str, + hass: HomeAssistant, + aioclient_mock: AiohttpClientMocker, + addon_info, ) -> None: """Test the hassio discovery flow.""" url = "http://core-silabs-multiprotocol:8081" @@ -290,12 +307,7 @@ async def test_hassio_discovery_flow_sky_connect( addon_info.return_value = { "available": True, "hostname": None, - "options": { - "device": ( - "/dev/serial/by-id/usb-Nabu_Casa_SkyConnect_v1.0_" - "9e2adbd75b8beb119fe564a0f320645d-if00-port0" - ) - }, + "options": {"device": device}, "state": None, "update_available": False, "version": None, @@ -314,7 +326,7 @@ async def test_hassio_discovery_flow_sky_connect( } assert result["type"] == FlowResultType.CREATE_ENTRY - assert result["title"] == "Home Assistant SkyConnect (Silicon Labs Multiprotocol)" + assert result["title"] == title assert result["data"] == expected_data assert result["options"] == {} assert len(mock_setup_entry.mock_calls) == 1 @@ -322,9 +334,7 @@ async def test_hassio_discovery_flow_sky_connect( config_entry = hass.config_entries.async_entries(otbr.DOMAIN)[0] assert config_entry.data == expected_data assert config_entry.options == {} - assert ( - config_entry.title == "Home Assistant SkyConnect (Silicon Labs Multiprotocol)" - ) + assert config_entry.title == title assert config_entry.unique_id == HASSIO_DATA.uuid diff --git a/tests/components/zha/test_repairs.py b/tests/components/zha/test_repairs.py index c164abf9b2d..fea68be86cb 100644 --- a/tests/components/zha/test_repairs.py +++ b/tests/components/zha/test_repairs.py @@ -38,6 +38,7 @@ from tests.common import MockConfigEntry from tests.typing import ClientSessionGenerator SKYCONNECT_DEVICE = "/dev/serial/by-id/usb-Nabu_Casa_SkyConnect_v1.0_9e2adbd75b8beb119fe564a0f320645d-if00-port0" +CONNECT_ZBT1_DEVICE = "/dev/serial/by-id/usb-Nabu_Casa_Home_Assistant_Connect_ZBT-1_9e2adbd75b8beb119fe564a0f320645d-if00-port0" def set_flasher_app_type(app_type: ApplicationType) -> Callable[[Flasher], None]: @@ -66,6 +67,22 @@ def test_detect_radio_hardware(hass: HomeAssistant) -> None: ) skyconnect_config_entry.add_to_hass(hass) + connect_zbt1_config_entry = MockConfigEntry( + data={ + "device": CONNECT_ZBT1_DEVICE, + "vid": "10C4", + "pid": "EA60", + "serial_number": "3c0ed67c628beb11b1cd64a0f320645d", + "manufacturer": "Nabu Casa", + "description": "Home Assistant Connect ZBT-1", + }, + domain=SKYCONNECT_DOMAIN, + options={}, + title="Home Assistant Connect ZBT-1", + ) + connect_zbt1_config_entry.add_to_hass(hass) + + assert _detect_radio_hardware(hass, CONNECT_ZBT1_DEVICE) == HardwareType.SKYCONNECT assert _detect_radio_hardware(hass, SKYCONNECT_DEVICE) == HardwareType.SKYCONNECT assert ( _detect_radio_hardware(hass, SKYCONNECT_DEVICE + "_foo") == HardwareType.OTHER