Add options flow to enable multiprotocol support on sky connect (#82525)

This commit is contained in:
Erik Montnemery 2022-11-29 22:34:55 +01:00 committed by GitHub
parent 16fc2972d3
commit b7652c78ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 962 additions and 95 deletions

View file

@ -98,6 +98,10 @@ class BaseMultiPanFlow(FlowHandler):
being migrated.
"""
@abstractmethod
def _hardware_name(self) -> str:
"""Return the name of the hardware."""
@abstractmethod
def _zha_name(self) -> str:
"""Return the ZHA name."""
@ -254,6 +258,7 @@ class OptionsFlowHandler(BaseMultiPanFlow, config_entries.OptionsFlow):
data_schema=vol.Schema(
{vol.Required(CONF_ENABLE_MULTI_PAN, default=False): bool}
),
description_placeholders={"hardware_name": self._hardware_name()},
)
if not user_input[CONF_ENABLE_MULTI_PAN]:
return self.async_create_entry(title="", data={})
@ -285,10 +290,8 @@ class OptionsFlowHandler(BaseMultiPanFlow, config_entries.OptionsFlow):
"name": self._zha_name(),
"port": {
"path": get_zigbee_socket(self.hass, addon_info),
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
"radio_type": "ezsp",
},
"old_discovery_info": await self._async_zha_physical_discovery(),
}

View file

@ -0,0 +1,43 @@
{
"silabs_multiprotocol_hardware": {
"options": {
"step": {
"addon_not_installed": {
"title": "Enable multiprotocol support on the IEEE 802.15.4 radio",
"description": "When multiprotocol support is enabled, the {hardware_name}'s IEEE 802.15.4 radio can be used for both Zigbee and Thread (used by Matter) at the same time. If the radio is already used by the ZHA Zigbee integration, ZHA will be reconfigured to use the multiprotocol firmware.\n\nNote: This is an experimental feature.",
"data": {
"enable_multi_pan": "Enable multiprotocol support"
}
},
"addon_installed_other_device": {
"title": "Multiprotocol support is already enabled for another device"
},
"install_addon": {
"title": "The Silicon Labs Multiprotocol add-on installation has started"
},
"show_revert_guide": {
"title": "Multiprotocol support is enabled for this device",
"description": "If you want to change to Zigbee only firmware, please complete the following manual steps:\n\n * Remove the Silicon Labs Multiprotocol addon\n\n * Flash the Zigbee only firmware, follow the guide at https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually.\n\n * Reconfigure ZHA to migrate settings to the reflashed radio"
},
"start_addon": {
"title": "The Silicon Labs Multiprotocol add-on is starting."
}
},
"error": {
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"abort": {
"addon_info_failed": "Failed to get Silicon Labs Multiprotocol add-on info.",
"addon_install_failed": "Failed to install the Silicon Labs Multiprotocol add-on.",
"addon_set_config_failed": "Failed to set Silicon Labs Multiprotocol configuration.",
"addon_start_failed": "Failed to start the Silicon Labs Multiprotocol add-on.",
"not_hassio": "The hardware options can only be configured on HassOS installations.",
"zha_migration_failed": "The ZHA migration did not succeed."
},
"progress": {
"install_addon": "Please wait while the Silicon Labs Multiprotocol add-on installation finishes. This can take several minutes.",
"start_addon": "Please wait while the Silicon Labs Multiprotocol add-on start completes. This may take some seconds."
}
}
}
}

View file

@ -0,0 +1,43 @@
{
"silabs_multiprotocol_hardware": {
"options": {
"abort": {
"addon_info_failed": "Failed to get Silicon Labs Multiprotocol add-on info.",
"addon_install_failed": "Failed to install the Silicon Labs Multiprotocol add-on.",
"addon_set_config_failed": "Failed to set Silicon Labs Multiprotocol configuration.",
"addon_start_failed": "Failed to start the Silicon Labs Multiprotocol add-on.",
"not_hassio": "The hardware options can only be configured on HassOS installations.",
"zha_migration_failed": "The ZHA migration did not succeed."
},
"error": {
"unknown": "Unexpected error"
},
"progress": {
"install_addon": "Please wait while the Silicon Labs Multiprotocol add-on installation finishes. This can take several minutes.",
"start_addon": "Please wait while the Silicon Labs Multiprotocol add-on start completes. This may take some seconds."
},
"step": {
"addon_installed_other_device": {
"title": "Multiprotocol support is already enabled for another device"
},
"addon_not_installed": {
"data": {
"enable_multi_pan": "Enable multiprotocol support"
},
"description": "When multiprotocol support is enabled, the {hardware_name}'s IEEE 802.15.4 radio can be used for both Zigbee and Thread (used by Matter) at the same time. If the radio is already used by the ZHA Zigbee integration, ZHA will be reconfigured to use the multiprotocol firmware.\n\nNote: This is an experimental feature.",
"title": "Enable multiprotocol support on the IEEE 802.15.4 radio"
},
"install_addon": {
"title": "The Silicon Labs Multiprotocol add-on installation has started"
},
"show_revert_guide": {
"description": "If you want to change to Zigbee only firmware, please complete the following manual steps:\n\n * Remove the Silicon Labs Multiprotocol addon\n\n * Flash the Zigbee only firmware, follow the guide at https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually.\n\n * Reconfigure ZHA to migrate settings to the reflashed radio",
"title": "Multiprotocol support is enabled for this device"
},
"start_addon": {
"title": "The Silicon Labs Multiprotocol add-on is starting."
}
}
}
}
}

View file

@ -1,12 +1,63 @@
"""The Home Assistant Sky Connect integration."""
from __future__ import annotations
import logging
from homeassistant.components import usb
from homeassistant.components.hassio import (
AddonError,
AddonInfo,
AddonManager,
AddonState,
is_hassio,
)
from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon import (
get_addon_manager,
get_zigbee_socket,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from .const import DOMAIN
from .util import get_usb_service_info
_LOGGER = logging.getLogger(__name__)
async def _multi_pan_addon_info(hass, entry: ConfigEntry) -> AddonInfo | None:
"""Return AddonInfo if the multi-PAN addon is enabled for our SkyConnect."""
if not is_hassio(hass):
return None
addon_manager: AddonManager = get_addon_manager(hass)
try:
addon_info: AddonInfo = await addon_manager.async_get_addon_info()
except AddonError as err:
_LOGGER.error(err)
raise ConfigEntryNotReady from err
# Start the addon if it's not started
if addon_info.state == AddonState.NOT_RUNNING:
await addon_manager.async_start_addon()
if addon_info.state not in (AddonState.NOT_INSTALLED, AddonState.RUNNING):
_LOGGER.debug(
"Multi pan addon in state %s, delaying yellow config entry setup",
addon_info.state,
)
raise ConfigEntryNotReady
if addon_info.state == AddonState.NOT_INSTALLED:
return None
usb_dev = entry.data["device"]
dev_path = await hass.async_add_executor_job(usb.get_serial_by_id, usb_dev)
if addon_info.options["device"] != dev_path:
return None
return addon_info
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
@ -24,19 +75,28 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# The USB dongle is not plugged in
raise ConfigEntryNotReady
usb_info = usb.UsbServiceInfo(
device=entry.data["device"],
vid=entry.data["vid"],
pid=entry.data["pid"],
serial_number=entry.data["serial_number"],
manufacturer=entry.data["manufacturer"],
description=entry.data["description"],
)
addon_info = await _multi_pan_addon_info(hass, entry)
if not addon_info:
usb_info = get_usb_service_info(entry)
await hass.config_entries.flow.async_init(
"zha",
context={"source": "usb"},
data=usb_info,
)
return True
hw_discovery_data = {
"name": "Sky Connect Multi-PAN",
"port": {
"path": get_zigbee_socket(hass, addon_info),
},
"radio_type": "ezsp",
}
await hass.config_entries.flow.async_init(
"zha",
context={"source": "usb"},
data=usb_info,
context={"source": "hardware"},
data=hw_discovery_data,
)
return True

View file

@ -1,11 +1,16 @@
"""Config flow for the Home Assistant Sky Connect integration."""
from __future__ import annotations
from typing import Any
from homeassistant.components import usb
from homeassistant.config_entries import ConfigFlow
from homeassistant.components.homeassistant_hardware import silabs_multiprotocol_addon
from homeassistant.config_entries import ConfigEntry, ConfigFlow
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from .const import DOMAIN
from .util import get_usb_service_info
class HomeAssistantSkyConnectConfigFlow(ConfigFlow, domain=DOMAIN):
@ -13,6 +18,14 @@ class HomeAssistantSkyConnectConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1
@staticmethod
@callback
def async_get_options_flow(
config_entry: ConfigEntry,
) -> HomeAssistantSkyConnectOptionsFlow:
"""Return the options flow."""
return HomeAssistantSkyConnectOptionsFlow(config_entry)
async def async_step_usb(self, discovery_info: usb.UsbServiceInfo) -> FlowResult:
"""Handle usb discovery."""
device = discovery_info.device
@ -35,3 +48,35 @@ class HomeAssistantSkyConnectConfigFlow(ConfigFlow, domain=DOMAIN):
"description": description,
},
)
class HomeAssistantSkyConnectOptionsFlow(silabs_multiprotocol_addon.OptionsFlowHandler):
"""Handle an option flow for Home Assistant Sky Connect."""
async def _async_serial_port_settings(
self,
) -> silabs_multiprotocol_addon.SerialPortSettings:
"""Return the radio serial port settings."""
usb_dev = self.config_entry.data["device"]
dev_path = await self.hass.async_add_executor_job(usb.get_serial_by_id, usb_dev)
return silabs_multiprotocol_addon.SerialPortSettings(
device=dev_path,
baudrate="115200",
flow_control=True,
)
async def _async_zha_physical_discovery(self) -> dict[str, Any]:
"""Return ZHA discovery data when multiprotocol FW is not used.
Passed to ZHA do determine if the ZHA config entry is connected to the radio
being migrated.
"""
return {"usb": get_usb_service_info(self.config_entry)}
def _zha_name(self) -> str:
"""Return the ZHA name."""
return "Sky Connect Multi-PAN"
def _hardware_name(self) -> str:
"""Return the name of the hardware."""
return "Home Assistant Sky Connect"

View file

@ -3,7 +3,7 @@
"name": "Home Assistant Sky Connect",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/homeassistant_sky_connect",
"dependencies": ["hardware", "usb"],
"dependencies": ["hardware", "usb", "homeassistant_hardware"],
"codeowners": ["@home-assistant/core"],
"integration_type": "hardware",
"usb": [

View file

@ -0,0 +1,41 @@
{
"options": {
"step": {
"addon_not_installed": {
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_not_installed::title%]",
"description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_not_installed::description%]",
"data": {
"enable_multi_pan": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_not_installed::data::enable_multi_pan%]"
}
},
"addon_installed_other_device": {
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_installed_other_device::title%]"
},
"install_addon": {
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::install_addon::title%]"
},
"show_revert_guide": {
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::show_revert_guide::title%]",
"description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::show_revert_guide::description%]"
},
"start_addon": {
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::start_addon::title%]"
}
},
"error": {
"unknown": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::error::unknown%]"
},
"abort": {
"addon_info_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_info_failed%]",
"addon_install_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_install_failed%]",
"addon_set_config_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_set_config_failed%]",
"addon_start_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_start_failed%]",
"not_hassio": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::not_hassio%]",
"zha_migration_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::zha_migration_failed%]"
},
"progress": {
"install_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::progress::install_addon%]",
"start_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::progress::start_addon%]"
}
}
}

View file

@ -0,0 +1,41 @@
{
"options": {
"abort": {
"addon_info_failed": "Failed to get Silicon Labs Multiprotocol add-on info.",
"addon_install_failed": "Failed to install the Silicon Labs Multiprotocol add-on.",
"addon_set_config_failed": "Failed to set Silicon Labs Multiprotocol configuration.",
"addon_start_failed": "Failed to start the Silicon Labs Multiprotocol add-on.",
"not_hassio": "The hardware options can only be configured on HassOS installations.",
"zha_migration_failed": "The ZHA migration did not succeed."
},
"error": {
"unknown": "Unexpected error"
},
"progress": {
"install_addon": "Please wait while the Silicon Labs Multiprotocol add-on installation finishes. This can take several minutes.",
"start_addon": "Please wait while the Silicon Labs Multiprotocol add-on start completes. This may take some seconds."
},
"step": {
"addon_installed_other_device": {
"title": "Multiprotocol support is already enabled for another device"
},
"addon_not_installed": {
"data": {
"enable_multi_pan": "Enable multiprotocol support"
},
"description": "When multiprotocol support is enabled, the {hardware_name}'s IEEE 802.15.4 radio can be used for both Zigbee and Thread (used by Matter) at the same time. If the radio is already used by the ZHA Zigbee integration, ZHA will be reconfigured to use the multiprotocol firmware.\n\nNote: This is an experimental feature.",
"title": "Enable multiprotocol support on the IEEE 802.15.4 radio"
},
"install_addon": {
"title": "The Silicon Labs Multiprotocol add-on installation has started"
},
"show_revert_guide": {
"description": "If you want to change to Zigbee only firmware, please complete the following manual steps:\n\n * Remove the Silicon Labs Multiprotocol addon\n\n * Flash the Zigbee only firmware, follow the guide at https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually.\n\n * Reconfigure ZHA to migrate settings to the reflashed radio",
"title": "Multiprotocol support is enabled for this device"
},
"start_addon": {
"title": "The Silicon Labs Multiprotocol add-on is starting."
}
}
}
}

View file

@ -0,0 +1,17 @@
"""Utility functions for Home Assistant Sky Connect integration."""
from __future__ import annotations
from homeassistant.components import usb
from homeassistant.config_entries import ConfigEntry
def get_usb_service_info(config_entry: ConfigEntry) -> usb.UsbServiceInfo:
"""Return UsbServiceInfo."""
return usb.UsbServiceInfo(
device=config_entry.data["device"],
vid=config_entry.data["vid"],
pid=config_entry.data["pid"],
serial_number=config_entry.data["serial_number"],
manufacturer=config_entry.data["manufacturer"],
description=config_entry.data["description"],
)

View file

@ -73,10 +73,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"name": "Yellow Multi-PAN",
"port": {
"path": get_zigbee_socket(hass, addon_info),
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
"radio_type": "ezsp",
}
await hass.config_entries.flow.async_init(

View file

@ -51,8 +51,12 @@ class HomeAssistantYellowOptionsFlow(silabs_multiprotocol_addon.OptionsFlowHandl
Passed to ZHA do determine if the ZHA config entry is connected to the radio
being migrated.
"""
return ZHA_HW_DISCOVERY_DATA
return {"hw": ZHA_HW_DISCOVERY_DATA}
def _zha_name(self) -> str:
"""Return the ZHA name."""
return "Yellow Multi-PAN"
def _hardware_name(self) -> str:
"""Return the name of the hardware."""
return "Home Assistant Yellow"

View file

@ -2,40 +2,40 @@
"options": {
"step": {
"addon_not_installed": {
"title": "Enable multiprotocol support on the IEEE 802.15.4 radio",
"description": "When multiprotocol support is enabled, the Home Assistant Yellow's IEEE 802.15.4 radio can be used for both Zigbee and Thread (used by Matter) at the same time. If the radio is already used by the ZHA Zigbee integration, ZHA will be reconfigured to use the multiprotocol firmware.\n\nNote: This is an experimental feature.",
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_not_installed::title%]",
"description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_not_installed::description%]",
"data": {
"enable_multi_pan": "Enable multiprotocol support"
"enable_multi_pan": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_not_installed::data::enable_multi_pan%]"
}
},
"addon_installed_other_device": {
"title": "Multiprotocol support is already enabled for another device"
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_installed_other_device::title%]"
},
"install_addon": {
"title": "The Silicon Labs Multiprotocol add-on installation has started"
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::install_addon::title%]"
},
"show_revert_guide": {
"title": "Multiprotocol support is enabled for this device",
"description": "If you want to change to Zigbee only firmware, please complete the following manual steps:\n\n * Remove the Silicon Labs Multiprotocol addon\n\n * Flash the Zigbee only firmware, follow the guide at https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually.\n\n * Reconfigure ZHA to migrate settings to the reflashed radio"
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::show_revert_guide::title%]",
"description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::show_revert_guide::description%]"
},
"start_addon": {
"title": "The Silicon Labs Multiprotocol add-on is starting."
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::start_addon::title%]"
}
},
"error": {
"unknown": "[%key:common::config_flow::error::unknown%]"
"unknown": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::error::unknown%]"
},
"abort": {
"addon_info_failed": "Failed to get Silicon Labs Multiprotocol add-on info.",
"addon_install_failed": "Failed to install the Silicon Labs Multiprotocol add-on.",
"addon_set_config_failed": "Failed to set Silicon Labs Multiprotocol configuration.",
"addon_start_failed": "Failed to start the Silicon Labs Multiprotocol add-on.",
"not_hassio": "The hardware options can only be configured on HassOS installations.",
"zha_migration_failed": "The ZHA migration did not succeed."
"addon_info_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_info_failed%]",
"addon_install_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_install_failed%]",
"addon_set_config_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_set_config_failed%]",
"addon_start_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::addon_start_failed%]",
"not_hassio": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::not_hassio%]",
"zha_migration_failed": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::abort::zha_migration_failed%]"
},
"progress": {
"install_addon": "Please wait while the Silicon Labs Multiprotocol add-on installation finishes. This can take several minutes.",
"start_addon": "Please wait while the Silicon Labs Multiprotocol add-on start completes. This may take some seconds."
"install_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::progress::install_addon%]",
"start_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::progress::start_addon%]"
}
}
}

