Catch update exception in AirGradient (#153828)

This commit is contained in:
Joost Lekkerkerker
2025-10-06 21:31:55 +02:00
committed by Franck Nijhof
parent f4339dc031
commit 809070d2ad
2 changed files with 89 additions and 5 deletions
+25 -4
View File
@@ -1,7 +1,9 @@
"""Airgradient Update platform."""
from datetime import timedelta
import logging
from airgradient import AirGradientConnectionError
from propcache.api import cached_property
from homeassistant.components.update import UpdateDeviceClass, UpdateEntity
@@ -13,6 +15,7 @@ from .entity import AirGradientEntity
PARALLEL_UPDATES = 1
SCAN_INTERVAL = timedelta(hours=1)
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
@@ -31,6 +34,7 @@ class AirGradientUpdate(AirGradientEntity, UpdateEntity):
"""Representation of Airgradient Update."""
_attr_device_class = UpdateDeviceClass.FIRMWARE
_server_unreachable_logged = False
def __init__(self, coordinator: AirGradientCoordinator) -> None:
"""Initialize the entity."""
@@ -47,10 +51,27 @@ class AirGradientUpdate(AirGradientEntity, UpdateEntity):
"""Return the installed version of the entity."""
return self.coordinator.data.measures.firmware_version
@property
def available(self) -> bool:
"""Return if entity is available."""
return super().available and self._attr_available
async def async_update(self) -> None:
"""Update the entity."""
self._attr_latest_version = (
await self.coordinator.client.get_latest_firmware_version(
self.coordinator.serial_number
try:
self._attr_latest_version = (
await self.coordinator.client.get_latest_firmware_version(
self.coordinator.serial_number
)
)
)
except AirGradientConnectionError:
self._attr_latest_version = None
self._attr_available = False
if not self._server_unreachable_logged:
_LOGGER.error(
"Unable to connect to AirGradient server to check for updates"
)
self._server_unreachable_logged = True
else:
self._server_unreachable_logged = False
self._attr_available = True
+64 -1
View File
@@ -3,10 +3,12 @@
from datetime import timedelta
from unittest.mock import AsyncMock, patch
from airgradient import AirGradientConnectionError
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.const import STATE_OFF, STATE_ON, Platform
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
@@ -67,3 +69,64 @@ async def test_update_mechanism(
assert state.state == STATE_ON
assert state.attributes["installed_version"] == "3.1.4"
assert state.attributes["latest_version"] == "3.1.5"
async def test_update_errors(
hass: HomeAssistant,
mock_airgradient_client: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test update entity errors."""
await setup_integration(hass, mock_config_entry)
state = hass.states.get("update.airgradient_firmware")
assert state.state == STATE_ON
mock_airgradient_client.get_latest_firmware_version.side_effect = (
AirGradientConnectionError("Boom")
)
freezer.tick(timedelta(hours=1))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("update.airgradient_firmware")
assert state.state == STATE_UNAVAILABLE
assert "Unable to connect to AirGradient server to check for updates" in caplog.text
caplog.clear()
freezer.tick(timedelta(hours=1))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("update.airgradient_firmware")
assert state.state == STATE_UNAVAILABLE
assert (
"Unable to connect to AirGradient server to check for updates"
not in caplog.text
)
mock_airgradient_client.get_latest_firmware_version.side_effect = None
freezer.tick(timedelta(hours=1))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("update.airgradient_firmware")
assert state.state == STATE_ON
mock_airgradient_client.get_latest_firmware_version.side_effect = (
AirGradientConnectionError("Boom")
)
freezer.tick(timedelta(hours=1))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("update.airgradient_firmware")
assert state.state == STATE_UNAVAILABLE
assert "Unable to connect to AirGradient server to check for updates" in caplog.text