From 56c53fdb9b9e5b34d4a7f39af0ee3572cbcb7147 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Thu, 24 Jul 2025 20:14:44 +0200 Subject: [PATCH] Allow Bluetooth proxy for Shelly devices only if Zigbee firmware is not active (#149193) Co-authored-by: Shay Levy Co-authored-by: Norbert Rittel --- homeassistant/components/shelly/__init__.py | 2 +- homeassistant/components/shelly/config_flow.py | 4 ++-- homeassistant/components/shelly/coordinator.py | 4 ++-- homeassistant/components/shelly/strings.json | 2 +- tests/components/shelly/conftest.py | 1 + tests/components/shelly/test_config_flow.py | 8 ++++---- tests/components/shelly/test_coordinator.py | 6 +++--- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py index 0467b93a7c8..5582ab488df 100644 --- a/homeassistant/components/shelly/__init__.py +++ b/homeassistant/components/shelly/__init__.py @@ -298,7 +298,7 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ShellyConfigEntry) translation_key="firmware_unsupported", translation_placeholders={"device": entry.title}, ) - runtime_data.rpc_zigbee_enabled = device.zigbee_enabled + runtime_data.rpc_zigbee_firmware = device.zigbee_firmware runtime_data.rpc_supports_scripts = await device.supports_scripts() if runtime_data.rpc_supports_scripts: runtime_data.rpc_script_events = await get_rpc_scripts_event_types( diff --git a/homeassistant/components/shelly/config_flow.py b/homeassistant/components/shelly/config_flow.py index bde57f6f9bc..d310f3525c5 100644 --- a/homeassistant/components/shelly/config_flow.py +++ b/homeassistant/components/shelly/config_flow.py @@ -475,8 +475,8 @@ class OptionsFlowHandler(OptionsFlow): return self.async_abort(reason="cannot_connect") if not supports_scripts: return self.async_abort(reason="no_scripts_support") - if self.config_entry.runtime_data.rpc_zigbee_enabled: - return self.async_abort(reason="zigbee_enabled") + if self.config_entry.runtime_data.rpc_zigbee_firmware: + return self.async_abort(reason="zigbee_firmware") if user_input is not None: return self.async_create_entry(title="", data=user_input) diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py index 9291d7aa70f..18430da8841 100644 --- a/homeassistant/components/shelly/coordinator.py +++ b/homeassistant/components/shelly/coordinator.py @@ -94,7 +94,7 @@ class ShellyEntryData: rpc_poll: ShellyRpcPollingCoordinator | None = None rpc_script_events: dict[int, list[str]] | None = None rpc_supports_scripts: bool | None = None - rpc_zigbee_enabled: bool | None = None + rpc_zigbee_firmware: bool | None = None type ShellyConfigEntry = ConfigEntry[ShellyEntryData] @@ -730,7 +730,7 @@ class ShellyRpcCoordinator(ShellyCoordinatorBase[RpcDevice]): if not self.sleep_period: if ( self.config_entry.runtime_data.rpc_supports_scripts - and not self.config_entry.runtime_data.rpc_zigbee_enabled + and not self.config_entry.runtime_data.rpc_zigbee_firmware ): await self._async_connect_ble_scanner() else: diff --git a/homeassistant/components/shelly/strings.json b/homeassistant/components/shelly/strings.json index c1d520a59f1..2bb5cd73bfd 100644 --- a/homeassistant/components/shelly/strings.json +++ b/homeassistant/components/shelly/strings.json @@ -105,7 +105,7 @@ "abort": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "no_scripts_support": "Device does not support scripts and cannot be used as a Bluetooth scanner.", - "zigbee_enabled": "Device with Zigbee enabled cannot be used as a Bluetooth scanner. Please disable it to use the device as a Bluetooth scanner." + "zigbee_firmware": "A device with Zigbee firmware cannot be used as a Bluetooth scanner. Please switch to Matter firmware to use the device as a Bluetooth scanner." } }, "selector": { diff --git a/tests/components/shelly/conftest.py b/tests/components/shelly/conftest.py index 4eccb075b67..47ff723bddc 100644 --- a/tests/components/shelly/conftest.py +++ b/tests/components/shelly/conftest.py @@ -548,6 +548,7 @@ def _mock_rpc_device(version: str | None = None): ), xmod_info={}, zigbee_enabled=False, + zigbee_firmware=False, ip_address="10.10.10.10", ) type(device).name = PropertyMock(return_value="Test name") diff --git a/tests/components/shelly/test_config_flow.py b/tests/components/shelly/test_config_flow.py index 93893035a3e..3282756fe28 100644 --- a/tests/components/shelly/test_config_flow.py +++ b/tests/components/shelly/test_config_flow.py @@ -870,17 +870,17 @@ async def test_options_flow_abort_no_scripts_support( assert result["reason"] == "no_scripts_support" -async def test_options_flow_abort_zigbee_enabled( +async def test_options_flow_abort_zigbee_firmware( hass: HomeAssistant, mock_rpc_device: Mock, monkeypatch: pytest.MonkeyPatch ) -> None: - """Test ble options abort if Zigbee is enabled for the device.""" - monkeypatch.setattr(mock_rpc_device, "zigbee_enabled", True) + """Test ble options abort if Zigbee firmware is active.""" + monkeypatch.setattr(mock_rpc_device, "zigbee_firmware", True) entry = await init_integration(hass, 4) result = await hass.config_entries.options.async_init(entry.entry_id) assert result["type"] is FlowResultType.ABORT - assert result["reason"] == "zigbee_enabled" + assert result["reason"] == "zigbee_firmware" async def test_zeroconf_already_configured(hass: HomeAssistant) -> None: diff --git a/tests/components/shelly/test_coordinator.py b/tests/components/shelly/test_coordinator.py index 5b4372fe938..ff61eda626f 100644 --- a/tests/components/shelly/test_coordinator.py +++ b/tests/components/shelly/test_coordinator.py @@ -864,7 +864,7 @@ async def test_rpc_update_entry_fw_ver( @pytest.mark.parametrize( - ("supports_scripts", "zigbee_enabled", "result"), + ("supports_scripts", "zigbee_firmware", "result"), [ (True, False, True), (True, True, False), @@ -877,14 +877,14 @@ async def test_rpc_runs_connected_events_when_initialized( mock_rpc_device: Mock, monkeypatch: pytest.MonkeyPatch, supports_scripts: bool, - zigbee_enabled: bool, + zigbee_firmware: bool, result: bool, ) -> None: """Test RPC runs connected events when initialized.""" monkeypatch.setattr( mock_rpc_device, "supports_scripts", AsyncMock(return_value=supports_scripts) ) - monkeypatch.setattr(mock_rpc_device, "zigbee_enabled", zigbee_enabled) + monkeypatch.setattr(mock_rpc_device, "zigbee_firmware", zigbee_firmware) monkeypatch.setattr(mock_rpc_device, "initialized", False) await init_integration(hass, 2)