Fix Reolink camera updates persisting in UI (#161149)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Paul Tarjan
2026-03-03 07:40:32 -07:00
committed by GitHub
parent e9a576494b
commit e343e90da2
2 changed files with 58 additions and 0 deletions
@@ -143,8 +143,13 @@ async def async_setup_entry(
min_timeout = host.api.timeout * (RETRY_ATTEMPTS + 2)
update_timeout = max(min_timeout, min_timeout * host.api.num_cameras / 10)
# Track firmware versions to detect external updates (e.g., via Reolink app)
last_known_firmware: dict[int | None, str | None] = {}
async def async_device_config_update() -> None:
"""Update the host state cache and renew the ONVIF-subscription."""
nonlocal last_known_firmware
async with asyncio.timeout(update_timeout):
try:
await host.update_states()
@@ -162,6 +167,23 @@ async def async_setup_entry(
host.credential_errors = 0
# Check for firmware version changes (external update detection)
firmware_changed = False
for ch in (*host.api.channels, None):
new_version = host.api.camera_sw_version(ch)
old_version = last_known_firmware.get(ch)
if (
old_version is not None
and new_version is not None
and new_version != old_version
):
firmware_changed = True
last_known_firmware[ch] = new_version
# Notify firmware coordinator if firmware changed externally
if firmware_changed and firmware_coordinator is not None:
firmware_coordinator.async_set_updated_data(None)
async with asyncio.timeout(min_timeout):
await host.renew()
+36
View File
@@ -206,3 +206,39 @@ async def test_update_firm_keeps_available(
# still available
assert hass.states.get(entity_id).state == STATE_ON
@pytest.mark.parametrize("entity_name", [TEST_NVR_NAME, TEST_CAM_NAME])
async def test_external_firmware_update_detected(
hass: HomeAssistant,
config_entry: MockConfigEntry,
reolink_host: MagicMock,
entity_name: str,
) -> None:
"""Test that external firmware updates (via Reolink app) are detected."""
reolink_host.camera_sw_version.return_value = "v1.1.0.0.0.0000"
new_firmware = NewSoftwareVersion(
version_string="v3.3.0.226_23031644",
download_url=TEST_DOWNLOAD_URL,
release_notes=TEST_RELEASE_NOTES,
)
reolink_host.firmware_update_available.return_value = new_firmware
with patch("homeassistant.components.reolink.PLATFORMS", [Platform.UPDATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
entity_id = f"{Platform.UPDATE}.{entity_name}_firmware"
assert hass.states.get(entity_id).state == STATE_ON
# Simulate external firmware update via Reolink app
reolink_host.camera_sw_version.return_value = "v3.3.0.226_23031644"
reolink_host.firmware_update_available.return_value = False
# Trigger device coordinator update (simulates regular polling)
await config_entry.runtime_data.device_coordinator.async_refresh()
await hass.async_block_till_done()
# The firmware coordinator should have been refreshed, and update should be cleared
assert hass.states.get(entity_id).state == STATE_OFF