"""Automation-plan sensors exposed by GREE Controller.""" from __future__ import annotations from typing import Any from homeassistant.components.sensor import SensorEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import GreeControllerRuntimeData from .const import DOMAIN from .coordinator import GreeControllerCoordinator async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Create whole-house and per-zone automation-plan sensors.""" runtime: GreeControllerRuntimeData = entry.runtime_data entities: list[SensorEntity] = [GreeControllerHousePlanSensor(runtime.coordinator)] for zone in runtime.coordinator.plan.get("zones", []): if zone.get("zone_id"): entities.append(GreeControllerZonePlanSensor(runtime.coordinator, str(zone["zone_id"]))) async_add_entities(entities) class GreeControllerHousePlanSensor(CoordinatorEntity[GreeControllerCoordinator], SensorEntity): """Summary of the current whole-house control plan.""" _attr_has_entity_name = True _attr_name = "Automation plan" _attr_unique_id = "house-control-plan" _unrecorded_attributes = frozenset({"next_events", "rules"}) @property def native_value(self) -> str: return str(self.coordinator.plan.get("house_mode") or "unknown") @property def device_info(self) -> DeviceInfo: return DeviceInfo( identifiers={(DOMAIN, "controller")}, name="GREE Controller", manufacturer="GREE Controller", model="Local controller", ) @property def extra_state_attributes(self) -> dict[str, Any]: plan = self.coordinator.plan zones = plan.get("zones", []) return { "generated_at": plan.get("generated_at"), "outdoor_temperature": plan.get("outdoor_temperature"), "control_strategy": plan.get("control_strategy"), "work_profile": plan.get("house_preset"), "master_power": bool(plan.get("house_power", False)), "enabled_zones": sum(bool(zone.get("enabled")) for zone in zones), "demanding_zones": sum(bool(zone.get("enabled")) and bool(zone.get("demand")) for zone in zones), "next_events": plan.get("next_events", []), "rules": plan.get("rules", []), } class GreeControllerZonePlanSensor(CoordinatorEntity[GreeControllerCoordinator], SensorEntity): """Readable automation plan for one controller zone.""" _attr_has_entity_name = True _attr_name = "Control plan" _unrecorded_attributes = frozenset({"next_events"}) def __init__(self, coordinator: GreeControllerCoordinator, zone_id: str) -> None: super().__init__(coordinator) self._zone_id = zone_id self._attr_unique_id = f"{zone_id}-control-plan" @property def _zone(self) -> dict[str, Any]: for zone in self.coordinator.plan.get("zones", []): if str(zone.get("zone_id")) == self._zone_id: return zone return {} @property def available(self) -> bool: return super().available and bool(self._zone) @property def native_value(self) -> str: zone = self._zone if not zone.get("enabled", False): return "disabled" return "requesting" if zone.get("demand", False) else "satisfied" @property def device_info(self) -> DeviceInfo: zone = self._zone return DeviceInfo( identifiers={(DOMAIN, f"zone:{self._zone_id}")}, name=str(zone.get("zone_name") or self._zone_id), manufacturer="GREE Controller", model="Zone thermostat", via_device=(DOMAIN, "controller"), ) @property def extra_state_attributes(self) -> dict[str, Any]: zone = self._zone return { "zone_id": self._zone_id, "device_id": zone.get("device_id"), "device_name": zone.get("device_name"), "mode": zone.get("mode"), "preset": zone.get("preset"), "current_temperature": zone.get("current_temperature"), "target_temperature": zone.get("target_temperature"), "device_setpoint": zone.get("device_setpoint"), "control_source": zone.get("control_source"), "manual_override_until": zone.get("manual_override_until"), "current_schedule": zone.get("current_schedule_name"), "next_events": zone.get("next_events", []), }