mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 09:47:52 +00:00
Warn when changing multipan channel if there are not 2 known users (#95898)
* Warn when changing multipan channel if there are not 2 known users * Add test * Improve messages * Tweak translation string * Adjust message * Remove unused translation placeholders
This commit is contained in:
parent
ea57f78392
commit
c7f6d84058
@ -138,6 +138,17 @@ class MultiprotocolAddonManager(AddonManager):
|
||||
|
||||
return tasks
|
||||
|
||||
async def async_active_platforms(self) -> list[str]:
|
||||
"""Return a list of platforms using the multipan radio."""
|
||||
active_platforms: list[str] = []
|
||||
|
||||
for integration_domain, platform in self._platforms.items():
|
||||
if not await platform.async_using_multipan(self._hass):
|
||||
continue
|
||||
active_platforms.append(integration_domain)
|
||||
|
||||
return active_platforms
|
||||
|
||||
@callback
|
||||
def async_get_channel(self) -> int | None:
|
||||
"""Get the channel."""
|
||||
@ -510,7 +521,26 @@ class OptionsFlowHandler(config_entries.OptionsFlow, ABC):
|
||||
) -> FlowResult:
|
||||
"""Reconfigure the addon."""
|
||||
multipan_manager = await get_addon_manager(self.hass)
|
||||
active_platforms = await multipan_manager.async_active_platforms()
|
||||
if set(active_platforms) != {"otbr", "zha"}:
|
||||
return await self.async_step_notify_unknown_multipan_user()
|
||||
return await self.async_step_change_channel()
|
||||
|
||||
async def async_step_notify_unknown_multipan_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Notify that there may be unknown multipan platforms."""
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
step_id="notify_unknown_multipan_user",
|
||||
)
|
||||
return await self.async_step_change_channel()
|
||||
|
||||
async def async_step_change_channel(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Change the channel."""
|
||||
multipan_manager = await get_addon_manager(self.hass)
|
||||
if user_input is None:
|
||||
channels = [str(x) for x in range(11, 27)]
|
||||
suggested_channel = DEFAULT_CHANNEL
|
||||
@ -529,7 +559,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow, ABC):
|
||||
}
|
||||
)
|
||||
return self.async_show_form(
|
||||
step_id="reconfigure_addon", data_schema=data_schema
|
||||
step_id="change_channel", data_schema=data_schema
|
||||
)
|
||||
|
||||
# Change the shared channel
|
||||
|
@ -18,6 +18,12 @@
|
||||
"uninstall_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::uninstall_addon::title%]"
|
||||
}
|
||||
},
|
||||
"change_channel": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::title%]",
|
||||
"data": {
|
||||
"channel": "Channel"
|
||||
}
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "The Silicon Labs Multiprotocol add-on installation has started"
|
||||
},
|
||||
@ -25,11 +31,12 @@
|
||||
"title": "Channel change initiated",
|
||||
"description": "A Zigbee and Thread channel change has been initiated and will finish in {delay_minutes} minutes."
|
||||
},
|
||||
"notify_unknown_multipan_user": {
|
||||
"title": "Manual configuration may be needed",
|
||||
"description": "Home Assistant can automatically change the channels for otbr and zha. If you have configured another integration to use the radio, for example Zigbee2MQTT, you will have to reconfigure the channel in that integration after completing this guide."
|
||||
},
|
||||
"reconfigure_addon": {
|
||||
"title": "Reconfigure IEEE 802.15.4 radio multiprotocol support",
|
||||
"data": {
|
||||
"channel": "Channel"
|
||||
}
|
||||
"title": "Reconfigure IEEE 802.15.4 radio multiprotocol support"
|
||||
},
|
||||
"show_revert_guide": {
|
||||
"title": "Multiprotocol support is enabled for this device",
|
||||
|
@ -17,6 +17,12 @@
|
||||
"uninstall_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_menu::menu_options::uninstall_addon%]"
|
||||
}
|
||||
},
|
||||
"change_channel": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::title%]",
|
||||
"data": {
|
||||
"channel": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::data::channel%]"
|
||||
}
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::install_addon::title%]"
|
||||
},
|
||||
@ -24,11 +30,12 @@
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::notify_channel_change::title%]",
|
||||
"description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::notify_channel_change::description%]"
|
||||
},
|
||||
"notify_unknown_multipan_user": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::notify_unknown_multipan_user::title%]",
|
||||
"description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::notify_unknown_multipan_user::description%]"
|
||||
},
|
||||
"reconfigure_addon": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::title%]",
|
||||
"data": {
|
||||
"channel": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::data::channel%]"
|
||||
}
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::title%]"
|
||||
},
|
||||
"show_revert_guide": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::show_revert_guide::title%]",
|
||||
|
@ -17,6 +17,12 @@
|
||||
"uninstall_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::addon_menu::menu_options::uninstall_addon%]"
|
||||
}
|
||||
},
|
||||
"change_channel": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::title%]",
|
||||
"data": {
|
||||
"channel": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::data::channel%]"
|
||||
}
|
||||
},
|
||||
"hardware_settings": {
|
||||
"title": "Configure hardware settings",
|
||||
"data": {
|
||||
@ -38,6 +44,10 @@
|
||||
"multipan_settings": "Configure IEEE 802.15.4 radio multiprotocol support"
|
||||
}
|
||||
},
|
||||
"notify_unknown_multipan_user": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::notify_unknown_multipan_user::title%]",
|
||||
"description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::notify_unknown_multipan_user::description%]"
|
||||
},
|
||||
"reboot_menu": {
|
||||
"title": "Reboot required",
|
||||
"description": "The settings have changed, but the new settings will not take effect until the system is rebooted",
|
||||
@ -47,10 +57,7 @@
|
||||
}
|
||||
},
|
||||
"reconfigure_addon": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::title%]",
|
||||
"data": {
|
||||
"channel": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::data::channel%]"
|
||||
}
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::title%]"
|
||||
},
|
||||
"show_revert_guide": {
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::show_revert_guide::title%]",
|
||||
|
@ -27,6 +27,7 @@ from tests.common import (
|
||||
)
|
||||
|
||||
TEST_DOMAIN = "test"
|
||||
TEST_DOMAIN_2 = "test_2"
|
||||
|
||||
|
||||
class FakeConfigFlow(ConfigFlow):
|
||||
@ -456,7 +457,7 @@ async def test_option_flow_addon_installed_other_device(
|
||||
@pytest.mark.parametrize(
|
||||
("configured_channel", "suggested_channel"), [(None, "15"), (11, "11")]
|
||||
)
|
||||
async def test_option_flow_addon_installed_same_device_reconfigure(
|
||||
async def test_option_flow_addon_installed_same_device_reconfigure_unexpected_users(
|
||||
hass: HomeAssistant,
|
||||
addon_info,
|
||||
addon_store_info,
|
||||
@ -465,7 +466,7 @@ async def test_option_flow_addon_installed_same_device_reconfigure(
|
||||
configured_channel: int | None,
|
||||
suggested_channel: int,
|
||||
) -> None:
|
||||
"""Test installing the multi pan addon."""
|
||||
"""Test reconfiguring the multi pan addon."""
|
||||
mock_integration(hass, MockModule("hassio"))
|
||||
addon_info.return_value["options"]["device"] = "/dev/ttyTEST123"
|
||||
|
||||
@ -494,7 +495,11 @@ async def test_option_flow_addon_installed_same_device_reconfigure(
|
||||
{"next_step_id": "reconfigure_addon"},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "reconfigure_addon"
|
||||
assert result["step_id"] == "notify_unknown_multipan_user"
|
||||
|
||||
result = await hass.config_entries.options.async_configure(result["flow_id"], {})
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "change_channel"
|
||||
assert get_suggested(result["data_schema"].schema, "channel") == suggested_channel
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
@ -508,6 +513,79 @@ async def test_option_flow_addon_installed_same_device_reconfigure(
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
|
||||
assert mock_multiprotocol_platform.change_channel_calls == [(14, 300)]
|
||||
assert multipan_manager._channel == 14
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("configured_channel", "suggested_channel"), [(None, "15"), (11, "11")]
|
||||
)
|
||||
async def test_option_flow_addon_installed_same_device_reconfigure_expected_users(
|
||||
hass: HomeAssistant,
|
||||
addon_info,
|
||||
addon_store_info,
|
||||
addon_installed,
|
||||
configured_channel: int | None,
|
||||
suggested_channel: int,
|
||||
) -> None:
|
||||
"""Test reconfiguring the multi pan addon."""
|
||||
mock_integration(hass, MockModule("hassio"))
|
||||
addon_info.return_value["options"]["device"] = "/dev/ttyTEST123"
|
||||
|
||||
multipan_manager = await silabs_multiprotocol_addon.get_addon_manager(hass)
|
||||
multipan_manager._channel = configured_channel
|
||||
|
||||
# Setup the config entry
|
||||
config_entry = MockConfigEntry(
|
||||
data={},
|
||||
domain=TEST_DOMAIN,
|
||||
options={},
|
||||
title="Test HW",
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
mock_multiprotocol_platforms = {}
|
||||
for domain in ["otbr", "zha"]:
|
||||
mock_multiprotocol_platform = MockMultiprotocolPlatform()
|
||||
mock_multiprotocol_platforms[domain] = mock_multiprotocol_platform
|
||||
mock_multiprotocol_platform.channel = configured_channel
|
||||
mock_multiprotocol_platform.using_multipan = True
|
||||
|
||||
hass.config.components.add(domain)
|
||||
mock_platform(
|
||||
hass, f"{domain}.silabs_multiprotocol", mock_multiprotocol_platform
|
||||
)
|
||||
hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: domain})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
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.MENU
|
||||
assert result["step_id"] == "addon_menu"
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
{"next_step_id": "reconfigure_addon"},
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "change_channel"
|
||||
assert get_suggested(result["data_schema"].schema, "channel") == suggested_channel
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"], {"channel": "14"}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "notify_channel_change"
|
||||
assert result["description_placeholders"] == {"delay_minutes": "5"}
|
||||
|
||||
result = await hass.config_entries.options.async_configure(result["flow_id"], {})
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
|
||||
for domain in ["otbr", "zha"]:
|
||||
assert mock_multiprotocol_platforms[domain].change_channel_calls == [(14, 300)]
|
||||
assert multipan_manager._channel == 14
|
||||
|
||||
|
||||
async def test_option_flow_addon_installed_same_device_uninstall(
|
||||
@ -1007,3 +1085,39 @@ async def test_load_preferences(hass: HomeAssistant) -> None:
|
||||
await multipan_manager2.async_setup()
|
||||
|
||||
assert multipan_manager._channel == multipan_manager2._channel
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"multipan_platforms",
|
||||
"active_platforms",
|
||||
),
|
||||
[
|
||||
({}, []),
|
||||
({TEST_DOMAIN: False}, []),
|
||||
({TEST_DOMAIN: True}, [TEST_DOMAIN]),
|
||||
({TEST_DOMAIN: True, TEST_DOMAIN_2: False}, [TEST_DOMAIN]),
|
||||
({TEST_DOMAIN: True, TEST_DOMAIN_2: True}, [TEST_DOMAIN, TEST_DOMAIN_2]),
|
||||
],
|
||||
)
|
||||
async def test_active_plaforms(
|
||||
hass: HomeAssistant,
|
||||
multipan_platforms: dict[str, bool],
|
||||
active_platforms: list[str],
|
||||
) -> None:
|
||||
"""Test async_active_platforms."""
|
||||
multipan_manager = await silabs_multiprotocol_addon.get_addon_manager(hass)
|
||||
|
||||
for domain, platform_using_multipan in multipan_platforms.items():
|
||||
mock_multiprotocol_platform = MockMultiprotocolPlatform()
|
||||
mock_multiprotocol_platform.channel = 11
|
||||
mock_multiprotocol_platform.using_multipan = platform_using_multipan
|
||||
|
||||
hass.config.components.add(domain)
|
||||
mock_platform(
|
||||
hass, f"{domain}.silabs_multiprotocol", mock_multiprotocol_platform
|
||||
)
|
||||
hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: domain})
|
||||
|
||||
await hass.async_block_till_done()
|
||||
assert await multipan_manager.async_active_platforms() == active_platforms
|
||||
|
Loading…
x
Reference in New Issue
Block a user