View file

@ -23,7 +23,7 @@
"data": {
"enable_multi_pan": "Enable multiprotocol support"
},
"description": "When multiprotocol support is enabled, the Home Assistant Yellow's IEEE 802.15.4 radio can be used for both Zigbee and Thread (used by Matter) at the same time. If the radio is already used by the ZHA Zigbee integration, ZHA will be reconfigured to use the multiprotocol firmware.\n\nNote: This is an experimental feature.",
"description": "When multiprotocol support is enabled, the {hardware_name}'s IEEE 802.15.4 radio can be used for both Zigbee and Thread (used by Matter) at the same time. If the radio is already used by the ZHA Zigbee integration, ZHA will be reconfigured to use the multiprotocol firmware.\n\nNote: This is an experimental feature.",
"title": "Enable multiprotocol support on the IEEE 802.15.4 radio"
},
"install_addon": {

View file

@ -15,6 +15,7 @@ from zigpy.config import CONF_DEVICE, CONF_DEVICE_PATH
from zigpy.exceptions import NetworkNotFormed
from homeassistant import config_entries
from homeassistant.components import usb
from homeassistant.core import HomeAssistant
from .core.const import (
@ -53,7 +54,12 @@ HARDWARE_DISCOVERY_SCHEMA = vol.Schema(
HARDWARE_MIGRATION_SCHEMA = vol.Schema(
{
vol.Required("new_discovery_info"): HARDWARE_DISCOVERY_SCHEMA,
vol.Required("old_discovery_info"): HARDWARE_DISCOVERY_SCHEMA,
vol.Required("old_discovery_info"): vol.Schema(
{
vol.Exclusive("hw", "discovery"): HARDWARE_DISCOVERY_SCHEMA,
vol.Exclusive("usb", "discovery"): usb.UsbServiceInfo,
}
),
}
)
@ -297,21 +303,20 @@ class ZhaMultiPANMigrationHelper:
new_radio_type = ZhaRadioManager.parse_radio_type(
migration_data["new_discovery_info"]["radio_type"]
)
old_radio_type = ZhaRadioManager.parse_radio_type(
migration_data["old_discovery_info"]["radio_type"]
)
new_device_settings = new_radio_type.controller.SCHEMA_DEVICE(
migration_data["new_discovery_info"]["port"]
)
old_device_settings = old_radio_type.controller.SCHEMA_DEVICE(
migration_data["old_discovery_info"]["port"]
)
if (
self._config_entry.data[CONF_DEVICE][CONF_DEVICE_PATH]
!= old_device_settings[CONF_DEVICE_PATH]
):
if "hw" in migration_data["old_discovery_info"]:
old_device_path = migration_data["old_discovery_info"]["hw"]["port"]["path"]
else: # usb
device = migration_data["old_discovery_info"]["usb"].device
old_device_path = await self._hass.async_add_executor_job(
usb.get_serial_by_id, device
)
if self._config_entry.data[CONF_DEVICE][CONF_DEVICE_PATH] != old_device_path:
# ZHA is using another radio, do nothing
return False
@ -322,11 +327,12 @@ class ZhaMultiPANMigrationHelper:
pass
# Temporarily connect to the old radio to read its settings
config_entry_data = self._config_entry.data
old_radio_mgr = ZhaRadioManager()
old_radio_mgr.hass = self._hass
old_radio_mgr.radio_type = old_radio_type
old_radio_mgr.device_path = old_device_settings[CONF_DEVICE_PATH]
old_radio_mgr.device_settings = old_device_settings
old_radio_mgr.device_path = config_entry_data[CONF_DEVICE][CONF_DEVICE_PATH]
old_radio_mgr.device_settings = config_entry_data[CONF_DEVICE]
old_radio_mgr.radio_type = RadioType[config_entry_data[CONF_RADIO_TYPE]]
backup = await old_radio_mgr.async_load_network_settings(create_backup=True)
# Then configure the radio manager for the new radio to use the new settings

View file

@ -275,6 +275,22 @@ def gen_auth_schema(config: Config, integration: Integration) -> vol.Schema:
)
def gen_ha_hardware_schema(config: Config, integration: Integration):
"""Generate auth schema."""
return vol.Schema(
{
str: {
vol.Optional("options"): gen_data_entry_schema(
config=config,
integration=integration,
flow_title=UNDEFINED,
require_step_title=False,
)
}
}
)
def gen_platform_strings_schema(config: Config, integration: Integration) -> vol.Schema:
"""Generate platform strings schema like strings.sensor.json.
@ -351,6 +367,8 @@ def validate_translation_file( # noqa: C901
)
}
)
elif integration.domain == "homeassistant_hardware":
strings_schema = gen_ha_hardware_schema(config, integration)
else:
strings_schema = gen_strings_schema(config, integration)

View file

@ -61,13 +61,15 @@ class TestOptionsFlow(silabs_multiprotocol_addon.OptionsFlowHandler):
being migrated.
"""
return {
"name": "Test",
"port": {
"path": "/dev/ttyTEST123",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
"hw": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST123",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
}
}
def _zha_name(self) -> str:
@ -223,8 +225,8 @@ async def test_option_flow_install_multi_pan_addon_zha(
assert zha_config_entry.data == {
"device": {
"path": "socket://core-silabs-multiprotocol:9999",
"baudrate": 115200,
"flow_control": "hardware",
"baudrate": 57600, # ZHA default
"flow_control": "software", # ZHA default
},
"radio_type": "ezsp",
}

View file

@ -1,14 +1,138 @@
"""Test fixtures for the Home Assistant Sky Connect integration."""
from unittest.mock import patch
from collections.abc import Generator
from unittest.mock import MagicMock, patch
import pytest
@pytest.fixture(name="mock_usb_serial_by_id", autouse=True)
def mock_usb_serial_by_id_fixture() -> Generator[MagicMock, None, None]:
"""Mock usb serial by id."""
with patch(
"homeassistant.components.zwave_js.config_flow.usb.get_serial_by_id"
) as mock_usb_serial_by_id:
mock_usb_serial_by_id.side_effect = lambda x: x
yield mock_usb_serial_by_id
@pytest.fixture(autouse=True)
def mock_zha():
"""Mock the zha integration."""
mock_connect_app = MagicMock()
mock_connect_app.__aenter__.return_value.backups.backups = [MagicMock()]
mock_connect_app.__aenter__.return_value.backups.create_backup.return_value = (
MagicMock()
)
with patch(
"homeassistant.components.zha.radio_manager.ZhaRadioManager._connect_zigpy_app",
return_value=mock_connect_app,
), patch(
"homeassistant.components.zha.async_setup_entry",
return_value=True,
):
yield
@pytest.fixture(name="addon_running")
def mock_addon_running(addon_store_info, addon_info):
"""Mock add-on already running."""
addon_store_info.return_value = {
"installed": "1.0.0",
"state": "started",
"version": "1.0.0",
}
addon_info.return_value["hostname"] = "core-silabs-multiprotocol"
addon_info.return_value["state"] = "started"
addon_info.return_value["version"] = "1.0.0"
return addon_info
@pytest.fixture(name="addon_installed")
def mock_addon_installed(addon_store_info, addon_info):
"""Mock add-on already installed but not running."""
addon_store_info.return_value = {
"installed": "1.0.0",
"state": "stopped",
"version": "1.0.0",
}
addon_info.return_value["hostname"] = "core-silabs-multiprotocol"
addon_info.return_value["state"] = "stopped"
addon_info.return_value["version"] = "1.0.0"
return addon_info
@pytest.fixture(name="addon_store_info")
def addon_store_info_fixture():
"""Mock Supervisor add-on store info."""
with patch(
"homeassistant.components.hassio.addon_manager.async_get_addon_store_info"
) as addon_store_info:
addon_store_info.return_value = {
"installed": None,
"state": None,
"version": "1.0.0",
}
yield addon_store_info
@pytest.fixture(name="addon_info")
def addon_info_fixture():
"""Mock Supervisor add-on info."""
with patch(
"homeassistant.components.hassio.addon_manager.async_get_addon_info",
) as addon_info:
addon_info.return_value = {
"hostname": None,
"options": {},
"state": None,
"update_available": False,
"version": None,
}
yield addon_info
@pytest.fixture(name="set_addon_options")
def set_addon_options_fixture():
"""Mock set add-on options."""
with patch(
"homeassistant.components.hassio.addon_manager.async_set_addon_options"
) as set_options:
yield set_options
@pytest.fixture(name="install_addon_side_effect")
def install_addon_side_effect_fixture(addon_store_info, addon_info):
"""Return the install add-on side effect."""
async def install_addon(hass, slug):
"""Mock install add-on."""
addon_store_info.return_value = {
"installed": "1.0.0",
"state": "stopped",
"version": "1.0.0",
}
addon_info.return_value["hostname"] = "core-silabs-multiprotocol"
addon_info.return_value["state"] = "stopped"
addon_info.return_value["version"] = "1.0.0"
return install_addon
@pytest.fixture(name="install_addon")
def mock_install_addon(install_addon_side_effect):
"""Mock install add-on."""
with patch(
"homeassistant.components.hassio.addon_manager.async_install_addon",
side_effect=install_addon_side_effect,
) as install_addon:
yield install_addon
@pytest.fixture(name="start_addon")
def start_addon_fixture():
"""Mock start add-on."""
with patch(
"homeassistant.components.hassio.addon_manager.async_start_addon"
) as start_addon:
yield start_addon

View file

@ -1,13 +1,18 @@
"""Test the Home Assistant Sky Connect config flow."""
import copy
from unittest.mock import patch
from unittest.mock import Mock, patch
from homeassistant.components import homeassistant_sky_connect, usb
from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
from homeassistant.components.zha.core.const import (
CONF_DEVICE_PATH,
DOMAIN as ZHA_DOMAIN,
RadioType,
)
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
from tests.common import MockConfigEntry, MockModule, mock_integration
USB_DATA = usb.UsbServiceInfo(
device="bla_device",
@ -143,3 +148,190 @@ async def test_config_flow_update_device(hass: HomeAssistant) -> None:
assert result["reason"] == "already_configured"
assert len(mock_setup_entry.mock_calls) == 1
assert len(mock_unload_entry.mock_calls) == 1
async def test_option_flow_install_multi_pan_addon(
hass: HomeAssistant,
addon_store_info,
addon_info,
install_addon,
set_addon_options,
start_addon,
) -> None:
"""Test installing the multi pan addon."""
mock_integration(hass, MockModule("hassio"))
# 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,
},
domain=DOMAIN,
options={},
title="Home Assistant Sky Connect",
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_hardware.silabs_multiprotocol_addon.is_hassio",
side_effect=Mock(return_value=True),
):
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "addon_not_installed"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
"enable_multi_pan": True,
},
)
assert result["type"] == FlowResultType.SHOW_PROGRESS
assert result["step_id"] == "install_addon"
assert result["progress_action"] == "install_addon"
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.SHOW_PROGRESS_DONE
assert result["step_id"] == "configure_addon"
install_addon.assert_called_once_with(hass, "core_silabs_multiprotocol")
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.SHOW_PROGRESS
assert result["step_id"] == "start_addon"
set_addon_options.assert_called_once_with(
hass,
"core_silabs_multiprotocol",
{
"options": {
"autoflash_firmware": True,
"device": "bla_device",
"baudrate": "115200",
"flow_control": True,
}
},
)
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.SHOW_PROGRESS_DONE
assert result["step_id"] == "finish_addon_setup"
start_addon.assert_called_once_with(hass, "core_silabs_multiprotocol")
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.CREATE_ENTRY
def mock_detect_radio_type(radio_type=RadioType.ezsp, ret=True):
"""Mock `detect_radio_type` that just sets the appropriate attributes."""
async def detect(self):
self.radio_type = radio_type
self.device_settings = radio_type.controller.SCHEMA_DEVICE(
{CONF_DEVICE_PATH: self.device_path}
)
return ret
return detect
@patch(
"homeassistant.components.zha.radio_manager.ZhaRadioManager.detect_radio_type",
mock_detect_radio_type(),
)
async def test_option_flow_install_multi_pan_addon_zha(
hass: HomeAssistant,
addon_store_info,
addon_info,
install_addon,
set_addon_options,
start_addon,
) -> None:
"""Test installing the multi pan addon when a zha config entry exists."""
mock_integration(hass, MockModule("hassio"))
# 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,
},
domain=DOMAIN,
options={},
title="Home Assistant Sky Connect",
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"},
domain=ZHA_DOMAIN,
options={},
title="Yellow",
)
zha_config_entry.add_to_hass(hass)
with patch(
"homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon.is_hassio",
side_effect=Mock(return_value=True),
):
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "addon_not_installed"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
"enable_multi_pan": True,
},
)
assert result["type"] == FlowResultType.SHOW_PROGRESS
assert result["step_id"] == "install_addon"
assert result["progress_action"] == "install_addon"
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.SHOW_PROGRESS_DONE
assert result["step_id"] == "configure_addon"
install_addon.assert_called_once_with(hass, "core_silabs_multiprotocol")
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.SHOW_PROGRESS
assert result["step_id"] == "start_addon"
set_addon_options.assert_called_once_with(
hass,
"core_silabs_multiprotocol",
{
"options": {
"autoflash_firmware": True,
"device": "bla_device",
"baudrate": "115200",
"flow_control": True,
}
},
)
# Check the ZHA config entry data is updated
assert zha_config_entry.data == {
"device": {
"path": "socket://core-silabs-multiprotocol:9999",
"baudrate": 57600, # ZHA default
"flow_control": "software", # ZHA default
},
"radio_type": "ezsp",
}
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.SHOW_PROGRESS_DONE
assert result["step_id"] == "finish_addon_setup"
start_addon.assert_called_once_with(hass, "core_silabs_multiprotocol")
result = await hass.config_entries.options.async_configure(result["flow_id"])
assert result["type"] == FlowResultType.CREATE_ENTRY

