Fix update data for multiple Gree devices (#139469)

fix sync date for multiple devices

do not use handler for explicit update devices as internal communication lib do not provide which device is updated
use ha update loop

copy data object to prevent rewrite data from internal lib

allow more time to process response before log warning about long wait for response and make log message more clear
This commit is contained in:
Filip Agh 2025-03-01 11:50:24 +01:00 committed by Bram Kragten
parent a4e71e2055
commit 708f22fe6f
3 changed files with 13 additions and 5 deletions

View File

@ -20,3 +20,4 @@ MAX_ERRORS = 2
TARGET_TEMPERATURE_STEP = 1
UPDATE_INTERVAL = 60
MAX_EXPECTED_RESPONSE_TIME_INTERVAL = UPDATE_INTERVAL * 2

View File

@ -2,6 +2,7 @@
from __future__ import annotations
import copy
from datetime import datetime, timedelta
import logging
from typing import Any
@ -24,6 +25,7 @@ from .const import (
DISPATCH_DEVICE_DISCOVERED,
DOMAIN,
MAX_ERRORS,
MAX_EXPECTED_RESPONSE_TIME_INTERVAL,
UPDATE_INTERVAL,
)
@ -48,7 +50,6 @@ class DeviceDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
always_update=False,
)
self.device = device
self.device.add_handler(Response.DATA, self.device_state_updated)
self.device.add_handler(Response.RESULT, self.device_state_updated)
self._error_count: int = 0
@ -88,7 +89,9 @@ class DeviceDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
# raise update failed if time for more than MAX_ERRORS has passed since last update
now = utcnow()
elapsed_success = now - self._last_response_time
if self.update_interval and elapsed_success >= self.update_interval:
if self.update_interval and elapsed_success >= timedelta(
seconds=MAX_EXPECTED_RESPONSE_TIME_INTERVAL
):
if not self._last_error_time or (
(now - self.update_interval) >= self._last_error_time
):
@ -96,16 +99,19 @@ class DeviceDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
self._error_count += 1
_LOGGER.warning(
"Device %s is unresponsive for %s seconds",
"Device %s took an unusually long time to respond, %s seconds",
self.name,
elapsed_success,
)
else:
self._error_count = 0
if self.last_update_success and self._error_count >= MAX_ERRORS:
raise UpdateFailed(
f"Device {self.name} is unresponsive for too long and now unavailable"
)
return self.device.raw_properties
self._last_response_time = utcnow()
return copy.deepcopy(self.device.raw_properties)
async def push_state_update(self):
"""Send state updates to the physical device."""

View File

@ -52,6 +52,7 @@ from homeassistant.components.gree.const import (
DISCOVERY_SCAN_INTERVAL,
FAN_MEDIUM_HIGH,
FAN_MEDIUM_LOW,
MAX_EXPECTED_RESPONSE_TIME_INTERVAL,
UPDATE_INTERVAL,
)
from homeassistant.const import (
@ -346,7 +347,7 @@ async def test_unresponsive_device(
await async_setup_gree(hass)
async def run_update():
freezer.tick(timedelta(seconds=UPDATE_INTERVAL))
freezer.tick(timedelta(seconds=MAX_EXPECTED_RESPONSE_TIME_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()