Use runtime_data in gree (#144880)

This commit is contained in:
epenet 2025-05-14 14:06:40 +02:00 committed by GitHub
parent 67b9904740
commit 710e18f399
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 40 additions and 58 deletions

View File

@ -1,33 +1,29 @@
"""The Gree Climate integration."""
from __future__ import annotations
from datetime import timedelta
import logging
from homeassistant.components.network import async_get_ipv4_broadcast_addresses
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.event import async_track_time_interval
from .const import (
COORDINATORS,
DATA_DISCOVERY_SERVICE,
DISCOVERY_SCAN_INTERVAL,
DISPATCHERS,
DOMAIN,
)
from .coordinator import DiscoveryService
from .const import DISCOVERY_SCAN_INTERVAL
from .coordinator import DiscoveryService, GreeConfigEntry, GreeRuntimeData
_LOGGER = logging.getLogger(__name__)
PLATFORMS = [Platform.CLIMATE, Platform.SWITCH]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: GreeConfigEntry) -> bool:
"""Set up Gree Climate from a config entry."""
hass.data.setdefault(DOMAIN, {})
gree_discovery = DiscoveryService(hass, entry)
hass.data[DATA_DISCOVERY_SERVICE] = gree_discovery
entry.runtime_data = GreeRuntimeData(
discovery_service=gree_discovery, coordinators=[]
)
async def _async_scan_update(_=None):
bcast_addr = list(await async_get_ipv4_broadcast_addresses(hass))
@ -47,15 +43,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: GreeConfigEntry) -> bool:
"""Unload a config entry."""
if hass.data.get(DATA_DISCOVERY_SERVICE) is not None:
hass.data.pop(DATA_DISCOVERY_SERVICE)
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
hass.data[DOMAIN].pop(COORDINATORS, None)
hass.data[DOMAIN].pop(DISPATCHERS, None)
return unload_ok
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@ -36,21 +36,18 @@ from homeassistant.components.climate import (
ClimateEntityFeature,
HVACMode,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import (
COORDINATORS,
DISPATCH_DEVICE_DISCOVERED,
DOMAIN,
FAN_MEDIUM_HIGH,
FAN_MEDIUM_LOW,
TARGET_TEMPERATURE_STEP,
)
from .coordinator import DeviceDataUpdateCoordinator
from .coordinator import DeviceDataUpdateCoordinator, GreeConfigEntry
from .entity import GreeEntity
_LOGGER = logging.getLogger(__name__)
@ -87,17 +84,17 @@ SWING_MODES = [SWING_OFF, SWING_VERTICAL, SWING_HORIZONTAL, SWING_BOTH]
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: GreeConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Gree HVAC device from a config entry."""
@callback
def init_device(coordinator):
def init_device(coordinator: DeviceDataUpdateCoordinator) -> None:
"""Register the device."""
async_add_entities([GreeClimateEntity(coordinator)])
for coordinator in hass.data[DOMAIN][COORDINATORS]:
for coordinator in entry.runtime_data.coordinators:
init_device(coordinator)
entry.async_on_unload(

View File

@ -1,16 +1,10 @@
"""Constants for the Gree Climate integration."""
COORDINATORS = "coordinators"
DATA_DISCOVERY_SERVICE = "gree_discovery"
DISCOVERY_SCAN_INTERVAL = 300
DISCOVERY_TIMEOUT = 8
DISPATCH_DEVICE_DISCOVERED = "gree_device_discovered"
DISPATCHERS = "dispatchers"
DOMAIN = "gree"
COORDINATOR = "coordinator"
FAN_MEDIUM_LOW = "medium low"
FAN_MEDIUM_HIGH = "medium high"

View File

@ -3,6 +3,7 @@
from __future__ import annotations
import copy
from dataclasses import dataclass
from datetime import datetime, timedelta
import logging
from typing import Any
@ -20,7 +21,6 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
from homeassistant.util.dt import utcnow
from .const import (
COORDINATORS,
DISCOVERY_TIMEOUT,
DISPATCH_DEVICE_DISCOVERED,
DOMAIN,
@ -31,14 +31,24 @@ from .const import (
_LOGGER = logging.getLogger(__name__)
type GreeConfigEntry = ConfigEntry[GreeRuntimeData]
@dataclass
class GreeRuntimeData:
"""RUntime data for Gree Climate integration."""
discovery_service: DiscoveryService
coordinators: list[DeviceDataUpdateCoordinator]
class DeviceDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
"""Manages polling for state changes from the device."""
config_entry: ConfigEntry
config_entry: GreeConfigEntry
def __init__(
self, hass: HomeAssistant, config_entry: ConfigEntry, device: Device
self, hass: HomeAssistant, config_entry: GreeConfigEntry, device: Device
) -> None:
"""Initialize the data update coordinator."""
super().__init__(
@ -128,7 +138,7 @@ class DeviceDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
class DiscoveryService(Listener):
"""Discovery event handler for gree devices."""
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
def __init__(self, hass: HomeAssistant, entry: GreeConfigEntry) -> None:
"""Initialize discovery service."""
super().__init__()
self.hass = hass
@ -137,8 +147,6 @@ class DiscoveryService(Listener):
self.discovery = Discovery(DISCOVERY_TIMEOUT)
self.discovery.add_listener(self)
hass.data[DOMAIN].setdefault(COORDINATORS, [])
async def device_found(self, device_info: DeviceInfo) -> None:
"""Handle new device found on the network."""
@ -157,14 +165,14 @@ class DiscoveryService(Listener):
device.device_info.port,
)
coordo = DeviceDataUpdateCoordinator(self.hass, self.entry, device)
self.hass.data[DOMAIN][COORDINATORS].append(coordo)
self.entry.runtime_data.coordinators.append(coordo)
await coordo.async_refresh()
async_dispatcher_send(self.hass, DISPATCH_DEVICE_DISCOVERED, coordo)
async def device_update(self, device_info: DeviceInfo) -> None:
"""Handle updates in device information, update if ip has changed."""
for coordinator in self.hass.data[DOMAIN][COORDINATORS]:
for coordinator in self.entry.runtime_data.coordinators:
if coordinator.device.device_info.mac == device_info.mac:
coordinator.device.device_info.ip = device_info.ip
await coordinator.async_refresh()

View File

@ -13,13 +13,13 @@ from homeassistant.components.switch import (
SwitchEntity,
SwitchEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import COORDINATORS, DISPATCH_DEVICE_DISCOVERED, DOMAIN
from .entity import GreeEntity
from .const import DISPATCH_DEVICE_DISCOVERED
from .coordinator import GreeConfigEntry
from .entity import DeviceDataUpdateCoordinator, GreeEntity
@dataclass(kw_only=True, frozen=True)
@ -92,13 +92,13 @@ GREE_SWITCHES: tuple[GreeSwitchEntityDescription, ...] = (
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
entry: GreeConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Gree HVAC device from a config entry."""
@callback
def init_device(coordinator):
def init_device(coordinator: DeviceDataUpdateCoordinator) -> None:
"""Register the device."""
async_add_entities(
@ -106,7 +106,7 @@ async def async_setup_entry(
for description in GREE_SWITCHES
)
for coordinator in hass.data[DOMAIN][COORDINATORS]:
for coordinator in entry.runtime_data.coordinators:
init_device(coordinator)
entry.async_on_unload(

View File

@ -6,11 +6,7 @@ from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN, HVACMode
from homeassistant.components.gree.const import (
COORDINATORS,
DOMAIN as GREE,
UPDATE_INTERVAL,
)
from homeassistant.components.gree.const import UPDATE_INTERVAL
from homeassistant.core import HomeAssistant
from homeassistant.util import dt as dt_util
@ -42,13 +38,13 @@ async def test_discovery_after_setup(
discovery.return_value.mock_devices = [mock_device_1, mock_device_2]
device.side_effect = [mock_device_1, mock_device_2]
await async_setup_gree(hass)
entry = await async_setup_gree(hass)
await hass.async_block_till_done()
assert discovery.return_value.scan_count == 1
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 2
device_infos = [x.device.device_info for x in hass.data[GREE][COORDINATORS]]
device_infos = [x.device.device_info for x in entry.runtime_data.coordinators]
assert device_infos[0].ip == "1.1.1.1"
assert device_infos[1].ip == "2.2.2.2"
@ -70,7 +66,7 @@ async def test_discovery_after_setup(
assert discovery.return_value.scan_count == 2
assert len(hass.states.async_all(CLIMATE_DOMAIN)) == 2
device_infos = [x.device.device_info for x in hass.data[GREE][COORDINATORS]]
device_infos = [x.device.device_info for x in entry.runtime_data.coordinators]
assert device_infos[0].ip == "1.1.1.2"
assert device_infos[1].ip == "2.2.2.1"