Reject small uptime updates for Unifi clients (#120398)

Extend logic to reject small uptime updates to Unifi clients + add unit tests
This commit is contained in:
wittypluck 2024-06-28 22:47:20 +02:00 committed by GitHub
parent a3394675f3
commit 3549aaf69c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 10 deletions

View File

@ -139,7 +139,7 @@ def async_device_uptime_value_fn(hub: UnifiHub, device: Device) -> datetime | No
@callback
def async_device_uptime_value_changed_fn(
def async_uptime_value_changed_fn(
old: StateType | date | datetime | Decimal, new: datetime | float | str | None
) -> bool:
"""Reject the new uptime value if it's too similar to the old one. Avoids unwanted fluctuation."""
@ -310,6 +310,7 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
supported_fn=lambda hub, _: hub.config.option_allow_uptime_sensors,
unique_id_fn=lambda hub, obj_id: f"uptime-{obj_id}",
value_fn=async_client_uptime_value_fn,
value_changed_fn=async_uptime_value_changed_fn,
),
UnifiSensorEntityDescription[Wlans, Wlan](
key="WLAN clients",
@ -396,7 +397,7 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
object_fn=lambda api, obj_id: api.devices[obj_id],
unique_id_fn=lambda hub, obj_id: f"device_uptime-{obj_id}",
value_fn=async_device_uptime_value_fn,
value_changed_fn=async_device_uptime_value_changed_fn,
value_changed_fn=async_uptime_value_changed_fn,
),
UnifiSensorEntityDescription[Devices, Device](
key="Device temperature",

View File

@ -484,12 +484,12 @@ async def test_bandwidth_sensors(
],
)
@pytest.mark.parametrize(
("initial_uptime", "event_uptime", "new_uptime"),
("initial_uptime", "event_uptime", "small_variation_uptime", "new_uptime"),
[
# Uptime listed in epoch time should never change
(1609462800, 1609462800, 1612141200),
(1609462800, 1609462800, 1609462800, 1612141200),
# Uptime counted in seconds increases with every event
(60, 64, 60),
(60, 240, 480, 60),
],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
@ -503,6 +503,7 @@ async def test_uptime_sensors(
client_payload: list[dict[str, Any]],
initial_uptime,
event_uptime,
small_variation_uptime,
new_uptime,
) -> None:
"""Verify that uptime sensors are working as expected."""
@ -519,15 +520,24 @@ async def test_uptime_sensors(
)
# Verify normal new event doesn't change uptime
# 4 seconds has passed
# 4 minutes have passed
uptime_client["uptime"] = event_uptime
now = datetime(2021, 1, 1, 1, 1, 4, tzinfo=dt_util.UTC)
now = datetime(2021, 1, 1, 1, 4, 0, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_websocket_message(message=MessageKey.CLIENT, data=uptime_client)
await hass.async_block_till_done()
assert hass.states.get("sensor.client1_uptime").state == "2021-01-01T01:00:00+00:00"
# Verify small variation of uptime (<120 seconds) is ignored
# 15 seconds variation after 8 minutes
uptime_client["uptime"] = small_variation_uptime
now = datetime(2021, 1, 1, 1, 8, 15, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_websocket_message(message=MessageKey.CLIENT, data=uptime_client)
assert hass.states.get("sensor.client1_uptime").state == "2021-01-01T01:00:00+00:00"
# Verify new event change uptime
# 1 month has passed
uptime_client["uptime"] = new_uptime
@ -911,10 +921,20 @@ async def test_device_uptime(
)
# Verify normal new event doesn't change uptime
# 4 seconds has passed
# 4 minutes have passed
device = device_payload[0]
device["uptime"] = 64
now = datetime(2021, 1, 1, 1, 1, 4, tzinfo=dt_util.UTC)
device["uptime"] = 240
now = datetime(2021, 1, 1, 1, 4, 0, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_websocket_message(message=MessageKey.DEVICE, data=device)
assert hass.states.get("sensor.device_uptime").state == "2021-01-01T01:00:00+00:00"
# Verify small variation of uptime (<120 seconds) is ignored
# 15 seconds variation after 8 minutes
device = device_payload[0]
device["uptime"] = 480
now = datetime(2021, 1, 1, 1, 8, 15, tzinfo=dt_util.UTC)
with patch("homeassistant.util.dt.now", return_value=now):
mock_websocket_message(message=MessageKey.DEVICE, data=device)