From 6127a9a0418f7bf08f9eff874f3a76add5698fba Mon Sep 17 00:00:00 2001 From: Jeef Date: Wed, 29 Jun 2022 12:01:38 -0600 Subject: [PATCH] Intellifire climate Entity (#70818) Co-authored-by: J. Nick Koston --- .coveragerc | 1 + .../components/intellifire/__init__.py | 2 +- .../components/intellifire/climate.py | 120 ++++++++++++++++++ homeassistant/components/intellifire/const.py | 2 + .../components/intellifire/coordinator.py | 2 +- 5 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/intellifire/climate.py diff --git a/.coveragerc b/.coveragerc index f52631a57bd..2443e30a2c3 100644 --- a/.coveragerc +++ b/.coveragerc @@ -555,6 +555,7 @@ omit = homeassistant/components/insteon/utils.py homeassistant/components/intellifire/__init__.py homeassistant/components/intellifire/coordinator.py + homeassistant/components/intellifire/climate.py homeassistant/components/intellifire/binary_sensor.py homeassistant/components/intellifire/sensor.py homeassistant/components/intellifire/switch.py diff --git a/homeassistant/components/intellifire/__init__.py b/homeassistant/components/intellifire/__init__.py index 034e74c2aa6..5fb8ac92a72 100644 --- a/homeassistant/components/intellifire/__init__.py +++ b/homeassistant/components/intellifire/__init__.py @@ -20,7 +20,7 @@ from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from .const import CONF_USER_ID, DOMAIN, LOGGER from .coordinator import IntellifireDataUpdateCoordinator -PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR, Platform.SWITCH] +PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR, Platform.CLIMATE, Platform.SWITCH] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: diff --git a/homeassistant/components/intellifire/climate.py b/homeassistant/components/intellifire/climate.py new file mode 100644 index 00000000000..37a126bf3d6 --- /dev/null +++ b/homeassistant/components/intellifire/climate.py @@ -0,0 +1,120 @@ +"""Intellifire Climate Entities.""" +from __future__ import annotations + +from homeassistant.components.climate import ( + ClimateEntity, + ClimateEntityDescription, + ClimateEntityFeature, +) +from homeassistant.components.climate.const import HVACMode +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import IntellifireDataUpdateCoordinator +from .const import DEFAULT_THERMOSTAT_TEMP, DOMAIN, LOGGER +from .entity import IntellifireEntity + +INTELLIFIRE_CLIMATES: tuple[ClimateEntityDescription, ...] = ( + ClimateEntityDescription(key="climate", name="Thermostat"), +) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Configure the fan entry..""" + coordinator: IntellifireDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] + + if coordinator.data.has_thermostat: + async_add_entities( + IntellifireClimate( + coordinator=coordinator, + description=description, + ) + for description in INTELLIFIRE_CLIMATES + ) + + +class IntellifireClimate(IntellifireEntity, ClimateEntity): + """Intellifire climate entity.""" + + entity_description: ClimateEntityDescription + + _attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF] + _attr_min_temp = 0 + _attr_max_temp = 37 + _attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE + _attr_target_temperature_step = 1.0 + _attr_temperature_unit = TEMP_CELSIUS + last_temp = DEFAULT_THERMOSTAT_TEMP + + def __init__( + self, + coordinator: IntellifireDataUpdateCoordinator, + description: ClimateEntityDescription, + ) -> None: + """Configure climate entry - and override last_temp if the thermostat is currently on.""" + super().__init__(coordinator, description) + + if coordinator.data.thermostat_on: + self.last_temp = coordinator.data.thermostat_setpoint_c + + @property + def hvac_mode(self) -> str: + """Return current hvac mode.""" + if self.coordinator.read_api.data.thermostat_on: + return HVACMode.HEAT + return HVACMode.OFF + + async def async_set_temperature(self, **kwargs) -> None: + """Turn on thermostat by setting a target temperature.""" + raw_target_temp = kwargs[ATTR_TEMPERATURE] + self.last_temp = int(raw_target_temp) + LOGGER.debug( + "Setting target temp to %sc %sf", + int(raw_target_temp), + (raw_target_temp * 9 / 5) + 32, + ) + await self.coordinator.control_api.set_thermostat_c( + fireplace=self.coordinator.control_api.default_fireplace, + temp_c=self.last_temp, + ) + + @property + def current_temperature(self) -> float: + """Return the current temperature.""" + return float(self.coordinator.read_api.data.temperature_c) + + @property + def target_temperature(self) -> float: + """Return target temperature.""" + return float(self.coordinator.read_api.data.thermostat_setpoint_c) + + async def async_set_hvac_mode(self, hvac_mode: str) -> None: + """Set HVAC mode to normal or thermostat control.""" + LOGGER.debug( + "Setting mode to [%s] - using last temp: %s", hvac_mode, self.last_temp + ) + + if hvac_mode == HVACMode.OFF: + await self.coordinator.control_api.turn_off_thermostat( + fireplace=self.coordinator.control_api.default_fireplace + ) + return + + # hvac_mode == HVACMode.HEAT + # 1) Set the desired target temp + await self.coordinator.control_api.set_thermostat_c( + fireplace=self.coordinator.control_api.default_fireplace, + temp_c=self.last_temp, + ) + + # 2) Make sure the fireplace is on! + if not self.coordinator.read_api.data.is_on: + await self.coordinator.control_api.flame_on( + fireplace=self.coordinator.control_api.default_fireplace, + ) diff --git a/homeassistant/components/intellifire/const.py b/homeassistant/components/intellifire/const.py index 2e9a2fabc06..cae25ea11ae 100644 --- a/homeassistant/components/intellifire/const.py +++ b/homeassistant/components/intellifire/const.py @@ -10,3 +10,5 @@ CONF_USER_ID = "user_id" LOGGER = logging.getLogger(__package__) CONF_SERIAL = "serial" + +DEFAULT_THERMOSTAT_TEMP = 21 diff --git a/homeassistant/components/intellifire/coordinator.py b/homeassistant/components/intellifire/coordinator.py index 39f197285d4..356ddedf16d 100644 --- a/homeassistant/components/intellifire/coordinator.py +++ b/homeassistant/components/intellifire/coordinator.py @@ -45,7 +45,7 @@ class IntellifireDataUpdateCoordinator(DataUpdateCoordinator[IntellifirePollData except (ConnectionError, ClientConnectionError) as exception: raise UpdateFailed from exception - LOGGER.info("Failure Count %d", self._api.failed_poll_attempts) + LOGGER.debug("Failure Count %d", self._api.failed_poll_attempts) if self._api.failed_poll_attempts > 10: LOGGER.debug("Too many polling errors - raising exception") raise UpdateFailed