From 0af96f60a5b4d58deeec825e153ea90ef4098987 Mon Sep 17 00:00:00 2001 From: marq24 Date: Thu, 31 Aug 2023 10:50:10 +0200 Subject: [PATCH] - moved temperatures from Sensor to Diagnose - added FAN status (if available at all) as diagnose info --- custom_components/senec/__init__.py | 2 +- custom_components/senec/binary_sensor.py | 78 +++++++++++++++++++ custom_components/senec/const.py | 51 ++++++++++++ .../senec/pysenec_ha/__init__.py | 11 +++ 4 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 custom_components/senec/binary_sensor.py diff --git a/custom_components/senec/__init__.py b/custom_components/senec/__init__.py index e41ab3e..24f718d 100644 --- a/custom_components/senec/__init__.py +++ b/custom_components/senec/__init__.py @@ -32,7 +32,7 @@ SCAN_INTERVAL = timedelta(seconds=60) CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA) -PLATFORMS = ["sensor", "switch"] +PLATFORMS = ["sensor", "binary_sensor", "switch"] async def async_setup(hass: HomeAssistant, config: dict): diff --git a/custom_components/senec/binary_sensor.py b/custom_components/senec/binary_sensor.py new file mode 100644 index 0000000..275a621 --- /dev/null +++ b/custom_components/senec/binary_sensor.py @@ -0,0 +1,78 @@ +"""Binary sensor platform for Waterkotte Heatpump.""" +import logging + +from homeassistant.components.binary_sensor import BinarySensorEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.helpers.typing import HomeAssistantType +from homeassistant.util import slugify +from homeassistant.const import STATE_ON, STATE_OFF, CONF_TYPE + +from typing import Literal +from . import SenecDataUpdateCoordinator, SenecEntity +from .const import DOMAIN, MAIN_BIN_SENSOR_TYPES, CONF_SYSTYPE_INVERTER, ExtBinarySensorEntityDescription + +_LOGGER = logging.getLogger(__name__) + +async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry, async_add_entities): + coordinator = hass.data[DOMAIN][config_entry.entry_id] + if (CONF_TYPE in config_entry.data and config_entry.data[CONF_TYPE] == CONF_SYSTYPE_INVERTER): + _LOGGER.info("No switches for Inverters...") + else: + entities = [] + for description in MAIN_BIN_SENSOR_TYPES: + entity = SenecBinarySensor(coordinator, description) + entities.append(entity) + async_add_entities(entities) + + +class SenecBinarySensor(SenecEntity, BinarySensorEntity): + def __init__( + self, + coordinator: SenecDataUpdateCoordinator, + description: ExtBinarySensorEntityDescription + ): + """Initialize a singular value sensor.""" + super().__init__(coordinator=coordinator, description=description) + if (hasattr(self.entity_description, 'entity_registry_enabled_default')): + self._attr_entity_registry_enabled_default = self.entity_description.entity_registry_enabled_default + else: + self._attr_entity_registry_enabled_default = True + + title = self.coordinator._entry.title + key = self.entity_description.key + name = self.entity_description.name + self.entity_id = f"binary_sensor.{slugify(title)}_{key}" + self._attr_name = f"{title} {name}" + self._attr_icon = self.entity_description.icon + self._attr_icon_off = self.entity_description.icon_off + + @property + def is_on(self) -> bool | None: + """Return true if the binary_sensor is on.""" + # return self.coordinator.data.get("title", "") == "foo" + try: + value = getattr(self.coordinator.senec, self.entity_description.key) + if value is None or value == "": + value = None + else: + self._attr_is_on = value + except KeyError: + value = None + except TypeError: + return None + return value + + @property + def state(self) -> Literal["on", "off"] | None: + """Return the state.""" + if (is_on := self.is_on) is None: + return None + return STATE_ON if is_on else STATE_OFF + + @ property + def icon(self): + """Return the icon of the sensor.""" + if self.state == STATE_ON: + return self._attr_icon + else: + return self._attr_icon_off diff --git a/custom_components/senec/const.py b/custom_components/senec/const.py index 635ff93..87c2019 100644 --- a/custom_components/senec/const.py +++ b/custom_components/senec/const.py @@ -2,6 +2,7 @@ from typing import Final from dataclasses import dataclass +from homeassistant.components.binary_sensor import BinarySensorEntityDescription from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntityDescription, @@ -16,6 +17,7 @@ UnitOfElectricPotential, UnitOfElectricCurrent, UnitOfFrequency, ) +from homeassistant.helpers.entity import EntityCategory DOMAIN: Final = "senec" MANUFACTURE: Final = "SENEC GmbH" @@ -60,6 +62,9 @@ class ExtSensorEntityDescription(SensorEntityDescription): controls: list[str] | None = None +@dataclass +class ExtBinarySensorEntityDescription(BinarySensorEntityDescription): + icon_off: str | None = None """Supported main unit switch types.""" MAIN_SWITCH_TYPES = [ @@ -76,6 +81,25 @@ class ExtSensorEntityDescription(SensorEntityDescription): ), ] +"""Supported main unit binary_sensor types.""" +MAIN_BIN_SENSOR_TYPES = [ + ExtBinarySensorEntityDescription( + key="fan_inv_lv", + name="Fan LV-Inverter", + icon="mdi:fan", + icon_off="mdi:fan-off", + entity_category=EntityCategory.DIAGNOSTIC, + ), + ExtBinarySensorEntityDescription( + entity_registry_enabled_default=False, + key="fan_inv_hv", + name="Fan HV-Inverter", + icon="mdi:fan", + icon_off="mdi:fan-off", + entity_category=EntityCategory.DIAGNOSTIC, + ), +] + """Supported main unit sensor types.""" MAIN_SENSOR_TYPES = [ ExtSensorEntityDescription( @@ -88,18 +112,21 @@ class ExtSensorEntityDescription(SensorEntityDescription): name="Battery Temperature", native_unit_of_measurement=TEMP_CELSIUS, icon="mdi:thermometer", + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( key="case_temp", name="Case Temperature", native_unit_of_measurement=TEMP_CELSIUS, icon="mdi:thermometer", + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( key="mcu_temp", name="Controller Temperature", native_unit_of_measurement=TEMP_CELSIUS, icon="mdi:thermometer", + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( key="solar_generated_power", @@ -496,6 +523,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -505,6 +533,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -514,6 +543,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -523,6 +553,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -532,6 +563,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -541,6 +573,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -550,6 +583,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -559,6 +593,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -568,6 +603,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -577,6 +613,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -586,6 +623,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -595,6 +633,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -604,6 +643,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -613,6 +653,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -622,6 +663,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -631,6 +673,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -640,6 +683,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -649,6 +693,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -658,6 +703,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -667,6 +713,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -676,6 +723,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -685,6 +733,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -694,6 +743,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( entity_registry_enabled_default=False, @@ -703,6 +753,7 @@ class ExtSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, ), ExtSensorEntityDescription( diff --git a/custom_components/senec/pysenec_ha/__init__.py b/custom_components/senec/pysenec_ha/__init__.py index 0e4a69e..50b6964 100644 --- a/custom_components/senec/pysenec_ha/__init__.py +++ b/custom_components/senec/pysenec_ha/__init__.py @@ -848,6 +848,16 @@ def wallbox_energy(self) -> float: if hasattr(self, '_raw') and "STATISTIC" in self._raw and "LIVE_WB_ENERGY" in self._raw["STATISTIC"]: return self._raw["STATISTIC"]["LIVE_WB_ENERGY"][0] + @property + def fan_inv_lv(self) -> bool: + if hasattr(self, '_raw') and "FAN_SPEED" in self._raw and "INV_LV" in self._raw["FAN_SPEED"]: + return self._raw["FAN_SPEED"]["INV_LV"] + @property + def fan_inv_hv(self) -> bool: + if hasattr(self, '_raw') and "FAN_SPEED" in self._raw and "INV_HV" in self._raw["FAN_SPEED"]: + return self._raw["FAN_SPEED"]["INV_HV"] + + async def update(self): await self.read_senec_v31() @@ -919,6 +929,7 @@ async def read_senec_v31(self): "L3_CHARGING_CURRENT": "", "EV_CONNECTED": "" }, + "FAN_SPEED":{}, } async with self.websession.post(self.url, json=form, ssl=False) as res: