mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 06:47:09 +00:00
Migrate homeassistant_hardware
to use FirmwareInfo
instead of just the application type (#138874)
* Migrate `self._probed_firmware_type` to `self._probed_firmware_info` * Migrate from `firmware_type` to the full `firmware_info` * Implement `probe_silabs_firmware_type` via `probe_silabs_firmware_info` * Fix unit tests * Increase coverage * Bring test coverage to 100% * Simplify test per review comment
This commit is contained in:
parent
508b6c8db0
commit
debee25086
@ -28,12 +28,13 @@ from . import silabs_multiprotocol_addon
|
|||||||
from .const import OTBR_DOMAIN, ZHA_DOMAIN
|
from .const import OTBR_DOMAIN, ZHA_DOMAIN
|
||||||
from .util import (
|
from .util import (
|
||||||
ApplicationType,
|
ApplicationType,
|
||||||
|
FirmwareInfo,
|
||||||
OwningAddon,
|
OwningAddon,
|
||||||
OwningIntegration,
|
OwningIntegration,
|
||||||
get_otbr_addon_manager,
|
get_otbr_addon_manager,
|
||||||
get_zigbee_flasher_addon_manager,
|
get_zigbee_flasher_addon_manager,
|
||||||
guess_hardware_owners,
|
guess_hardware_owners,
|
||||||
probe_silabs_firmware_type,
|
probe_silabs_firmware_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -52,7 +53,7 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
"""Instantiate base flow."""
|
"""Instantiate base flow."""
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
self._probed_firmware_type: ApplicationType | None = None
|
self._probed_firmware_info: FirmwareInfo | None = None
|
||||||
self._device: str | None = None # To be set in a subclass
|
self._device: str | None = None # To be set in a subclass
|
||||||
self._hardware_name: str = "unknown" # To be set in a subclass
|
self._hardware_name: str = "unknown" # To be set in a subclass
|
||||||
|
|
||||||
@ -64,8 +65,8 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
"""Shared translation placeholders."""
|
"""Shared translation placeholders."""
|
||||||
placeholders = {
|
placeholders = {
|
||||||
"firmware_type": (
|
"firmware_type": (
|
||||||
self._probed_firmware_type.value
|
self._probed_firmware_info.firmware_type.value
|
||||||
if self._probed_firmware_type is not None
|
if self._probed_firmware_info is not None
|
||||||
else "unknown"
|
else "unknown"
|
||||||
),
|
),
|
||||||
"model": self._hardware_name,
|
"model": self._hardware_name,
|
||||||
@ -120,39 +121,49 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
description_placeholders=self._get_translation_placeholders(),
|
description_placeholders=self._get_translation_placeholders(),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _probe_firmware_type(self) -> bool:
|
async def _probe_firmware_info(
|
||||||
"""Probe the firmware currently on the device."""
|
self,
|
||||||
assert self._device is not None
|
probe_methods: tuple[ApplicationType, ...] = (
|
||||||
|
# We probe in order of frequency: Zigbee, Thread, then multi-PAN
|
||||||
self._probed_firmware_type = await probe_silabs_firmware_type(
|
ApplicationType.GECKO_BOOTLOADER,
|
||||||
self._device,
|
|
||||||
probe_methods=(
|
|
||||||
# We probe in order of frequency: Zigbee, Thread, then multi-PAN
|
|
||||||
ApplicationType.GECKO_BOOTLOADER,
|
|
||||||
ApplicationType.EZSP,
|
|
||||||
ApplicationType.SPINEL,
|
|
||||||
ApplicationType.CPC,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
return self._probed_firmware_type in (
|
|
||||||
ApplicationType.EZSP,
|
ApplicationType.EZSP,
|
||||||
ApplicationType.SPINEL,
|
ApplicationType.SPINEL,
|
||||||
ApplicationType.CPC,
|
ApplicationType.CPC,
|
||||||
|
),
|
||||||
|
) -> bool:
|
||||||
|
"""Probe the firmware currently on the device."""
|
||||||
|
assert self._device is not None
|
||||||
|
|
||||||
|
self._probed_firmware_info = await probe_silabs_firmware_info(
|
||||||
|
self._device,
|
||||||
|
probe_methods=probe_methods,
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
self._probed_firmware_info is not None
|
||||||
|
and self._probed_firmware_info.firmware_type
|
||||||
|
in (
|
||||||
|
ApplicationType.EZSP,
|
||||||
|
ApplicationType.SPINEL,
|
||||||
|
ApplicationType.CPC,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_pick_firmware_zigbee(
|
async def async_step_pick_firmware_zigbee(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
"""Pick Zigbee firmware."""
|
"""Pick Zigbee firmware."""
|
||||||
if not await self._probe_firmware_type():
|
if not await self._probe_firmware_info():
|
||||||
return self.async_abort(
|
return self.async_abort(
|
||||||
reason="unsupported_firmware",
|
reason="unsupported_firmware",
|
||||||
description_placeholders=self._get_translation_placeholders(),
|
description_placeholders=self._get_translation_placeholders(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Allow the stick to be used with ZHA without flashing
|
# Allow the stick to be used with ZHA without flashing
|
||||||
if self._probed_firmware_type == ApplicationType.EZSP:
|
if (
|
||||||
|
self._probed_firmware_info is not None
|
||||||
|
and self._probed_firmware_info.firmware_type == ApplicationType.EZSP
|
||||||
|
):
|
||||||
return await self.async_step_confirm_zigbee()
|
return await self.async_step_confirm_zigbee()
|
||||||
|
|
||||||
if not is_hassio(self.hass):
|
if not is_hassio(self.hass):
|
||||||
@ -338,7 +349,12 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
"""Confirm Zigbee setup."""
|
"""Confirm Zigbee setup."""
|
||||||
assert self._device is not None
|
assert self._device is not None
|
||||||
assert self._hardware_name is not None
|
assert self._hardware_name is not None
|
||||||
self._probed_firmware_type = ApplicationType.EZSP
|
|
||||||
|
if not await self._probe_firmware_info(probe_methods=(ApplicationType.EZSP,)):
|
||||||
|
return self.async_abort(
|
||||||
|
reason="unsupported_firmware",
|
||||||
|
description_placeholders=self._get_translation_placeholders(),
|
||||||
|
)
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
await self.hass.config_entries.flow.async_init(
|
await self.hass.config_entries.flow.async_init(
|
||||||
@ -366,7 +382,7 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
"""Pick Thread firmware."""
|
"""Pick Thread firmware."""
|
||||||
if not await self._probe_firmware_type():
|
if not await self._probe_firmware_info():
|
||||||
return self.async_abort(
|
return self.async_abort(
|
||||||
reason="unsupported_firmware",
|
reason="unsupported_firmware",
|
||||||
description_placeholders=self._get_translation_placeholders(),
|
description_placeholders=self._get_translation_placeholders(),
|
||||||
@ -458,7 +474,11 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
"""Confirm OTBR setup."""
|
"""Confirm OTBR setup."""
|
||||||
assert self._device is not None
|
assert self._device is not None
|
||||||
|
|
||||||
self._probed_firmware_type = ApplicationType.SPINEL
|
if not await self._probe_firmware_info(probe_methods=(ApplicationType.SPINEL,)):
|
||||||
|
return self.async_abort(
|
||||||
|
reason="unsupported_firmware",
|
||||||
|
description_placeholders=self._get_translation_placeholders(),
|
||||||
|
)
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
# OTBR discovery is done automatically via hassio
|
# OTBR discovery is done automatically via hassio
|
||||||
@ -497,14 +517,14 @@ class BaseFirmwareConfigFlow(BaseFirmwareInstallFlow, ConfigFlow):
|
|||||||
class BaseFirmwareOptionsFlow(BaseFirmwareInstallFlow, OptionsFlow):
|
class BaseFirmwareOptionsFlow(BaseFirmwareInstallFlow, OptionsFlow):
|
||||||
"""Zigbee and Thread options flow handlers."""
|
"""Zigbee and Thread options flow handlers."""
|
||||||
|
|
||||||
|
_probed_firmware_info: FirmwareInfo
|
||||||
|
|
||||||
def __init__(self, config_entry: ConfigEntry, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, config_entry: ConfigEntry, *args: Any, **kwargs: Any) -> None:
|
||||||
"""Instantiate options flow."""
|
"""Instantiate options flow."""
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
self._config_entry = config_entry
|
self._config_entry = config_entry
|
||||||
|
|
||||||
self._probed_firmware_type = ApplicationType(self.config_entry.data["firmware"])
|
|
||||||
|
|
||||||
# Make `context` a regular dictionary
|
# Make `context` a regular dictionary
|
||||||
self.context = {}
|
self.context = {}
|
||||||
|
|
||||||
|
@ -249,10 +249,10 @@ async def guess_firmware_info(hass: HomeAssistant, device_path: str) -> Firmware
|
|||||||
return guesses[-1][0]
|
return guesses[-1][0]
|
||||||
|
|
||||||
|
|
||||||
async def probe_silabs_firmware_type(
|
async def probe_silabs_firmware_info(
|
||||||
device: str, *, probe_methods: Iterable[ApplicationType] | None = None
|
device: str, *, probe_methods: Iterable[ApplicationType] | None = None
|
||||||
) -> ApplicationType | None:
|
) -> FirmwareInfo | None:
|
||||||
"""Probe the running firmware on a Silabs device."""
|
"""Probe the running firmware on a SiLabs device."""
|
||||||
flasher = Flasher(
|
flasher = Flasher(
|
||||||
device=device,
|
device=device,
|
||||||
**(
|
**(
|
||||||
@ -270,4 +270,26 @@ async def probe_silabs_firmware_type(
|
|||||||
if flasher.app_type is None:
|
if flasher.app_type is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return ApplicationType.from_flasher_application_type(flasher.app_type)
|
return FirmwareInfo(
|
||||||
|
device=device,
|
||||||
|
firmware_type=ApplicationType.from_flasher_application_type(flasher.app_type),
|
||||||
|
firmware_version=(
|
||||||
|
flasher.app_version.orig_version
|
||||||
|
if flasher.app_version is not None
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
source="probe",
|
||||||
|
owners=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def probe_silabs_firmware_type(
|
||||||
|
device: str, *, probe_methods: Iterable[ApplicationType] | None = None
|
||||||
|
) -> ApplicationType | None:
|
||||||
|
"""Probe the running firmware type on a SiLabs device."""
|
||||||
|
|
||||||
|
fw_info = await probe_silabs_firmware_info(device, probe_methods=probe_methods)
|
||||||
|
if fw_info is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return fw_info.firmware_type
|
||||||
|
@ -10,7 +10,10 @@ from homeassistant.components.homeassistant_hardware import (
|
|||||||
firmware_config_flow,
|
firmware_config_flow,
|
||||||
silabs_multiprotocol_addon,
|
silabs_multiprotocol_addon,
|
||||||
)
|
)
|
||||||
from homeassistant.components.homeassistant_hardware.util import ApplicationType
|
from homeassistant.components.homeassistant_hardware.util import (
|
||||||
|
ApplicationType,
|
||||||
|
FirmwareInfo,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import (
|
from homeassistant.config_entries import (
|
||||||
ConfigEntry,
|
ConfigEntry,
|
||||||
ConfigEntryBaseFlow,
|
ConfigEntryBaseFlow,
|
||||||
@ -118,7 +121,7 @@ class HomeAssistantSkyConnectConfigFlow(
|
|||||||
"""Create the config entry."""
|
"""Create the config entry."""
|
||||||
assert self._usb_info is not None
|
assert self._usb_info is not None
|
||||||
assert self._hw_variant is not None
|
assert self._hw_variant is not None
|
||||||
assert self._probed_firmware_type is not None
|
assert self._probed_firmware_info is not None
|
||||||
|
|
||||||
return self.async_create_entry(
|
return self.async_create_entry(
|
||||||
title=self._hw_variant.full_name,
|
title=self._hw_variant.full_name,
|
||||||
@ -130,7 +133,7 @@ class HomeAssistantSkyConnectConfigFlow(
|
|||||||
"description": self._usb_info.description, # For backwards compatibility
|
"description": self._usb_info.description, # For backwards compatibility
|
||||||
"product": self._usb_info.description,
|
"product": self._usb_info.description,
|
||||||
"device": self._usb_info.device,
|
"device": self._usb_info.device,
|
||||||
"firmware": self._probed_firmware_type.value,
|
"firmware": self._probed_firmware_info.firmware_type.value,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -203,18 +206,26 @@ class HomeAssistantSkyConnectOptionsFlowHandler(
|
|||||||
self._hardware_name = self._hw_variant.full_name
|
self._hardware_name = self._hw_variant.full_name
|
||||||
self._device = self._usb_info.device
|
self._device = self._usb_info.device
|
||||||
|
|
||||||
|
self._probed_firmware_info = FirmwareInfo(
|
||||||
|
device=self._device,
|
||||||
|
firmware_type=ApplicationType(self.config_entry.data["firmware"]),
|
||||||
|
firmware_version=None,
|
||||||
|
source="guess",
|
||||||
|
owners=[],
|
||||||
|
)
|
||||||
|
|
||||||
# Regenerate the translation placeholders
|
# Regenerate the translation placeholders
|
||||||
self._get_translation_placeholders()
|
self._get_translation_placeholders()
|
||||||
|
|
||||||
def _async_flow_finished(self) -> ConfigFlowResult:
|
def _async_flow_finished(self) -> ConfigFlowResult:
|
||||||
"""Create the config entry."""
|
"""Create the config entry."""
|
||||||
assert self._probed_firmware_type is not None
|
assert self._probed_firmware_info is not None
|
||||||
|
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
entry=self.config_entry,
|
entry=self.config_entry,
|
||||||
data={
|
data={
|
||||||
**self.config_entry.data,
|
**self.config_entry.data,
|
||||||
"firmware": self._probed_firmware_type.value,
|
"firmware": self._probed_firmware_info.firmware_type.value,
|
||||||
},
|
},
|
||||||
options=self.config_entry.options,
|
options=self.config_entry.options,
|
||||||
)
|
)
|
||||||
|
@ -24,7 +24,10 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
|
|||||||
OptionsFlowHandler as MultiprotocolOptionsFlowHandler,
|
OptionsFlowHandler as MultiprotocolOptionsFlowHandler,
|
||||||
SerialPortSettings as MultiprotocolSerialPortSettings,
|
SerialPortSettings as MultiprotocolSerialPortSettings,
|
||||||
)
|
)
|
||||||
from homeassistant.components.homeassistant_hardware.util import ApplicationType
|
from homeassistant.components.homeassistant_hardware.util import (
|
||||||
|
ApplicationType,
|
||||||
|
FirmwareInfo,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import (
|
from homeassistant.config_entries import (
|
||||||
SOURCE_HARDWARE,
|
SOURCE_HARDWARE,
|
||||||
ConfigEntry,
|
ConfigEntry,
|
||||||
@ -79,10 +82,13 @@ class HomeAssistantYellowConfigFlow(BaseFirmwareConfigFlow, domain=DOMAIN):
|
|||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
"""Handle the initial step."""
|
"""Handle the initial step."""
|
||||||
# We do not actually use any portion of `BaseFirmwareConfigFlow` beyond this
|
# We do not actually use any portion of `BaseFirmwareConfigFlow` beyond this
|
||||||
await self._probe_firmware_type()
|
await self._probe_firmware_info()
|
||||||
|
|
||||||
# Kick off ZHA hardware discovery automatically if Zigbee firmware is running
|
# Kick off ZHA hardware discovery automatically if Zigbee firmware is running
|
||||||
if self._probed_firmware_type is ApplicationType.EZSP:
|
if (
|
||||||
|
self._probed_firmware_info is not None
|
||||||
|
and self._probed_firmware_info.firmware_type is ApplicationType.EZSP
|
||||||
|
):
|
||||||
discovery_flow.async_create_flow(
|
discovery_flow.async_create_flow(
|
||||||
self.hass,
|
self.hass,
|
||||||
ZHA_DOMAIN,
|
ZHA_DOMAIN,
|
||||||
@ -98,7 +104,11 @@ class HomeAssistantYellowConfigFlow(BaseFirmwareConfigFlow, domain=DOMAIN):
|
|||||||
title=BOARD_NAME,
|
title=BOARD_NAME,
|
||||||
data={
|
data={
|
||||||
# Assume the firmware type is EZSP if we cannot probe it
|
# Assume the firmware type is EZSP if we cannot probe it
|
||||||
FIRMWARE: (self._probed_firmware_type or ApplicationType.EZSP).value,
|
FIRMWARE: (
|
||||||
|
self._probed_firmware_info.firmware_type
|
||||||
|
if self._probed_firmware_info is not None
|
||||||
|
else ApplicationType.EZSP
|
||||||
|
).value,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -264,6 +274,14 @@ class HomeAssistantYellowOptionsFlowHandler(
|
|||||||
self._hardware_name = BOARD_NAME
|
self._hardware_name = BOARD_NAME
|
||||||
self._device = RADIO_DEVICE
|
self._device = RADIO_DEVICE
|
||||||
|
|
||||||
|
self._probed_firmware_info = FirmwareInfo(
|
||||||
|
device=self._device,
|
||||||
|
firmware_type=ApplicationType(self.config_entry.data["firmware"]),
|
||||||
|
firmware_version=None,
|
||||||
|
source="guess",
|
||||||
|
owners=[],
|
||||||
|
)
|
||||||
|
|
||||||
# Regenerate the translation placeholders
|
# Regenerate the translation placeholders
|
||||||
self._get_translation_placeholders()
|
self._get_translation_placeholders()
|
||||||
|
|
||||||
@ -285,13 +303,13 @@ class HomeAssistantYellowOptionsFlowHandler(
|
|||||||
|
|
||||||
def _async_flow_finished(self) -> ConfigFlowResult:
|
def _async_flow_finished(self) -> ConfigFlowResult:
|
||||||
"""Create the config entry."""
|
"""Create the config entry."""
|
||||||
assert self._probed_firmware_type is not None
|
assert self._probed_firmware_info is not None
|
||||||
|
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
entry=self.config_entry,
|
entry=self.config_entry,
|
||||||
data={
|
data={
|
||||||
**self.config_entry.data,
|
**self.config_entry.data,
|
||||||
FIRMWARE: self._probed_firmware_type.value,
|
FIRMWARE: self._probed_firmware_info.firmware_type.value,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ from homeassistant.components.homeassistant_hardware.firmware_config_flow import
|
|||||||
)
|
)
|
||||||
from homeassistant.components.homeassistant_hardware.util import (
|
from homeassistant.components.homeassistant_hardware.util import (
|
||||||
ApplicationType,
|
ApplicationType,
|
||||||
|
FirmwareInfo,
|
||||||
get_otbr_addon_manager,
|
get_otbr_addon_manager,
|
||||||
get_zigbee_flasher_addon_manager,
|
get_zigbee_flasher_addon_manager,
|
||||||
)
|
)
|
||||||
@ -65,13 +66,13 @@ class FakeFirmwareConfigFlow(BaseFirmwareConfigFlow, domain=TEST_DOMAIN):
|
|||||||
"""Create the config entry."""
|
"""Create the config entry."""
|
||||||
assert self._device is not None
|
assert self._device is not None
|
||||||
assert self._hardware_name is not None
|
assert self._hardware_name is not None
|
||||||
assert self._probed_firmware_type is not None
|
assert self._probed_firmware_info is not None
|
||||||
|
|
||||||
return self.async_create_entry(
|
return self.async_create_entry(
|
||||||
title=self._hardware_name,
|
title=self._hardware_name,
|
||||||
data={
|
data={
|
||||||
"device": self._device,
|
"device": self._device,
|
||||||
"firmware": self._probed_firmware_type.value,
|
"firmware": self._probed_firmware_info.firmware_type.value,
|
||||||
"hardware": self._hardware_name,
|
"hardware": self._hardware_name,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -87,18 +88,26 @@ class FakeFirmwareOptionsFlowHandler(BaseFirmwareOptionsFlow):
|
|||||||
self._device = self.config_entry.data["device"]
|
self._device = self.config_entry.data["device"]
|
||||||
self._hardware_name = self.config_entry.data["hardware"]
|
self._hardware_name = self.config_entry.data["hardware"]
|
||||||
|
|
||||||
|
self._probed_firmware_info = FirmwareInfo(
|
||||||
|
device=self._device,
|
||||||
|
firmware_type=ApplicationType(self.config_entry.data["firmware"]),
|
||||||
|
firmware_version=None,
|
||||||
|
source="guess",
|
||||||
|
owners=[],
|
||||||
|
)
|
||||||
|
|
||||||
# Regenerate the translation placeholders
|
# Regenerate the translation placeholders
|
||||||
self._get_translation_placeholders()
|
self._get_translation_placeholders()
|
||||||
|
|
||||||
def _async_flow_finished(self) -> ConfigFlowResult:
|
def _async_flow_finished(self) -> ConfigFlowResult:
|
||||||
"""Create the config entry."""
|
"""Create the config entry."""
|
||||||
assert self._probed_firmware_type is not None
|
assert self._probed_firmware_info is not None
|
||||||
|
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
entry=self.config_entry,
|
entry=self.config_entry,
|
||||||
data={
|
data={
|
||||||
**self.config_entry.data,
|
**self.config_entry.data,
|
||||||
"firmware": self._probed_firmware_type.value,
|
"firmware": self._probed_firmware_info.firmware_type.value,
|
||||||
},
|
},
|
||||||
options=self.config_entry.options,
|
options=self.config_entry.options,
|
||||||
)
|
)
|
||||||
@ -142,7 +151,7 @@ def mock_addon_info(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
*,
|
*,
|
||||||
is_hassio: bool = True,
|
is_hassio: bool = True,
|
||||||
app_type: ApplicationType = ApplicationType.EZSP,
|
app_type: ApplicationType | None = ApplicationType.EZSP,
|
||||||
otbr_addon_info: AddonInfo = AddonInfo(
|
otbr_addon_info: AddonInfo = AddonInfo(
|
||||||
available=True,
|
available=True,
|
||||||
hostname=None,
|
hostname=None,
|
||||||
@ -187,6 +196,17 @@ def mock_addon_info(
|
|||||||
)
|
)
|
||||||
mock_otbr_manager.async_get_addon_info.return_value = otbr_addon_info
|
mock_otbr_manager.async_get_addon_info.return_value = otbr_addon_info
|
||||||
|
|
||||||
|
if app_type is None:
|
||||||
|
firmware_info_result = None
|
||||||
|
else:
|
||||||
|
firmware_info_result = FirmwareInfo(
|
||||||
|
device="/dev/ttyUSB0", # Not used
|
||||||
|
firmware_type=app_type,
|
||||||
|
firmware_version=None,
|
||||||
|
owners=[],
|
||||||
|
source="probe",
|
||||||
|
)
|
||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.components.homeassistant_hardware.firmware_config_flow.get_otbr_addon_manager",
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.get_otbr_addon_manager",
|
||||||
@ -209,8 +229,8 @@ def mock_addon_info(
|
|||||||
return_value=is_hassio,
|
return_value=is_hassio,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_type",
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
|
||||||
return_value=app_type,
|
return_value=firmware_info_result,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
yield mock_otbr_manager, mock_flasher_manager
|
yield mock_otbr_manager, mock_flasher_manager
|
||||||
@ -274,10 +294,14 @@ async def test_config_flow_zigbee(hass: HomeAssistant) -> None:
|
|||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm_zigbee"
|
assert result["step_id"] == "confirm_zigbee"
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
with mock_addon_info(
|
||||||
result["flow_id"], user_input={}
|
hass,
|
||||||
)
|
app_type=ApplicationType.EZSP,
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
config_entry = result["result"]
|
config_entry = result["result"]
|
||||||
assert config_entry.data == {
|
assert config_entry.data == {
|
||||||
@ -347,10 +371,14 @@ async def test_config_flow_zigbee_skip_step_if_installed(hass: HomeAssistant) ->
|
|||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
with mock_addon_info(
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
hass,
|
||||||
assert result["type"] is FlowResultType.FORM
|
app_type=ApplicationType.EZSP,
|
||||||
assert result["step_id"] == "confirm_zigbee"
|
):
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||||
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "confirm_zigbee"
|
||||||
|
|
||||||
|
|
||||||
async def test_config_flow_thread(hass: HomeAssistant) -> None:
|
async def test_config_flow_thread(hass: HomeAssistant) -> None:
|
||||||
@ -419,17 +447,21 @@ async def test_config_flow_thread(hass: HomeAssistant) -> None:
|
|||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm_otbr"
|
assert result["step_id"] == "confirm_otbr"
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
with mock_addon_info(
|
||||||
result["flow_id"], user_input={}
|
hass,
|
||||||
)
|
app_type=ApplicationType.SPINEL,
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
config_entry = result["result"]
|
config_entry = result["result"]
|
||||||
assert config_entry.data == {
|
assert config_entry.data == {
|
||||||
"firmware": "spinel",
|
"firmware": "spinel",
|
||||||
"device": TEST_DEVICE,
|
"device": TEST_DEVICE,
|
||||||
"hardware": TEST_HARDWARE_NAME,
|
"hardware": TEST_HARDWARE_NAME,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_config_flow_thread_addon_already_installed(hass: HomeAssistant) -> None:
|
async def test_config_flow_thread_addon_already_installed(hass: HomeAssistant) -> None:
|
||||||
@ -477,10 +509,14 @@ async def test_config_flow_thread_addon_already_installed(hass: HomeAssistant) -
|
|||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm_otbr"
|
assert result["step_id"] == "confirm_otbr"
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
with mock_addon_info(
|
||||||
result["flow_id"], user_input={}
|
hass,
|
||||||
)
|
app_type=ApplicationType.SPINEL,
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
|
|
||||||
async def test_config_flow_zigbee_not_hassio(hass: HomeAssistant) -> None:
|
async def test_config_flow_zigbee_not_hassio(hass: HomeAssistant) -> None:
|
||||||
@ -501,10 +537,10 @@ async def test_config_flow_zigbee_not_hassio(hass: HomeAssistant) -> None:
|
|||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm_zigbee"
|
assert result["step_id"] == "confirm_zigbee"
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
result["flow_id"], user_input={}
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
config_entry = result["result"]
|
config_entry = result["result"]
|
||||||
assert config_entry.data == {
|
assert config_entry.data == {
|
||||||
@ -538,17 +574,17 @@ async def test_options_flow_zigbee_to_thread(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
# First step is confirmation
|
|
||||||
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
|
||||||
assert result["type"] is FlowResultType.MENU
|
|
||||||
assert result["step_id"] == "pick_firmware"
|
|
||||||
assert result["description_placeholders"]["firmware_type"] == "ezsp"
|
|
||||||
assert result["description_placeholders"]["model"] == TEST_HARDWARE_NAME
|
|
||||||
|
|
||||||
with mock_addon_info(
|
with mock_addon_info(
|
||||||
hass,
|
hass,
|
||||||
app_type=ApplicationType.EZSP,
|
app_type=ApplicationType.EZSP,
|
||||||
) as (mock_otbr_manager, mock_flasher_manager):
|
) as (mock_otbr_manager, mock_flasher_manager):
|
||||||
|
# First step is confirmation
|
||||||
|
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||||
|
assert result["type"] is FlowResultType.MENU
|
||||||
|
assert result["step_id"] == "pick_firmware"
|
||||||
|
assert result["description_placeholders"]["firmware_type"] == "ezsp"
|
||||||
|
assert result["description_placeholders"]["model"] == TEST_HARDWARE_NAME
|
||||||
|
|
||||||
result = await hass.config_entries.options.async_configure(
|
result = await hass.config_entries.options.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
||||||
@ -599,14 +635,18 @@ async def test_options_flow_zigbee_to_thread(hass: HomeAssistant) -> None:
|
|||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm_otbr"
|
assert result["step_id"] == "confirm_otbr"
|
||||||
|
|
||||||
# We are now done
|
with mock_addon_info(
|
||||||
result = await hass.config_entries.options.async_configure(
|
hass,
|
||||||
result["flow_id"], user_input={}
|
app_type=ApplicationType.SPINEL,
|
||||||
)
|
):
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
# We are now done
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
# The firmware type has been updated
|
# The firmware type has been updated
|
||||||
assert config_entry.data["firmware"] == "spinel"
|
assert config_entry.data["firmware"] == "spinel"
|
||||||
|
|
||||||
|
|
||||||
async def test_options_flow_thread_to_zigbee(hass: HomeAssistant) -> None:
|
async def test_options_flow_thread_to_zigbee(hass: HomeAssistant) -> None:
|
||||||
@ -680,11 +720,15 @@ async def test_options_flow_thread_to_zigbee(hass: HomeAssistant) -> None:
|
|||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm_zigbee"
|
assert result["step_id"] == "confirm_zigbee"
|
||||||
|
|
||||||
# We are now done
|
with mock_addon_info(
|
||||||
result = await hass.config_entries.options.async_configure(
|
hass,
|
||||||
result["flow_id"], user_input={}
|
app_type=ApplicationType.EZSP,
|
||||||
)
|
):
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
# We are now done
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
# The firmware type has been updated
|
# The firmware type has been updated
|
||||||
assert config_entry.data["firmware"] == "ezsp"
|
assert config_entry.data["firmware"] == "ezsp"
|
||||||
|
@ -309,6 +309,42 @@ async def test_config_flow_zigbee_flasher_uninstall_fails(hass: HomeAssistant) -
|
|||||||
assert result["step_id"] == "confirm_zigbee"
|
assert result["step_id"] == "confirm_zigbee"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"ignore_translations",
|
||||||
|
["component.test_firmware_domain.config.abort.unsupported_firmware"],
|
||||||
|
)
|
||||||
|
async def test_config_flow_zigbee_confirmation_fails(hass: HomeAssistant) -> None:
|
||||||
|
"""Test the config flow failing due to Zigbee firmware not being detected."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
TEST_DOMAIN, context={"source": "hardware"}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] is FlowResultType.MENU
|
||||||
|
assert result["step_id"] == "pick_firmware"
|
||||||
|
|
||||||
|
with mock_addon_info(
|
||||||
|
hass,
|
||||||
|
app_type=ApplicationType.EZSP,
|
||||||
|
) as (mock_otbr_manager, mock_flasher_manager):
|
||||||
|
# Pick the menu option: we are now installing the addon
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={"next_step_id": STEP_PICK_FIRMWARE_ZIGBEE},
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "confirm_zigbee"
|
||||||
|
|
||||||
|
with mock_addon_info(
|
||||||
|
hass,
|
||||||
|
app_type=None, # Probing fails
|
||||||
|
) as (mock_otbr_manager, mock_flasher_manager):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.ABORT
|
||||||
|
assert result["reason"] == "unsupported_firmware"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"ignore_translations",
|
"ignore_translations",
|
||||||
["component.test_firmware_domain.config.abort.not_hassio_thread"],
|
["component.test_firmware_domain.config.abort.not_hassio_thread"],
|
||||||
@ -530,6 +566,48 @@ async def test_config_flow_thread_flasher_uninstall_fails(hass: HomeAssistant) -
|
|||||||
assert result["step_id"] == "confirm_otbr"
|
assert result["step_id"] == "confirm_otbr"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"ignore_translations",
|
||||||
|
["component.test_firmware_domain.config.abort.unsupported_firmware"],
|
||||||
|
)
|
||||||
|
async def test_config_flow_thread_confirmation_fails(hass: HomeAssistant) -> None:
|
||||||
|
"""Test the config flow failing due to OpenThread firmware not being detected."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
TEST_DOMAIN, context={"source": "hardware"}
|
||||||
|
)
|
||||||
|
|
||||||
|
with mock_addon_info(
|
||||||
|
hass,
|
||||||
|
app_type=ApplicationType.EZSP,
|
||||||
|
) as (mock_otbr_manager, mock_flasher_manager):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
||||||
|
)
|
||||||
|
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||||
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "confirm_otbr"
|
||||||
|
|
||||||
|
with mock_addon_info(
|
||||||
|
hass,
|
||||||
|
app_type=None, # Probing fails
|
||||||
|
) as (mock_otbr_manager, mock_flasher_manager):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.ABORT
|
||||||
|
assert result["reason"] == "unsupported_firmware"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"ignore_translations",
|
"ignore_translations",
|
||||||
["component.test_firmware_domain.options.abort.zha_still_using_stick"],
|
["component.test_firmware_domain.options.abort.zha_still_using_stick"],
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from universal_silabs_flasher.common import Version as FlasherVersion
|
||||||
|
from universal_silabs_flasher.const import ApplicationType as FlasherApplicationType
|
||||||
|
|
||||||
from homeassistant.components.hassio import (
|
from homeassistant.components.hassio import (
|
||||||
AddonError,
|
AddonError,
|
||||||
AddonInfo,
|
AddonInfo,
|
||||||
@ -18,6 +22,8 @@ from homeassistant.components.homeassistant_hardware.util import (
|
|||||||
OwningIntegration,
|
OwningIntegration,
|
||||||
get_otbr_addon_firmware_info,
|
get_otbr_addon_firmware_info,
|
||||||
guess_firmware_info,
|
guess_firmware_info,
|
||||||
|
probe_silabs_firmware_info,
|
||||||
|
probe_silabs_firmware_type,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
|
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -280,3 +286,95 @@ async def test_get_otbr_addon_firmware_info_failure_bad_options(
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (await get_otbr_addon_firmware_info(hass, otbr_addon_manager)) is None
|
assert (await get_otbr_addon_firmware_info(hass, otbr_addon_manager)) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("app_type", "firmware_version", "expected_fw_info"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
FlasherApplicationType.EZSP,
|
||||||
|
FlasherVersion("1.0.0"),
|
||||||
|
FirmwareInfo(
|
||||||
|
device="/dev/ttyUSB0",
|
||||||
|
firmware_type=ApplicationType.EZSP,
|
||||||
|
firmware_version="1.0.0",
|
||||||
|
source="probe",
|
||||||
|
owners=[],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FlasherApplicationType.EZSP,
|
||||||
|
None,
|
||||||
|
FirmwareInfo(
|
||||||
|
device="/dev/ttyUSB0",
|
||||||
|
firmware_type=ApplicationType.EZSP,
|
||||||
|
firmware_version=None,
|
||||||
|
source="probe",
|
||||||
|
owners=[],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FlasherApplicationType.SPINEL,
|
||||||
|
FlasherVersion("2.0.0"),
|
||||||
|
FirmwareInfo(
|
||||||
|
device="/dev/ttyUSB0",
|
||||||
|
firmware_type=ApplicationType.SPINEL,
|
||||||
|
firmware_version="2.0.0",
|
||||||
|
source="probe",
|
||||||
|
owners=[],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(None, None, None),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_probe_silabs_firmware_info(
|
||||||
|
app_type: FlasherApplicationType | None,
|
||||||
|
firmware_version: FlasherVersion | None,
|
||||||
|
expected_fw_info: FirmwareInfo | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test getting the firmware info."""
|
||||||
|
|
||||||
|
def probe_app_type() -> None:
|
||||||
|
mock_flasher.app_type = app_type
|
||||||
|
mock_flasher.app_version = firmware_version
|
||||||
|
|
||||||
|
mock_flasher = MagicMock()
|
||||||
|
mock_flasher.app_type = None
|
||||||
|
mock_flasher.app_version = None
|
||||||
|
mock_flasher.probe_app_type = AsyncMock(side_effect=probe_app_type)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homeassistant_hardware.util.Flasher",
|
||||||
|
return_value=mock_flasher,
|
||||||
|
):
|
||||||
|
result = await probe_silabs_firmware_info("/dev/ttyUSB0")
|
||||||
|
assert result == expected_fw_info
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("probe_result", "expected"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
FirmwareInfo(
|
||||||
|
device="/dev/ttyUSB0",
|
||||||
|
firmware_type=ApplicationType.EZSP,
|
||||||
|
firmware_version=None,
|
||||||
|
source="unknown",
|
||||||
|
owners=[],
|
||||||
|
),
|
||||||
|
ApplicationType.EZSP,
|
||||||
|
),
|
||||||
|
(None, None),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_probe_silabs_firmware_type(
|
||||||
|
probe_result: FirmwareInfo | None, expected: ApplicationType | None
|
||||||
|
) -> None:
|
||||||
|
"""Test getting the firmware type from the probe result."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.homeassistant_hardware.util.probe_silabs_firmware_info",
|
||||||
|
autospec=True,
|
||||||
|
return_value=probe_result,
|
||||||
|
):
|
||||||
|
result = await probe_silabs_firmware_type("/dev/ttyUSB0")
|
||||||
|
assert result == expected
|
||||||
|
@ -13,6 +13,10 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
|
|||||||
get_flasher_addon_manager,
|
get_flasher_addon_manager,
|
||||||
get_multiprotocol_addon_manager,
|
get_multiprotocol_addon_manager,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.homeassistant_hardware.util import (
|
||||||
|
ApplicationType,
|
||||||
|
FirmwareInfo,
|
||||||
|
)
|
||||||
from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
|
from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
@ -61,10 +65,22 @@ async def test_config_flow(
|
|||||||
async def mock_async_step_pick_firmware_zigbee(self, data):
|
async def mock_async_step_pick_firmware_zigbee(self, data):
|
||||||
return await self.async_step_confirm_zigbee(user_input={})
|
return await self.async_step_confirm_zigbee(user_input={})
|
||||||
|
|
||||||
with patch(
|
with (
|
||||||
"homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareConfigFlow.async_step_pick_firmware_zigbee",
|
patch(
|
||||||
autospec=True,
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareConfigFlow.async_step_pick_firmware_zigbee",
|
||||||
side_effect=mock_async_step_pick_firmware_zigbee,
|
autospec=True,
|
||||||
|
side_effect=mock_async_step_pick_firmware_zigbee,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
|
||||||
|
return_value=FirmwareInfo(
|
||||||
|
device=usb_data.device,
|
||||||
|
firmware_type=ApplicationType.EZSP,
|
||||||
|
firmware_version=None,
|
||||||
|
owners=[],
|
||||||
|
source="probe",
|
||||||
|
),
|
||||||
|
),
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
@ -134,10 +150,22 @@ async def test_options_flow(
|
|||||||
async def mock_async_step_pick_firmware_zigbee(self, data):
|
async def mock_async_step_pick_firmware_zigbee(self, data):
|
||||||
return await self.async_step_confirm_zigbee(user_input={})
|
return await self.async_step_confirm_zigbee(user_input={})
|
||||||
|
|
||||||
with patch(
|
with (
|
||||||
"homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
|
patch(
|
||||||
autospec=True,
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
|
||||||
side_effect=mock_async_step_pick_firmware_zigbee,
|
autospec=True,
|
||||||
|
side_effect=mock_async_step_pick_firmware_zigbee,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
|
||||||
|
return_value=FirmwareInfo(
|
||||||
|
device=usb_data.device,
|
||||||
|
firmware_type=ApplicationType.EZSP,
|
||||||
|
firmware_version=None,
|
||||||
|
owners=[],
|
||||||
|
source="probe",
|
||||||
|
),
|
||||||
|
),
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.options.async_configure(
|
result = await hass.config_entries.options.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
|
@ -18,7 +18,10 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
|
|||||||
get_flasher_addon_manager,
|
get_flasher_addon_manager,
|
||||||
get_multiprotocol_addon_manager,
|
get_multiprotocol_addon_manager,
|
||||||
)
|
)
|
||||||
from homeassistant.components.homeassistant_hardware.util import ApplicationType
|
from homeassistant.components.homeassistant_hardware.util import (
|
||||||
|
ApplicationType,
|
||||||
|
FirmwareInfo,
|
||||||
|
)
|
||||||
from homeassistant.components.homeassistant_yellow.const import DOMAIN, RADIO_DEVICE
|
from homeassistant.components.homeassistant_yellow.const import DOMAIN, RADIO_DEVICE
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
@ -82,8 +85,14 @@ async def test_config_flow(hass: HomeAssistant) -> None:
|
|||||||
return_value=True,
|
return_value=True,
|
||||||
) as mock_setup_entry,
|
) as mock_setup_entry,
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_type",
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
|
||||||
return_value=ApplicationType.EZSP,
|
return_value=FirmwareInfo(
|
||||||
|
device=RADIO_DEVICE,
|
||||||
|
firmware_type=ApplicationType.EZSP,
|
||||||
|
firmware_version=None,
|
||||||
|
owners=[],
|
||||||
|
source="probe",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@ -330,10 +339,22 @@ async def test_firmware_options_flow(hass: HomeAssistant) -> None:
|
|||||||
async def mock_async_step_pick_firmware_zigbee(self, data):
|
async def mock_async_step_pick_firmware_zigbee(self, data):
|
||||||
return await self.async_step_confirm_zigbee(user_input={})
|
return await self.async_step_confirm_zigbee(user_input={})
|
||||||
|
|
||||||
with patch(
|
with (
|
||||||
"homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
|
patch(
|
||||||
autospec=True,
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.BaseFirmwareOptionsFlow.async_step_pick_firmware_zigbee",
|
||||||
side_effect=mock_async_step_pick_firmware_zigbee,
|
autospec=True,
|
||||||
|
side_effect=mock_async_step_pick_firmware_zigbee,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.homeassistant_hardware.firmware_config_flow.probe_silabs_firmware_info",
|
||||||
|
return_value=FirmwareInfo(
|
||||||
|
device=RADIO_DEVICE,
|
||||||
|
firmware_type=ApplicationType.EZSP,
|
||||||
|
firmware_version=None,
|
||||||
|
owners=[],
|
||||||
|
source="probe",
|
||||||
|
),
|
||||||
|
),
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.options.async_configure(
|
result = await hass.config_entries.options.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user