From 3aa677183502b7c4f85bfcd99b8f34c316893411 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Wed, 4 Oct 2023 09:00:17 +0000 Subject: [PATCH] Update `DeviceInfo.sw_version` value for Shelly Gen2 sleeping devices (#101338) * Update device info for gen2 sleeping devices * Add test * Update sw_version only if the firmware_version value has changed * Rename device_update_info() to update_device_fw_info() * Remove duplicate comparison --- .../components/shelly/coordinator.py | 11 +++---- homeassistant/components/shelly/utils.py | 12 ++++--- tests/components/shelly/test_coordinator.py | 33 +++++++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py index d838b5c6547..e648a80420a 100644 --- a/homeassistant/components/shelly/coordinator.py +++ b/homeassistant/components/shelly/coordinator.py @@ -58,7 +58,7 @@ from .const import ( UPDATE_PERIOD_MULTIPLIER, BLEScannerMode, ) -from .utils import device_update_info, get_rpc_device_wakeup_period +from .utils import get_rpc_device_wakeup_period, update_device_fw_info _DeviceT = TypeVar("_DeviceT", bound="BlockDevice|RpcDevice") @@ -374,16 +374,13 @@ class ShellyRestCoordinator(ShellyCoordinatorBase[BlockDevice]): if self.device.status["uptime"] > 2 * REST_SENSORS_UPDATE_INTERVAL: return - old_firmware = self.device.firmware_version await self.device.update_shelly() - if self.device.firmware_version == old_firmware: - return except DeviceConnectionError as err: raise UpdateFailed(f"Error fetching data: {repr(err)}") from err except InvalidAuthError: self.entry.async_start_reauth(self.hass) else: - device_update_info(self.hass, self.device, self.entry) + update_device_fw_info(self.hass, self.device, self.entry) class ShellyRpcCoordinator(ShellyCoordinatorBase[RpcDevice]): @@ -531,7 +528,7 @@ class ShellyRpcCoordinator(ShellyCoordinatorBase[RpcDevice]): LOGGER.debug("Reconnecting to Shelly RPC Device - %s", self.name) try: await self.device.initialize() - device_update_info(self.hass, self.device, self.entry) + update_device_fw_info(self.hass, self.device, self.entry) except DeviceConnectionError as err: raise UpdateFailed(f"Device disconnected: {repr(err)}") from err except InvalidAuthError: @@ -617,6 +614,8 @@ class ShellyRpcCoordinator(ShellyCoordinatorBase[RpcDevice]): self.hass.async_create_task(self._async_disconnected()) elif update_type is RpcUpdateType.STATUS: self.async_set_updated_data(None) + if self.sleep_period: + update_device_fw_info(self.hass, self.device, self.entry) elif update_type is RpcUpdateType.EVENT and (event := self.device.event): self._async_device_event_handler(event) diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py index b64b76534be..4d25812361c 100644 --- a/homeassistant/components/shelly/utils.py +++ b/homeassistant/components/shelly/utils.py @@ -375,13 +375,10 @@ def get_rpc_input_triggers(device: RpcDevice) -> list[tuple[str, str]]: @callback -def device_update_info( +def update_device_fw_info( hass: HomeAssistant, shellydevice: BlockDevice | RpcDevice, entry: ConfigEntry ) -> None: - """Update device registry info.""" - - LOGGER.debug("Updating device registry info for %s", entry.title) - + """Update the firmware version information in the device registry.""" assert entry.unique_id dev_reg = dr_async_get(hass) @@ -389,6 +386,11 @@ def device_update_info( identifiers={(DOMAIN, entry.entry_id)}, connections={(CONNECTION_NETWORK_MAC, format_mac(entry.unique_id))}, ): + if device.sw_version == shellydevice.firmware_version: + return + + LOGGER.debug("Updating device registry info for %s", entry.title) + dev_reg.async_update_device(device.id, sw_version=shellydevice.firmware_version) diff --git a/tests/components/shelly/test_coordinator.py b/tests/components/shelly/test_coordinator.py index 3872f6f5a1a..8ce80b70032 100644 --- a/tests/components/shelly/test_coordinator.py +++ b/tests/components/shelly/test_coordinator.py @@ -23,8 +23,10 @@ from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState from homeassistant.const import ATTR_DEVICE_ID, STATE_ON, STATE_UNAVAILABLE from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import ( + CONNECTION_NETWORK_MAC, async_entries_for_config_entry, async_get as async_get_dev_reg, + format_mac, ) import homeassistant.helpers.issue_registry as ir @@ -632,3 +634,34 @@ async def test_rpc_polling_disconnected( await mock_polling_rpc_update(hass, freezer) assert hass.states.get(entity_id).state == STATE_UNAVAILABLE + + +async def test_rpc_update_entry_fw_ver( + hass: HomeAssistant, mock_rpc_device, monkeypatch +) -> None: + """Test RPC update entry firmware version.""" + entry = await init_integration(hass, 2, sleep_period=600) + dev_reg = async_get_dev_reg(hass) + + # Make device online + mock_rpc_device.mock_update() + await hass.async_block_till_done() + + device = dev_reg.async_get_device( + identifiers={(DOMAIN, entry.entry_id)}, + connections={(CONNECTION_NETWORK_MAC, format_mac(entry.unique_id))}, + ) + + assert device.sw_version == "some fw string" + + monkeypatch.setattr(mock_rpc_device, "firmware_version", "99.0.0") + + mock_rpc_device.mock_update() + await hass.async_block_till_done() + + device = dev_reg.async_get_device( + identifiers={(DOMAIN, entry.entry_id)}, + connections={(CONNECTION_NETWORK_MAC, format_mac(entry.unique_id))}, + ) + + assert device.sw_version == "99.0.0"