From 2c0d9e3a93acc39b9a35cb6a8bfb807dea14f343 Mon Sep 17 00:00:00 2001 From: cyr-ius Date: Tue, 3 Dec 2024 19:47:48 +0100 Subject: [PATCH] Add humidity information --- custom_components/heatzy/climate.py | 97 +++++++++++++---------------- custom_components/heatzy/const.py | 2 +- custom_components/heatzy/sensor.py | 85 ------------------------- 3 files changed, 46 insertions(+), 138 deletions(-) delete mode 100644 custom_components/heatzy/sensor.py diff --git a/custom_components/heatzy/climate.py b/custom_components/heatzy/climate.py index f197528..07b0d63 100644 --- a/custom_components/heatzy/climate.py +++ b/custom_components/heatzy/climate.py @@ -2,14 +2,13 @@ from __future__ import annotations +import logging from collections.abc import Callable from dataclasses import dataclass -import logging from typing import Any, Final -from heatzypy.exception import HeatzyException import voluptuous as vol - +from heatzypy.exception import HeatzyException from homeassistant.components.climate import ( ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, @@ -25,8 +24,9 @@ HVACMode, ) from homeassistant.const import CONF_DELAY, UnitOfTemperature -from homeassistant.core import HomeAssistant -from homeassistant.helpers import config_validation as cv, entity_platform +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers import entity_platform from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import HeatzyConfigEntry, HeatzyDataUpdateCoordinator @@ -42,6 +42,7 @@ CONF_DEROG_TIME, CONF_ECO_TEMP, CONF_HEATING_STATE, + CONF_HUMIDITY, CONF_IS_ONLINE, CONF_MODE, CONF_ON_OFF, @@ -223,7 +224,7 @@ class HeatzyClimateEntityDescription(ClimateEntityDescription): temperature_low=CFT_TEMP_L, eco_temperature_high=ECO_TEMP_H, eco_temperature_low=ECO_TEMP_L, - target_temperature_step=1, + target_temperature_step=0.1, ), HeatzyClimateEntityDescription( key="bloom", @@ -261,6 +262,7 @@ class HeatzyClimateEntityDescription(ClimateEntityDescription): current_temperature=CONF_CUR_TEMP, temperature_high=CONF_CFT_TEMP, temperature_low=CONF_ECO_TEMP, + target_temperature_step=0.1, ), HeatzyClimateEntityDescription( key="pilotepro_v1", @@ -301,7 +303,7 @@ class HeatzyClimateEntityDescription(ClimateEntityDescription): current_temperature=CONF_CUR_TEMP, temperature_high=CONF_CFT_TEMP, temperature_low=CONF_ECO_TEMP, - target_temperature_step=1, + target_temperature_step=0.1, ), ) @@ -351,21 +353,19 @@ def __init__( @property def hvac_action(self) -> HVACAction: - """Return hvac action ie. heat, cool mode.""" - mode = self._attrs.get(CONF_MODE) - return ( - HVACAction.OFF - if mode == self.entity_description.stop - else HVACAction.HEATING - ) + """Return hvac action ie. heating, off mode.""" + if self._attrs.get(CONF_TIMER_SWITCH) == 1: + return HVACMode.AUTO + if self._attrs.get(CONF_MODE) == self.entity_description.stop: + return HVACAction.OFF + + return HVACAction.HEATING @property def hvac_mode(self) -> HVACMode: - """Return hvac operation ie. heat, cool mode.""" + """Return hvac mode ie. heat, auto, off.""" if self._attrs.get(CONF_TIMER_SWITCH) == 1: return HVACMode.AUTO - - # If preset mode is NONE set HVAC Mode to OFF if self._attrs.get(CONF_MODE) == self.entity_description.stop: return HVACMode.OFF # otherwise set HVAC Mode to HEAT @@ -418,7 +418,7 @@ async def async_presence_detection(self) -> None: """Presence detection derog.""" raise NotImplementedError - # @callback + @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" self._attrs = self.coordinator.data.get(self.unique_id, {}).get(CONF_ATTRS, {}) @@ -622,7 +622,7 @@ class HeatzyPiloteV3Thermostat(HeatzyPiloteV2Thermostat): """Pilote_Soc_C3, Elec_Pro_Ble, Sauter.""" -class Glowv1Thermostat(HeatzyPiloteV2Thermostat): +class Glowv1Thermostat(HeatzyPiloteV3Thermostat): """Glow.""" @property @@ -647,15 +647,26 @@ def target_temperature_low(self) -> float: eco_tempL = self._attrs.get(self.entity_description.eco_temperature_low, 0) return (eco_tempL + (eco_tempH * 256)) / 10 + @property + def hvac_action(self) -> HVACAction: + """Return hvac action ie. heating, off mode.""" + if self._attrs.get(CONF_TIMER_SWITCH) == 1: + return HVACMode.AUTO + if self.hvac_mode == HVACMode.OFF: + return HVACAction.OFF + if self.target_temperature and ( + self.current_temperature > self.target_temperature + ): + return HVACAction.OFF + return HVACAction.HEATING + @property def hvac_mode(self) -> HVACMode: """Return hvac operation ie. heat, cool mode.""" if self._attrs.get(CONF_TIMER_SWITCH) == 1: return HVACMode.AUTO - if self._attrs.get(CONF_ON_OFF) == 0: return HVACMode.OFF - # Otherwise set HVAC Mode to HEAT return HVACMode.HEAT @property @@ -672,22 +683,6 @@ def target_temperature(self) -> float | None: return FROST_TEMP return None - @property - def hvac_action(self) -> HVACAction: - """Return hvac action ie. heat, cool mode.""" - if self._attrs.get(CONF_TIMER_SWITCH) == 1: - return HVACMode.AUTO - if self.hvac_mode == HVACMode.OFF: - return HVACAction.OFF - - # If Target temp is higher than current temp then set HVAC Action to HEATING - if self.target_temperature and ( - self.current_temperature < self.target_temperature - ): - return HVACAction.HEATING - # Otherwise set to IDLE - return HVACAction.IDLE - @property def preset_mode(self) -> str | None: """Return the current preset mode, e.g., home, away, temp.""" @@ -819,14 +814,11 @@ def hvac_action(self) -> HVACAction: return HVACMode.AUTO if self.hvac_mode == HVACMode.OFF: return HVACAction.OFF - - # If Target temp is higher than current temp then set HVAC Action to HEATING if self.target_temperature and ( - self.current_temperature < self.target_temperature + self.current_temperature > self.target_temperature ): - return HVACAction.HEATING - # Otherwise set to IDLE - return HVACAction.IDLE + return HVACAction.OFF + return HVACAction.HEATING async def async_set_temperature(self, **kwargs: Any) -> None: """Set new target temperature.""" @@ -853,6 +845,11 @@ async def async_set_temperature(self, **kwargs: Any) -> None: class HeatzyPiloteProV1(HeatzyPiloteV3Thermostat): """Heatzy Pilote Pro.""" + @property + def current_humidity(self) -> float: + """Return current humidity.""" + return self._attrs.get(CONF_HUMIDITY) + @property def current_temperature(self) -> float: """Return current temperature.""" @@ -883,22 +880,18 @@ def target_temperature(self) -> float | None: @property def hvac_action(self) -> HVACAction: - """Return hvac action ie. heat, cool mode.""" + """Return hvac action ie. heating, off mode.""" if self._attrs.get(CONF_TIMER_SWITCH) == 1: return HVACMode.AUTO if self.hvac_mode == HVACMode.OFF: return HVACAction.OFF - - # if Target tem is reached if self._attrs.get(CONF_HEATING_STATE) == 1: - return HVACAction.IDLE - # If Target temp is higher than current temp then set HVAC Action to HEATING + return HVACAction.OFF if self.target_temperature and ( - self.current_temperature < self.target_temperature + self.current_temperature > self.target_temperature ): - return HVACAction.HEATING - # Otherwise set to IDLE - return HVACAction.IDLE + return HVACAction.OFF + return HVACAction.HEATING async def async_set_preset_mode(self, preset_mode: str) -> None: """Set new preset mode.""" diff --git a/custom_components/heatzy/const.py b/custom_components/heatzy/const.py index 2d5473a..852e99f 100644 --- a/custom_components/heatzy/const.py +++ b/custom_components/heatzy/const.py @@ -32,7 +32,7 @@ ECO_TEMP_H = "eco_tempH" ECO_TEMP_L = "eco_tempL" FROST_TEMP = 7 -PLATFORMS = ["climate", "switch", "sensor", "number"] +PLATFORMS = ["climate", "switch", "number"] PRESET_COMFORT_1 = "Comfort 1" PRESET_COMFORT_2 = "Comfort 2" PRESET_PRESENCE_DETECT = "Presence detection" diff --git a/custom_components/heatzy/sensor.py b/custom_components/heatzy/sensor.py deleted file mode 100644 index c433e88..0000000 --- a/custom_components/heatzy/sensor.py +++ /dev/null @@ -1,85 +0,0 @@ -"""Sensor platform.""" - -from __future__ import annotations - -from dataclasses import dataclass -from datetime import date, datetime -from decimal import Decimal -from typing import Final - -from homeassistant.components.sensor import ( - SensorEntity, - SensorEntityDescription, - SensorStateClass, -) -from homeassistant.const import PERCENTAGE -from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.typing import StateType - -from . import HeatzyConfigEntry, HeatzyDataUpdateCoordinator -from .const import CONF_ATTRS, CONF_HUMIDITY -from .entity import HeatzyEntity - - -@dataclass(frozen=True) -class HeatzySensorEntityDescription(SensorEntityDescription): - """Represents an Flow Sensor.""" - - attr: str | None = None - - -SENSOR_TYPES: Final[tuple[HeatzySensorEntityDescription, ...]] = ( - HeatzySensorEntityDescription( - key="humidity", - name="Humidity", - icon="mdi:water-percent", - translation_key="humidity", - native_unit_of_measurement=PERCENTAGE, - state_class=SensorStateClass.MEASUREMENT, - attr=CONF_HUMIDITY, - ), -) - - -async def async_setup_entry( - hass: HomeAssistant, - entry: HeatzyConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up the platform.""" - coordinator = entry.runtime_data - entities = [] - for unique_id, device in coordinator.data.items(): - for description in SENSOR_TYPES: - if device.get(CONF_ATTRS, {}).get(description.attr) is not None: - entities.extend([Sensor(coordinator, description, unique_id)]) - - async_add_entities(entities) - - -class Sensor(HeatzyEntity, SensorEntity): - """Sensor.""" - - _attr_has_entity_name = True - entity_description: HeatzySensorEntityDescription - - def __init__( - self, - coordinator: HeatzyDataUpdateCoordinator, - description: HeatzySensorEntityDescription, - did: str, - ) -> None: - """Initialize switch.""" - super().__init__(coordinator, description, did) - - @property - def native_value(self) -> StateType | date | datetime | Decimal: - """Return the value reported by the sensor.""" - return self._attrs.get(self.entity_description.attr) - - @callback - def _handle_coordinator_update(self) -> None: - """Handle updated data from the coordinator.""" - self._attrs = self.coordinator.data.get(self.unique_id, {}).get(CONF_ATTRS, {}) - self.async_write_ha_state()