""" Custom integration for heat pump monitoring via web interface. Place this code in custom_components/heat_pump_monitor/__init__.py """ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant async def async_setup(hass: HomeAssistant, config: dict) -> bool: """Set up the Heat Pump Monitor component.""" hass.data.setdefault(DOMAIN, {}) return True async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) if unload_ok: hass.data[DOMAIN].pop(entry.entry_id) return unload_ok import asyncio import logging import aiohttp from datetime import timedelta from homeassistant.core import HomeAssistant from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( CONF_URL, CONF_SCAN_INTERVAL, UnitOfTemperature, TIME_HOURS, ) from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, UpdateFailed, ) _LOGGER = logging.getLogger(__name__) DOMAIN = "heat_pump_monitor" DEFAULT_SCAN_INTERVAL = 3 PLATFORMS = ["sensor", "binary_sensor"] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up heat pump monitor from a config entry.""" url = entry.data[CONF_URL] scan_interval = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) coordinator = HeatPumpDataCoordinator( hass, _LOGGER, url=url, update_interval=timedelta(seconds=scan_interval), ) await coordinator.async_config_entry_first_refresh() hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = coordinator await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True class HeatPumpDataCoordinator(DataUpdateCoordinator): """Class to manage fetching heat pump data.""" def __init__( self, hass: HomeAssistant, logger: logging.Logger, url: str, update_interval: timedelta, ) -> None: """Initialize.""" super().__init__( hass, logger, name=DOMAIN, update_interval=update_interval, ) self.url = url async def _async_update_data(self): """Fetch data from heat pump.""" try: async with aiohttp.ClientSession() as session: async with session.get(self.url) as response: if response.status != 200: raise UpdateFailed(f"Error fetching data: {response.status}") data = await response.json() if not data.get("success", False): raise UpdateFailed("Heat pump returned unsuccessful response") status = data.get("RESULT", {}).get("status", {}) return { "software_version": data.get("sw", {}).get("V"), "last_update": data.get("RESULT", {}).get("TSLastUpdate"), "datetime": data.get("RESULT", {}).get("info", {}).get("datetime"), # Temperature readings # heating smart setpoint? "inlet_setpoint_temp": float(status.get("ISP", "0").split()[0]), # sanitary setpoint? "system_setpoint_temp": status.get("SSP"), "water_temp_t1": status.get("watert1"), "water_temp_t2": status.get("watert2"), "dhw_temp_t3": status.get("dhwt3"), "outdoor_temp_t4": status.get("t4"), # Setpoints # heating water normal setpoint "water_setpoint": status.get("watersetpoint"), "dhw_setpoint": status.get("dhwsetpoint"), # Operation states "is_heating": status.get("heating", False), "is_working": status.get("pwr", False), "is_cooling": status.get("cooling", False), "is_dhw": status.get("san", False), "is_pump_active": status.get("pump", False), "is_aux_heater" : status.get("res",False), "aux_heater": status.get("auxheater", 0), "is_standby": status.get("standby", False), "disabled_prod": status.get("disableProd",False), "sce": status.get("sce",False), # Operation times "worktime_pdc": status.get("worktime_pdc", 0), "worktime_res": status.get("worktime_res", 0), # Alarm status "has_alarm": status.get("alarm", {}).get("status", False), "alarm_type": status.get("alarm", {}).get("type", ""), "alarm_label": status.get("alarm", {}).get("label", ""), } except aiohttp.ClientError as err: raise UpdateFailed(f"Error communicating with heat pump: {err}")