View file

@ -4,7 +4,7 @@ from unittest.mock import patch
from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
from tests.common import MockConfigEntry, MockModule, mock_integration
CONFIG_ENTRY_DATA = {
"device": "bla_device",
@ -25,8 +25,12 @@ CONFIG_ENTRY_DATA_2 = {
}
async def test_hardware_info(hass: HomeAssistant, hass_ws_client) -> None:
async def test_hardware_info(
hass: HomeAssistant, hass_ws_client, addon_store_info
) -> None:
"""Test we can get the board info."""
mock_integration(hass, MockModule("usb"))
# Setup the config entry
config_entry = MockConfigEntry(
data=CONFIG_ENTRY_DATA,

View file

@ -1,11 +1,12 @@
"""Test the Home Assistant Sky Connect integration."""
from collections.abc import Generator
from typing import Any
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, Mock, patch
import pytest
from homeassistant.components import zha
from homeassistant.components.hassio.handler import HassioAPIError
from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
@ -46,7 +47,12 @@ def mock_zha_config_flow_setup() -> Generator[None, None, None]:
"onboarded, num_entries, num_flows", ((False, 1, 0), (True, 0, 1))
)
async def test_setup_entry(
mock_zha_config_flow_setup, hass: HomeAssistant, onboarded, num_entries, num_flows
mock_zha_config_flow_setup,
hass: HomeAssistant,
addon_store_info,
onboarded,
num_entries,
num_flows,
) -> None:
"""Test setup of a config entry, including setup of zha."""
# Setup the config entry
@ -90,7 +96,9 @@ async def test_setup_entry(
assert len(hass.config_entries.async_entries("zha")) == num_entries
async def test_setup_zha(mock_zha_config_flow_setup, hass: HomeAssistant) -> None:
async def test_setup_zha(
mock_zha_config_flow_setup, hass: HomeAssistant, addon_store_info
) -> None:
"""Test zha gets the right config."""
# Setup the config entry
config_entry = MockConfigEntry(
@ -134,6 +142,108 @@ async def test_setup_zha(mock_zha_config_flow_setup, hass: HomeAssistant) -> Non
assert config_entry.title == CONFIG_ENTRY_DATA["description"]
async def test_setup_zha_multipan(
hass: HomeAssistant, addon_info, addon_running
) -> None:
"""Test zha gets the right config."""
addon_info.return_value["options"]["device"] = CONFIG_ENTRY_DATA["device"]
# Setup the config entry
config_entry = MockConfigEntry(
data=CONFIG_ENTRY_DATA,
domain=DOMAIN,
options={},
title="Home Assistant Sky Connect",
)
config_entry.add_to_hass(hass)
with patch(
"homeassistant.components.homeassistant_sky_connect.usb.async_is_plugged_in",
return_value=True,
) as mock_is_plugged_in, patch(
"homeassistant.components.onboarding.async_is_onboarded", return_value=False
), patch(
"homeassistant.components.homeassistant_sky_connect.is_hassio",
side_effect=Mock(return_value=True),
):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert len(mock_is_plugged_in.mock_calls) == 1
# Finish setting up ZHA
zha_flows = hass.config_entries.flow.async_progress_by_handler("zha")
assert len(zha_flows) == 1
assert zha_flows[0]["step_id"] == "choose_formation_strategy"
await hass.config_entries.flow.async_configure(
zha_flows[0]["flow_id"],
user_input={"next_step_id": zha.config_flow.FORMATION_REUSE_SETTINGS},
)
await hass.async_block_till_done()
config_entry = hass.config_entries.async_entries("zha")[0]
assert config_entry.data == {
"device": {
"baudrate": 57600, # ZHA default
"flow_control": "software", # ZHA default
"path": "socket://core-silabs-multiprotocol:9999",
},
"radio_type": "ezsp",
}
assert config_entry.options == {}
assert config_entry.title == "Sky Connect Multi-PAN"
async def test_setup_zha_multipan_other_device(
mock_zha_config_flow_setup, hass: HomeAssistant, addon_info, addon_running
) -> None:
"""Test zha gets the right config."""
addon_info.return_value["options"]["device"] = "/dev/not_our_sky_connect"
# Setup the config entry
config_entry = MockConfigEntry(
data=CONFIG_ENTRY_DATA,
domain=DOMAIN,
options={},
title="Home Assistant Yellow",
)
config_entry.add_to_hass(hass)
with patch(
"homeassistant.components.homeassistant_sky_connect.usb.async_is_plugged_in",
return_value=True,
) as mock_is_plugged_in, patch(
"homeassistant.components.onboarding.async_is_onboarded", return_value=False
), patch(
"homeassistant.components.homeassistant_sky_connect.is_hassio",
side_effect=Mock(return_value=True),
):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert len(mock_is_plugged_in.mock_calls) == 1
# Finish setting up ZHA
zha_flows = hass.config_entries.flow.async_progress_by_handler("zha")
assert len(zha_flows) == 1
assert zha_flows[0]["step_id"] == "choose_formation_strategy"
await hass.config_entries.flow.async_configure(
zha_flows[0]["flow_id"],
user_input={"next_step_id": zha.config_flow.FORMATION_REUSE_SETTINGS},
)
await hass.async_block_till_done()
config_entry = hass.config_entries.async_entries("zha")[0]
assert config_entry.data == {
"device": {
"baudrate": 115200,
"flow_control": "software",
"path": CONFIG_ENTRY_DATA["device"],
},
"radio_type": "ezsp",
}
assert config_entry.options == {}
assert config_entry.title == CONFIG_ENTRY_DATA["description"]
async def test_setup_entry_wait_usb(hass: HomeAssistant) -> None:
"""Test setup of a config entry when the dongle is not plugged in."""
# Setup the config entry
@ -152,3 +262,58 @@ async def test_setup_entry_wait_usb(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
assert len(mock_is_plugged_in.mock_calls) == 1
assert config_entry.state == ConfigEntryState.SETUP_RETRY
async def test_setup_entry_addon_info_fails(
hass: HomeAssistant, addon_store_info
) -> None:
"""Test setup of a config entry when fetching addon info fails."""
addon_store_info.side_effect = HassioAPIError("Boom")
# Setup the config entry
config_entry = MockConfigEntry(
data=CONFIG_ENTRY_DATA,
domain=DOMAIN,
options={},
title="Home Assistant Sky Connect",
)
config_entry.add_to_hass(hass)
with patch(
"homeassistant.components.homeassistant_sky_connect.usb.async_is_plugged_in",
return_value=True,
), patch(
"homeassistant.components.onboarding.async_is_onboarded", return_value=False
), patch(
"homeassistant.components.homeassistant_sky_connect.is_hassio",
side_effect=Mock(return_value=True),
):
assert not await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state == ConfigEntryState.SETUP_RETRY
async def test_setup_entry_addon_not_running(
hass: HomeAssistant, addon_installed, start_addon
) -> None:
"""Test the addon is started if it is not running."""
# Setup the config entry
config_entry = MockConfigEntry(
data=CONFIG_ENTRY_DATA,
domain=DOMAIN,
options={},
title="Home Assistant Sky Connect",
)
config_entry.add_to_hass(hass)
with patch(
"homeassistant.components.homeassistant_sky_connect.usb.async_is_plugged_in",
return_value=True,
), patch(
"homeassistant.components.onboarding.async_is_onboarded", return_value=False
), patch(
"homeassistant.components.homeassistant_sky_connect.is_hassio",
side_effect=Mock(return_value=True),
):
assert not await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state == ConfigEntryState.SETUP_RETRY
start_addon.assert_called_once()

View file

@ -197,8 +197,8 @@ async def test_option_flow_install_multi_pan_addon_zha(
assert zha_config_entry.data == {
"device": {
"path": "socket://core-silabs-multiprotocol:9999",
"baudrate": 115200,
"flow_control": "hardware",
"baudrate": 57600, # ZHA default
"flow_control": "software", # ZHA default
},
"radio_type": "ezsp",
}

View file

@ -144,8 +144,8 @@ async def test_setup_zha_multipan(
config_entry = hass.config_entries.async_entries("zha")[0]
assert config_entry.data == {
"device": {
"baudrate": 115200,
"flow_control": "hardware",
"baudrate": 57600, # ZHA default
"flow_control": "software", # ZHA default
"path": "socket://core-silabs-multiprotocol:9999",
},
"radio_type": "ezsp",

View file

@ -11,6 +11,7 @@ from zigpy.config import CONF_DEVICE_PATH
import zigpy.types
from homeassistant import config_entries
from homeassistant.components.usb import UsbServiceInfo
from homeassistant.components.zha import radio_manager
from homeassistant.components.zha.core.const import DOMAIN, RadioType
from homeassistant.core import HomeAssistant
@ -125,14 +126,68 @@ async def test_migrate_matching_port(
"radio_type": "efr32",
},
"old_discovery_info": {
"name": "Test",
"hw": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST123",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
}
},
}
migration_helper = radio_manager.ZhaMultiPANMigrationHelper(hass, config_entry)
assert await migration_helper.async_initiate_migration(migration_data)
# Check the ZHA config entry data is updated
assert config_entry.data == {
"device": {
"path": "socket://some/virtual_port",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "ezsp",
}
assert config_entry.title == "Test Updated"
await migration_helper.async_finish_migration()
@patch(
"homeassistant.components.zha.radio_manager.ZhaRadioManager.detect_radio_type",
mock_detect_radio_type(),
)
@patch("homeassistant.components.zha.async_setup_entry", AsyncMock(return_value=True))
async def test_migrate_matching_port_usb(
hass: HomeAssistant,
mock_connect_zigpy_app,
) -> None:
"""Test automatic migration."""
# Setup the config entry
config_entry = MockConfigEntry(
data={"device": {"path": "/dev/ttyTEST123"}, "radio_type": "ezsp"},
domain=DOMAIN,
options={},
title="Test",
version=3,
)
config_entry.add_to_hass(hass)
migration_data = {
"new_discovery_info": {
"name": "Test Updated",
"port": {
"path": "/dev/ttyTEST123",
"path": "socket://some/virtual_port",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
},
"old_discovery_info": {
"usb": UsbServiceInfo("/dev/ttyTEST123", "blah", "blah", None, None, None)
},
}
migration_helper = radio_manager.ZhaMultiPANMigrationHelper(hass, config_entry)
@ -178,13 +233,15 @@ async def test_migrate_matching_port_config_entry_not_loaded(
"radio_type": "efr32",
},
"old_discovery_info": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST123",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
"hw": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST123",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
}
},
}
@ -236,13 +293,15 @@ async def test_migrate_matching_port_retry(
"radio_type": "efr32",
},
"old_discovery_info": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST123",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
"hw": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST123",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
}
},
}
@ -290,13 +349,15 @@ async def test_migrate_non_matching_port(
"radio_type": "efr32",
},
"old_discovery_info": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST456",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
"hw": {
"name": "Test",
"port": {
"path": "/dev/ttyTEST456",
"baudrate": 115200,
"flow_control": "hardware",
},
"radio_type": "efr32",
}
},
}