From fbfe32af6b3b05760ec7199f2610c4ee828d634b Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Wed, 18 Oct 2023 23:10:30 +0200 Subject: [PATCH 01/16] Improve reported Heatpump Status - migrated fixes for thermal desinfection and passive cooling that were already implemented in the old integration to the new integration - new additional fix for part where thermal desinfection is done using the 2nd heatsource (without heatpump running) --- custom_components/luxtronik/sensor.py | 36 ++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/custom_components/luxtronik/sensor.py b/custom_components/luxtronik/sensor.py index 2b84a0d..39ec5de 100644 --- a/custom_components/luxtronik/sensor.py +++ b/custom_components/luxtronik/sensor.py @@ -21,6 +21,7 @@ CONF_COORDINATOR, CONF_HA_SENSOR_PREFIX, DOMAIN, + LOGGER, DeviceKey, LuxCalculation as LC, LuxOperationMode, @@ -191,8 +192,8 @@ def _handle_coordinator_update( self._attr_cache[SA.EVU_SECOND_END_TIME] = time_now # region Workaround Luxtronik Bug - # Status shows heating but status 3 = no request! - Inverter heater is active but not the heatpump! else: + # Status shows heating but status 3 = no request! - Inverter heater is active but not the heatpump! sl1 = self._get_value(LC.C0117_STATUS_LINE_1) sl3 = self._get_value(LC.C0119_STATUS_LINE_3) add_circ_pump = self._get_value(LC.C0047_ADDITIONAL_CIRCULATION_PUMP) @@ -211,6 +212,39 @@ def _handle_coordinator_update( if sl1 in s1_workaround and sl3 in s3_workaround and not add_circ_pump: # ignore pump forerun self._attr_native_value = LuxOperationMode.no_request.value + + # Status shows heating or no_request, but actual status is thermal_desinfection + # Fixing the part where the heatpump is running + if sl3 == LuxStatus3Option.thermal_desinfection: + # map thermal desinfection to Domestic Water iso Heating + self._attr_native_value = LuxOperationMode.domestic_water.value + + # Status shows heating or no_request, but actual status is thermal_desinfection + # Fixing the part where the heatpump is not running; (only) using 2nd heatsource + s3_workaround: list[str | None] = [ + LuxStatus3Option.no_request, + LuxStatus3Option.cycle_lock, + ] + if sl3 in s3_workaround: + DHW_recirculation = self._get_value(LC.C0038_DHW_RECIRCULATION_PUMP) + AddHeat = self._get_value(LC.C0048_ADDITIONAL_HEAT_GENERATOR) + if AddHeat and DHW_recirculation: + # more fixes to detect thermal desinfection sequences + self._attr_native_value = LuxOperationMode.domestic_water.value + + # Workaround to detect passive cooling operation mode + if self._attr_native_value == LuxOperationMode.no_request.value: + # detect passive cooling + if self.coordinator.detect_cooling_present(): + T_in = self._get_value(LC.C0010_FLOW_IN_TEMPERATURE) + T_out = self._get_value(LC.C0011_FLOW_OUT_TEMPERATURE) + T_heat_in = self._get_value(LC.C0204_HEAT_SOURCE_INPUT_TEMPERATURE) + T_heat_out = self._get_value(LC.C0020_HEAT_SOURCE_OUTPUT_TEMPERATURE) + Flow_WQ = self._get_value(LC.C0173_HEAT_SOURCE_FLOW_RATE) + if (T_out > T_in) and (T_heat_out > T_heat_in) and (Flow_WQ > 0): + #LOGGER.info(f"Cooling mode detected!!!") + self._attr_native_value = LuxOperationMode.cooling.value + # endregion Workaround Luxtronik Bug self._last_state = self._attr_native_value From e62f4a5bf027355a72ee5574e5854459eb3c9fa1 Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Wed, 18 Oct 2023 23:20:49 +0200 Subject: [PATCH 02/16] Structured region formatting --- custom_components/luxtronik/sensor.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/custom_components/luxtronik/sensor.py b/custom_components/luxtronik/sensor.py index 39ec5de..74c53f2 100644 --- a/custom_components/luxtronik/sensor.py +++ b/custom_components/luxtronik/sensor.py @@ -193,7 +193,8 @@ def _handle_coordinator_update( # region Workaround Luxtronik Bug else: - # Status shows heating but status 3 = no request! - Inverter heater is active but not the heatpump! + # region Workaround: Inverter heater is active but not the heatpump! + # Status shows heating but status 3 = no request! sl1 = self._get_value(LC.C0117_STATUS_LINE_1) sl3 = self._get_value(LC.C0119_STATUS_LINE_3) add_circ_pump = self._get_value(LC.C0047_ADDITIONAL_CIRCULATION_PUMP) @@ -212,15 +213,15 @@ def _handle_coordinator_update( if sl1 in s1_workaround and sl3 in s3_workaround and not add_circ_pump: # ignore pump forerun self._attr_native_value = LuxOperationMode.no_request.value + # endregion Workaround: Inverter heater is active but not the heatpump! - # Status shows heating or no_request, but actual status is thermal_desinfection - # Fixing the part where the heatpump is running + # region Workaround Thermal desinfection with heatpump running if sl3 == LuxStatus3Option.thermal_desinfection: # map thermal desinfection to Domestic Water iso Heating self._attr_native_value = LuxOperationMode.domestic_water.value + # endregion Workaround Thermal desinfection with heatpump running - # Status shows heating or no_request, but actual status is thermal_desinfection - # Fixing the part where the heatpump is not running; (only) using 2nd heatsource + # region Workaround Thermal desinfection with (only) using 2nd heatsource s3_workaround: list[str | None] = [ LuxStatus3Option.no_request, LuxStatus3Option.cycle_lock, @@ -231,8 +232,9 @@ def _handle_coordinator_update( if AddHeat and DHW_recirculation: # more fixes to detect thermal desinfection sequences self._attr_native_value = LuxOperationMode.domestic_water.value + # endregion Workaround Thermal desinfection with (only) using 2nd heatsource - # Workaround to detect passive cooling operation mode + # region Workaround Detect passive cooling operation mode if self._attr_native_value == LuxOperationMode.no_request.value: # detect passive cooling if self.coordinator.detect_cooling_present(): @@ -244,7 +246,7 @@ def _handle_coordinator_update( if (T_out > T_in) and (T_heat_out > T_heat_in) and (Flow_WQ > 0): #LOGGER.info(f"Cooling mode detected!!!") self._attr_native_value = LuxOperationMode.cooling.value - + # endregion Workaround Detect passive cooling operation mode # endregion Workaround Luxtronik Bug self._last_state = self._attr_native_value From 3a5786d0ce76e8bce98a1379666e7365317e945a Mon Sep 17 00:00:00 2001 From: BenPru Date: Fri, 20 Oct 2023 18:37:15 +0200 Subject: [PATCH 03/16] * Remove own translation module * Change evu text handling * Change device name handling * Fix locale setting -> removed * Fix async_migrate_entry dependencies * Fix async_get_mac_address -> download diag * Add exception handling in added_to_hass * Add unrecorded_attributes to optimize record handling * Code cleanup --- custom_components/luxtronik/__init__.py | 61 ++++--- custom_components/luxtronik/base.py | 68 +++++--- custom_components/luxtronik/common.py | 2 +- custom_components/luxtronik/const.py | 9 - custom_components/luxtronik/coordinator.py | 165 +++++------------- custom_components/luxtronik/diagnostics.py | 4 +- custom_components/luxtronik/manifest.json | 2 +- custom_components/luxtronik/model.py | 3 +- custom_components/luxtronik/sensor.py | 66 +++++-- .../luxtronik/translations/de.json | 26 ++- .../luxtronik/translations/en.json | 24 ++- .../luxtronik/translations/pl.json | 26 +-- .../luxtronik/translations/texts.de.json | 4 - .../luxtronik/translations/texts.en.json | 4 - .../luxtronik/translations/texts.pl.json | 4 - 15 files changed, 221 insertions(+), 247 deletions(-) delete mode 100644 custom_components/luxtronik/translations/texts.de.json delete mode 100644 custom_components/luxtronik/translations/texts.en.json delete mode 100644 custom_components/luxtronik/translations/texts.pl.json diff --git a/custom_components/luxtronik/__init__.py b/custom_components/luxtronik/__init__.py index eededec..2d5b7ba 100644 --- a/custom_components/luxtronik/__init__.py +++ b/custom_components/luxtronik/__init__.py @@ -102,33 +102,36 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> config_entry.version = 4 hass.config_entries.async_update_entry(config_entry, data=new_data) - if config_entry.version >= 4: - # Ensure sensor prefix: + # Ensure sensor prefix: + prefix = None + ent_reg = None + + def _prepare_up() -> None: prefix = config_entry.data[CONF_HA_SENSOR_PREFIX] ent_reg = async_get(hass) - def _up(ident: str, new_id: SK, platform: P = P.SENSOR) -> None: - entity_id = f"{platform}.{prefix}_{ident}" - new_ident = f"{platform}.{prefix}_{new_id}" - try: - ent_reg.async_update_entity( - entity_id, new_entity_id=new_ident, new_unique_id=new_ident - ) - except KeyError as err: - LOGGER.info( - "Skip rename entity - Not existing: %s->%s", - entity_id, - new_ident, - exc_info=err, - ) - except ValueError as err: - LOGGER.warning( - "Could not rename entity %s->%s", entity_id, new_ident, exc_info=err - ) - except Exception as err: - LOGGER.error( - "Could not rename entity %s->%s", entity_id, new_ident, exc_info=err - ) + def _up(ident: str, new_id: SK, platform: P = P.SENSOR) -> None: + entity_id = f"{platform}.{prefix}_{ident}" + new_ident = f"{platform}.{prefix}_{new_id}" + try: + ent_reg.async_update_entity( + entity_id, new_entity_id=new_ident, new_unique_id=new_ident + ) + except KeyError as err: + LOGGER.info( + "Skip rename entity - Not existing: %s->%s", + entity_id, + new_ident, + exc_info=err, + ) + except ValueError as err: + LOGGER.warning( + "Could not rename entity %s->%s", entity_id, new_ident, exc_info=err + ) + except Exception as err: + LOGGER.error( + "Could not rename entity %s->%s", entity_id, new_ident, exc_info=err + ) if config_entry.version == 4: new_data = {**config_entry.data} @@ -136,6 +139,7 @@ def _up(ident: str, new_id: SK, platform: P = P.SENSOR) -> None: hass.config_entries.async_update_entry(config_entry, data=new_data) if config_entry.version == 5: + _prepare_up() _up("heat_amount_domestic_water", SK.DHW_HEAT_AMOUNT) _up("domestic_water_energy_input", SK.DHW_ENERGY_INPUT) _up("domestic_water_temperature", SK.DHW_TEMPERATURE) @@ -257,14 +261,17 @@ def _up(ident: str, new_id: SK, platform: P = P.SENSOR) -> None: hass.config_entries.async_update_entry(config_entry, data=new_data) if config_entry.version == 6: - _up("cooling_threshold_temperature", SK.COOLING_OUTDOOR_TEMP_THRESHOLD, P.NUMBER) + _prepare_up() + _up( + "cooling_threshold_temperature", SK.COOLING_OUTDOOR_TEMP_THRESHOLD, P.NUMBER + ) _up("cooling_start_delay_hours", SK.COOLING_START_DELAY_HOURS, P.NUMBER) _up("cooling_stop_delay_hours", SK.COOLING_STOP_DELAY_HOURS, P.NUMBER) - + new_data = {**config_entry.data} config_entry.version = 7 hass.config_entries.async_update_entry(config_entry, data=new_data) - + LOGGER.info("Migration to version %s successful", config_entry.version) return True diff --git a/custom_components/luxtronik/base.py b/custom_components/luxtronik/base.py index 6fdaf8b..abaec30 100644 --- a/custom_components/luxtronik/base.py +++ b/custom_components/luxtronik/base.py @@ -2,16 +2,13 @@ # region Imports from __future__ import annotations -from contextlib import suppress from datetime import datetime -import locale from typing import Any from homeassistant.backports.enum import StrEnum from homeassistant.components.water_heater import STATE_HEAT_PUMP from homeassistant.const import STATE_OFF, UnitOfTemperature, UnitOfTime from homeassistant.core import callback -from homeassistant.helpers.typing import UndefinedType from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -21,6 +18,7 @@ from .common import get_sensor_data from .const import ( DeviceKey, + LOGGER, LuxCalculation as LC, LuxMode, LuxOperationMode, @@ -41,6 +39,11 @@ class LuxtronikEntity(CoordinatorEntity[LuxtronikCoordinator], RestoreEntity): next_update: datetime | None = None _attr_cache: dict[SA, Any] = {} + _entity_component_unrecorded_attributes = frozenset( + { + SA.LUXTRONIK_KEY, + } + ) def __init__( self, @@ -50,6 +53,7 @@ def __init__( ) -> None: """Init LuxtronikEntity.""" super().__init__(coordinator=coordinator) + self._device_info_ident = device_info_ident self._attr_extra_state_attributes = { SA.LUXTRONIK_KEY: f"{description.luxtronik_key.name[1:5]} {description.luxtronik_key.value}" } @@ -71,7 +75,7 @@ def __init__( description ) self.entity_description = description - self._attr_device_info = coordinator.device_infos[device_info_ident.value] + self._attr_device_info = coordinator.get_device(device_info_ident) translation_key = ( description.key.value @@ -85,33 +89,39 @@ def __init__( async def async_added_to_hass(self) -> None: """When entity is added to hass.""" await super().async_added_to_hass() - # try set locale for local formatting - with suppress(locale.Error): - ha_locale = f"{self.hass.config.language}_{self.hass.config.country}" - locale.setlocale(locale.LC_ALL, locale.normalize(ha_locale)) - - last_state = await self.async_get_last_state() - if last_state is None: - return - self._attr_state = last_state.state + # Force device name: + self._attr_device_info = self.coordinator.get_device( + self._device_info_ident, self.platform + ) - for attr in self.entity_description.extra_attributes: - if not attr.restore_on_startup or attr.key not in last_state.attributes: - continue - self._attr_cache[attr.key] = self._restore_attr_value( - last_state.attributes[attr.key] + try: + last_state = await self.async_get_last_state() + if last_state is None: + return + self._attr_state = last_state.state + + for attr in self.entity_description.extra_attributes: + if not attr.restore_on_startup or attr.key not in last_state.attributes: + continue + self._attr_cache[attr.key] = self._restore_attr_value( + last_state.attributes[attr.key] + ) + + last_extra_data = await self.async_get_last_extra_data() + if last_extra_data is not None: + data: dict[str, Any] = last_extra_data.as_dict() + for attr in data: + setattr(self, attr, data.get(attr)) + + data_updated = f"{self.entity_id}_data_updated" + async_dispatcher_connect( + self.hass, data_updated, self._schedule_immediate_update + ) + except Exception as err: + LOGGER.error( + "Could not restore latest data (async_added_to_hass)", + exc_info=err, ) - - last_extra_data = await self.async_get_last_extra_data() - if last_extra_data is not None: - data: dict[str, Any] = last_extra_data.as_dict() - for attr in data: - setattr(self, attr, data.get(attr)) - - data_updated = f"{self.entity_id}_data_updated" - async_dispatcher_connect( - self.hass, data_updated, self._schedule_immediate_update - ) def _restore_attr_value(self, value: Any | None) -> Any: return value diff --git a/custom_components/luxtronik/common.py b/custom_components/luxtronik/common.py index 61c5658..2e23aa1 100644 --- a/custom_components/luxtronik/common.py +++ b/custom_components/luxtronik/common.py @@ -108,7 +108,7 @@ def state_as_number_or_none(state: State, default: float | None = None) -> float return default if not isinstance(result, float) or result is None else result -async def _async_get_mac_address(hass: HomeAssistant, host: str) -> str | None: +async def async_get_mac_address(hass: HomeAssistant, host: str) -> str | None: """Get mac address from host name, IPv4 address, or IPv6 address.""" # Help mypy, which has trouble with the async_add_executor_job + partial call mac_address: str | None diff --git a/custom_components/luxtronik/const.py b/custom_components/luxtronik/const.py index ee2198b..1317466 100644 --- a/custom_components/luxtronik/const.py +++ b/custom_components/luxtronik/const.py @@ -638,14 +638,6 @@ class SensorAttrKey(StrEnum): """Luxtronik sensor attribute keys.""" LUXTRONIK_KEY = "Luxtronik_Key" - LUXTRONIK_KEY_CURRENT_ACTION = "luxtronik_key_current_action" - LUXTRONIK_KEY_TARGET_TEMPERATURE = "luxtronik_key_target_temperature" - LUXTRONIK_KEY_CORRECTION_FACTOR = "luxtronik_key_correction_factor" - LUXTRONIK_KEY_CORRECTION_TARGET = "luxtronik_key_correction_target" - LUXTRONIK_KEY_CURRENT_TEMPERATURE = "luxtronik_key_current_temperature" - LUXTRONIK_ACTION_HEATING = "luxtronik_action_heating" - LUXTRONIK_KEY_TARGET_TEMPERATURE_HIGH = "luxtronik_key_target_temperature_high" - LUXTRONIK_KEY_TARGET_TEMPERATURE_LOW = "luxtronik_key_target_temperature_low" STATUS_TEXT = "status_text" LAST_THERMAL_DESINFECTION = "last_thermal_desinfection" @@ -676,5 +668,4 @@ class SensorAttrKey(StrEnum): TIMER_DEFROST = "Abtauen in ID_WEB_Time_AbtIn" TIMER_HOT_GAS = "ID_WEB_Time_Heissgas" - # endregion Attr Keys diff --git a/custom_components/luxtronik/coordinator.py b/custom_components/luxtronik/coordinator.py index 9bfe179..9eebb85 100644 --- a/custom_components/luxtronik/coordinator.py +++ b/custom_components/luxtronik/coordinator.py @@ -4,21 +4,18 @@ import asyncio from collections.abc import Awaitable, Callable, Coroutine, Mapping -from datetime import timedelta from functools import wraps -import json -import os.path -import re import threading from types import MappingProxyType -from typing import Any, Concatenate, Final, TypeVar, cast +from typing import Any, Concatenate, TypeVar from typing_extensions import ParamSpec from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TIMEOUT, Platform +from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TIMEOUT from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import EntityPlatform from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .common import correct_key_value @@ -30,10 +27,8 @@ DEFAULT_MAX_DATA_LENGTH, DEFAULT_TIMEOUT, DOMAIN, - LANG_DEFAULT, LOGGER, LUX_PARAMETER_MK_SENSORS, - PLATFORMS, UPDATE_INTERVAL_FAST, UPDATE_INTERVAL_NORMAL, DeviceKey, @@ -78,9 +73,6 @@ class LuxtronikCoordinator(DataUpdateCoordinator[LuxtronikCoordinatorData]): device_infos = dict[str, DeviceInfo]() update_reason_write = False client: Luxtronik = None - __content_locale__ = dict[Any, Any]() - __content_locale_texts__ = dict[Any, Any]() - __content_sensors_locale__ = dict[Any, Any]() def __init__( self, @@ -92,6 +84,7 @@ def __init__( self.lock = threading.Lock() self.client = client + self._config = config super().__init__( hass, LOGGER, @@ -99,8 +92,6 @@ def __init__( update_method=self._async_update_data, update_interval=UPDATE_INTERVAL_FAST, ) - self._load_translations(hass) - self._create_device_infos(hass, config) async def _async_update_data(self) -> LuxtronikCoordinatorData: """Connect and fetch data.""" @@ -216,74 +207,58 @@ def connect( config=config, ) - def _load_translations(self, hass: HomeAssistant): - """Load translations from file for device and entity names.""" - lang = self._normalize_lang(hass.config.language) - self.__content_locale__ = self._load_lang_from_file(f"translations/{lang}.json") - self.__content_locale_texts__ = self._load_lang_from_file( - f"translations/texts.{lang}.json" - ) - for platform in PLATFORMS: - fname = f"translations/{platform}.{LANG_DEFAULT}.json" - if self._exists_locale_file(self._build_filepath(fname)): - self.__content_sensors_locale__[platform] = self._load_lang_from_file( - fname - ) - - def _normalize_lang(self, lang: str) -> str: - if lang is None: - return LANG_DEFAULT - lang = lang.lower() - if "-" in lang: - lang = lang.split("-")[0] - fname = self._build_filepath(f"translations/{lang}.json") - if not self._exists_locale_file(fname): - return LANG_DEFAULT - return lang - - def _build_filepath(self, fname: str) -> str: - dir_path = os.path.dirname(os.path.realpath(__file__)) - return os.path.join(dir_path, fname) - - def _exists_locale_file(self, fname: str) -> bool: - return os.path.isfile(fname) - - def _load_lang_from_file(self, fname: str, log_warning=True) -> dict: - fname = self._build_filepath(fname) - if not self._exists_locale_file(fname): - if log_warning: - LOGGER.warning("_load_lang_from_file - file not found %s", fname) - return {} - with open(fname, encoding="utf8") as locale_file: - return json.load(locale_file) + def get_device( + self, + key: DeviceKey = DeviceKey.heatpump, + platform: EntityPlatform | None = None, + ) -> DeviceInfo: + if key not in self.device_infos: + self._create_device_infos(self.hass, self._config, platform) + device_info: DeviceInfo = self.device_infos.get(key) + if device_info["name"] == key: + device_info["name"] = self._build_device_name(key, platform) + return device_info def _create_device_infos( self, hass: HomeAssistant, config: Mapping[str, Any], + platform: EntityPlatform | None = None, ): host = config[CONF_HOST] dev = self.device_infos[DeviceKey.heatpump.value] = self._build_device_info( - DeviceKey.heatpump, host + DeviceKey.heatpump, host, platform ) via = ( DOMAIN, f"{self.unique_id}_{DeviceKey.heatpump.value}".lower(), ) self.device_infos[DeviceKey.heating.value] = self._build_device_info( - DeviceKey.heating, host, via + DeviceKey.heating, host, platform, via ) self.device_infos[DeviceKey.domestic_water.value] = self._build_device_info( - DeviceKey.domestic_water, host, via + DeviceKey.domestic_water, host, platform, via ) self.device_infos[DeviceKey.cooling.value] = self._build_device_info( - DeviceKey.cooling, host, via + DeviceKey.cooling, host, platform, via + ) + + def _build_device_name( + self, key: DeviceKey, platform: EntityPlatform | None = None + ) -> str: + if platform is None: + return str(key.value) + return platform.platform_translations.get( + f"component.{DOMAIN}.entity.device.{key.value}.name" ) def _build_device_info( - self, key: DeviceKey, host: str, via_device=None + self, + key: DeviceKey, + host: str, + platform: EntityPlatform | None = None, + via_device=None, ) -> DeviceInfo: - text = self.get_device_entity_title(key.value, "device") return DeviceInfo( identifiers={ ( @@ -292,7 +267,7 @@ def _build_device_info( ) }, entry_type=None, - name=f"{text}", + name=self._build_device_name(key, platform), via_device=via_device, configuration_url=f"http://{host}/", connections={ @@ -311,55 +286,6 @@ def _build_device_info( # default_model=self.model, ) - def get_text(self, key: str) -> str: - """Get a text in locale language.""" - result = self._get_value_recursive(self.__content_locale_texts__, [key]) - if result is not None: - return result - LOGGER.warning( - "Get_text key %s not found in", - key, - ) - return key.replace("_", " ").title() - - def get_device_entity_title(self, key: str, platform: Platform | str) -> str: - """Get a device or entity title text in locale language.""" - result = self._get_value_recursive( - self.__content_locale__, ["entity", platform, key, "name"] - ) - if result is not None: - return result - LOGGER.warning( - "Get_device_entity_title key %s.%s not found in", - platform, - key, - ) - return key.replace("_", " ").title() - - def get_sensor_value_text( - self, key: str, value: str, platform: Platform = Platform.SENSOR - ) -> str: - """Get a sensor value text.""" - result = self._get_value_recursive( - self.__content_locale__, ["entity", platform, key, "state", value] - ) - if result is not None: - return result - LOGGER.warning( - "Get_sensor_value_text key %s / value %s not found", - key, - value, - ) - return key.replace("_", " ").title() - - def _get_value_recursive(self, content: dict, keys: list[str]) -> str | None: - key = keys.pop(0) - if key not in content.keys(): - return None - if len(keys) > 0: - return self._get_value_recursive(cast(dict, content.get(key)), keys) - return str(content.get(key)) - @property def serial_number(self) -> str: """Return the serial number.""" @@ -519,16 +445,19 @@ def _detect_solar_present(self) -> bool: return ( bool(self.get_value(LV.V0250_SOLAR)) or self.get_value(LP.P0882_SOLAR_OPERATION_HOURS) > 0.01 # noqa: W503 - or - ( bool(self.get_value(LV.V0038_SOLAR_COLLECTOR)) # noqa: W503 - and - float(self.get_value(LC.C0026_SOLAR_COLLECTOR_TEMPERATURE)) # noqa: W503 - != 5.0 # noqa: W503 + or ( + bool(self.get_value(LV.V0038_SOLAR_COLLECTOR)) # noqa: W503 + and float( + self.get_value(LC.C0026_SOLAR_COLLECTOR_TEMPERATURE) + ) # noqa: W503 + != 5.0 # noqa: W503 ) - or - ( bool(self.get_value(LV.V0039_SOLAR_BUFFER)) # noqa: W503 - and float(self.get_value(LC.C0027_SOLAR_BUFFER_TEMPERATURE)) # noqa: W503 - != 150.0 # noqa: W503 + or ( + bool(self.get_value(LV.V0039_SOLAR_BUFFER)) # noqa: W503 + and float( + self.get_value(LC.C0027_SOLAR_BUFFER_TEMPERATURE) + ) # noqa: W503 + != 150.0 # noqa: W503 ) ) diff --git a/custom_components/luxtronik/diagnostics.py b/custom_components/luxtronik/diagnostics.py index 2f87283..325ab87 100644 --- a/custom_components/luxtronik/diagnostics.py +++ b/custom_components/luxtronik/diagnostics.py @@ -13,7 +13,7 @@ from .const import CONF_COORDINATOR, DOMAIN from .coordinator import LuxtronikCoordinator -from .common import _async_get_mac_address +from .common import async_get_mac_address # endregion Imports @@ -31,7 +31,7 @@ async def async_get_config_entry_diagnostics( mac: str | None = None async with timeout(10): - mac = await _async_get_mac_address(hass, entry.data[CONF_HOST]) + mac = await async_get_mac_address(hass, entry.data[CONF_HOST]) entry_data = async_redact_data(entry.as_dict(), TO_REDACT) if "data" not in entry_data: diff --git a/custom_components/luxtronik/manifest.json b/custom_components/luxtronik/manifest.json index 047b225..a245d83 100755 --- a/custom_components/luxtronik/manifest.json +++ b/custom_components/luxtronik/manifest.json @@ -9,7 +9,7 @@ "after_dependencies": [], "codeowners": ["@BenPru"], "iot_class": "local_polling", - "version": "2023.10.16", + "version": "2023.10.20", "homeassistant": "2023.1.0", "dhcp": [ { "macaddress": "000E8C*" }, diff --git a/custom_components/luxtronik/model.py b/custom_components/luxtronik/model.py index 3bc495d..abea003 100644 --- a/custom_components/luxtronik/model.py +++ b/custom_components/luxtronik/model.py @@ -28,7 +28,6 @@ from homeassistant.helpers.typing import StateType from .const import ( - UPDATE_INTERVAL_NORMAL, UPDATE_INTERVAL_VERY_SLOW, DeviceKey, FirmwareVersionMinor, @@ -160,7 +159,7 @@ class LuxtronikClimateDescription( luxtronik_key_target_temperature: LuxParameter | LuxCalculation = LuxParameter.UNSET luxtronik_key_correction_factor: LuxParameter = LuxParameter.UNSET luxtronik_key_correction_target: LuxParameter = LuxParameter.UNSET - temperature_unit: str = UnitOfTemperature.CELSIUS + temperature_unit: str = UnitOfTemperature.CELSIUS @dataclass diff --git a/custom_components/luxtronik/sensor.py b/custom_components/luxtronik/sensor.py index 2b84a0d..942c349 100644 --- a/custom_components/luxtronik/sensor.py +++ b/custom_components/luxtronik/sensor.py @@ -66,6 +66,28 @@ class LuxtronikSensorEntity(LuxtronikEntity, SensorEntity): entity_description: LuxtronikSensorDescription _coordinator: LuxtronikCoordinator + _unrecorded_attributes = frozenset( + { + SA.SWITCH_GAP, + SA.CODE, + SA.CAUSE, + SA.REMEDY, + SA.TIMER_HEATPUMP_ON, + SA.TIMER_ADD_HEAT_GENERATOR_ON, + SA.TIMER_SEC_HEAT_GENERATOR_ON, + SA.TIMER_NET_INPUT_DELAY, + SA.TIMER_SCB_OFF, + SA.TIMER_SCB_ON, + SA.TIMER_COMPRESSOR_OFF, + SA.TIMER_HC_ADD, + SA.TIMER_HC_LESS, + SA.TIMER_TDI, + SA.TIMER_BLOCK_DHW, + SA.TIMER_DEFROST, + SA.TIMER_HOT_GAS, + } + ) + def __init__( self, hass: HomeAssistant, @@ -148,6 +170,19 @@ class LuxtronikStatusSensorEntity(LuxtronikSensorEntity, SensorEntity): _attr_cache[SA.EVU_SECOND_START_TIME] = time.min _attr_cache[SA.EVU_SECOND_END_TIME] = time.min + _unrecorded_attributes = frozenset( + LuxtronikSensorEntity._unrecorded_attributes + | { + SA.STATUS_TEXT, + SA.STATUS_RAW, + SA.EVU_FIRST_START_TIME, + SA.EVU_FIRST_END_TIME, + SA.EVU_SECOND_START_TIME, + SA.EVU_SECOND_END_TIME, + SA.EVU_MINUTES_UNTIL_NEXT_EVENT, + } + ) + async def _data_update(self, event): self._handle_coordinator_update() @@ -156,7 +191,6 @@ def _handle_coordinator_update( self, data: LuxtronikCoordinatorData | None = None ) -> None: """Handle updated data from the coordinator.""" - # super()._handle_coordinator_update_internal(data) super()._handle_coordinator_update(data) time_now = time(datetime.now().hour, datetime.now().minute) evu = LuxOperationMode.evu.value @@ -250,29 +284,39 @@ def _build_status_text(self) -> str: status_time = self._get_sensor_attr( f"sensor.{self._sensor_prefix}_status_time", SA.STATUS_TEXT ) - line_1 = self._get_sensor_value(f"sensor.{self._sensor_prefix}_status_line_1") - line_2 = self._get_sensor_value(f"sensor.{self._sensor_prefix}_status_line_2") + line_1_state = self._get_sensor_value( + f"sensor.{self._sensor_prefix}_status_line_1" + ) + line_2_state = self._get_sensor_value( + f"sensor.{self._sensor_prefix}_status_line_2" + ) if status_time is None or status_time == STATE_UNAVAILABLE: return "" - if line_1 is None or line_1 == STATE_UNAVAILABLE: + if line_1_state is None or line_1_state == STATE_UNAVAILABLE: return "" - if line_2 is None or line_2 == STATE_UNAVAILABLE: + if line_2_state is None or line_2_state == STATE_UNAVAILABLE: return "" - line_1 = self.coordinator.get_sensor_value_text("status_line_1", line_1) - line_2 = self.coordinator.get_sensor_value_text("status_line_2", line_2) + line_1 = self.platform.platform_translations.get( + f"component.{DOMAIN}.entity.sensor.status_line_1.state.{line_1_state}" + ) + line_2 = self.platform.platform_translations.get( + f"component.{DOMAIN}.entity.sensor.status_line_2.state.{line_2_state}" + ) # Show evu end time if available evu_event_minutes = self._calc_next_evu_event_minutes() if evu_event_minutes is None: pass elif self.native_value == LuxOperationMode.evu.value: - evu_until = self.coordinator.get_text("evu_until").format( - evu_time=evu_event_minutes + text_locale = self.platform.platform_translations.get( + f"component.{DOMAIN}.entity.sensor.status.state_attributes.evu_text.state.evu_until" ) + evu_until = text_locale.format(evu_time=evu_event_minutes) return f"{evu_until} {line_1} {line_2} {status_time}." elif evu_event_minutes <= 30: - evu_in = self.coordinator.get_text("evu_in").format( - evu_time=evu_event_minutes + text_locale = self.platform.platform_translations.get( + f"component.{DOMAIN}.entity.sensor.status.state_attributes.evu_text.state.evu_in" ) + evu_in = text_locale.format(evu_time=evu_event_minutes) return f"{line_1} {line_2} {status_time}. {evu_in}" return f"{line_1} {line_2} {status_time}." diff --git a/custom_components/luxtronik/translations/de.json b/custom_components/luxtronik/translations/de.json index a4b771c..3329ad7 100644 --- a/custom_components/luxtronik/translations/de.json +++ b/custom_components/luxtronik/translations/de.json @@ -26,7 +26,7 @@ "name": "Systemzustand" }, "circulation_pump_heating": { - "name": "Umw\u00e4lzpumpe Heizung" + "name": "Umw\u00e4lzpumpe" }, "additional_circulation_pump": { "name": "Zusatzumw\u00e4lzpumpe" @@ -142,7 +142,7 @@ "name": "MK3 Heizkurve Nachts" }, "dhw_target_temperature": { - "name": "Brauchwasser soll" + "name": "Soll" }, "dhw_thermal_desinfection_target": { "name": "Thermische Desinfektion Soll Temperatur" @@ -184,7 +184,7 @@ "name": "Effizienzpumpe Minimal" }, "cooling_threshold_temperature": { - "name": "minimale Au\u00dfentemperatur f\u00fcr den K\u00fchlbetrieb" + "name": "minimale Au\u00dfentemperatur" }, "cooling_start_delay_hours": { "name": "Start Verz\u00f6gerung" @@ -192,14 +192,14 @@ "cooling_stop_delay_hours": { "name": "Ende Verz\u00f6gerung" }, - "cooling_target_temperature_mk1": { - "name": "K\u00fchlung Ziel" + "cooling_target_temperature_mk1": { + "name": "K\u00fchlung Ziel" }, - "cooling_target_temperature_mk2": { - "name": "K\u00fchlung Ziel" + "cooling_target_temperature_mk2": { + "name": "K\u00fchlung Ziel" }, - "cooling_target_temperature_mk3": { - "name": "K\u00fchlung Ziel" + "cooling_target_temperature_mk3": { + "name": "K\u00fchlung Ziel" } }, "sensor": { @@ -214,6 +214,14 @@ "heating external source": "Heizt aus externer Quelle", "cooling": "K\u00fchlen", "no request": "Leerlauf (keine Anforderung)" + }, + "state_attributes": { + "evu_text": { + "state": { + "evu_until": "Noch {evu_time} Minuten Netzsperre.", + "evu_in": "Netzsperre in {evu_time} Minuten." + } + } } }, "error_reason": { diff --git a/custom_components/luxtronik/translations/en.json b/custom_components/luxtronik/translations/en.json index b98ab79..4053a8a 100644 --- a/custom_components/luxtronik/translations/en.json +++ b/custom_components/luxtronik/translations/en.json @@ -142,7 +142,7 @@ "name": "HC3 Heating curve night" }, "dhw_target_temperature": { - "name": "Domestic hot water target" + "name": "Target" }, "dhw_thermal_desinfection_target": { "name": "Thermal desinfection target temperature" @@ -184,7 +184,7 @@ "name": "Efficiency pump minimal" }, "cooling_threshold_temperature": { - "name": "Minimal outdoor temperature for cooling mode" + "name": "Minimal outdoor temperature" }, "cooling_start_delay_hours": { "name": "Start delay" @@ -192,14 +192,14 @@ "cooling_stop_delay_hours": { "name": "Stop delay" }, - "cooling_target_temperature_mk1": { - "name": "Cooling target temperature" + "cooling_target_temperature_mk1": { + "name": "Cooling target temperature" }, - "cooling_target_temperature_mk2": { - "name": "Cooling target temperature" + "cooling_target_temperature_mk2": { + "name": "Cooling target temperature" }, - "cooling_target_temperature_mk3": { - "name": "Cooling target temperature" + "cooling_target_temperature_mk3": { + "name": "Cooling target temperature" } }, "sensor": { @@ -214,6 +214,14 @@ "heating external source": "Heating external source", "cooling": "Cooling", "no request": "Idle (no request)" + }, + "state_attributes": { + "evu_text": { + "state": { + "evu_until": "{evu_time} minutes more locktime.", + "evu_in": "Locktime in {evu_time} minutes." + } + } } }, "error_reason": { diff --git a/custom_components/luxtronik/translations/pl.json b/custom_components/luxtronik/translations/pl.json index bddcaf8..d40b740 100644 --- a/custom_components/luxtronik/translations/pl.json +++ b/custom_components/luxtronik/translations/pl.json @@ -155,24 +155,6 @@ }, "heating_night_lowering_to_temperature": { "name": "Ogrzewanie nocne obni\u017Caj\u0105ce temp" - }, - "cooling_threshold_temperature": { - "name": "T_outside >" - }, - "cooling_start_delay_hours": { - "name": "Start delay" - }, - "cooling_stop_delay_hours": { - "name": "Stop delay" - }, - "cooling_target_temperature_mk1": { - "name": "Cooling target temperature" - }, - "cooling_target_temperature_mk2": { - "name": "Cooling target temperature" - }, - "cooling_target_temperature_mk3": { - "name": "Cooling target temperature" } }, "sensor": { @@ -187,6 +169,14 @@ "heating external source": "Zewn\u0119trzne \u017Ar\u00F3d\u0142o ogrzewania", "cooling": "Ch\u0142odzenie", "no request": "Bezczynny (brak \u017C\u0105dania)" + }, + "state_attributes": { + "evu_text": { + "state": { + "evu_until": "Czas blokady d\u0142u\u017Cszy o {evu_time} minut.2", + "evu_in": "Czas blokady za {evu_time} minut." + } + } } }, "error_reason": { diff --git a/custom_components/luxtronik/translations/texts.de.json b/custom_components/luxtronik/translations/texts.de.json deleted file mode 100644 index 280b062..0000000 --- a/custom_components/luxtronik/translations/texts.de.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "evu_until": "Noch {evu_time} Minuten Netzsperre.", - "evu_in": "Netzsperre in {evu_time} Minuten." -} diff --git a/custom_components/luxtronik/translations/texts.en.json b/custom_components/luxtronik/translations/texts.en.json deleted file mode 100644 index 6da039f..0000000 --- a/custom_components/luxtronik/translations/texts.en.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "evu_until": "{evu_time} minutes more locktime.", - "evu_in": "Locktime in {evu_time} minutes." -} diff --git a/custom_components/luxtronik/translations/texts.pl.json b/custom_components/luxtronik/translations/texts.pl.json deleted file mode 100644 index 98b06ac..0000000 --- a/custom_components/luxtronik/translations/texts.pl.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "evu_until": "Czas blokady d\u0142u\u017Cszy o {evu_time} minut.", - "evu_in": "Czas blokady za {evu_time} minut." -} From e4309b82b9d473e2116bccde2003e0cc39f6e922 Mon Sep 17 00:00:00 2001 From: BenPru <32298537+BenPru@users.noreply.github.com> Date: Fri, 20 Oct 2023 19:07:51 +0200 Subject: [PATCH 04/16] Create FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..6e82019 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: BenPru From dcfd32224fa3f026cc06a8ec31b6fac11a3089b8 Mon Sep 17 00:00:00 2001 From: BenPru Date: Sat, 21 Oct 2023 20:36:46 +0200 Subject: [PATCH 05/16] * Code cleanup --- custom_components/luxtronik/const.py | 50 ++++++++++++++++++----- custom_components/luxtronik/manifest.json | 2 +- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/custom_components/luxtronik/const.py b/custom_components/luxtronik/const.py index 1317466..b5bf1a2 100644 --- a/custom_components/luxtronik/const.py +++ b/custom_components/luxtronik/const.py @@ -172,13 +172,6 @@ class LuxMkTypes(Enum): heating_cooling: Final = 4 -LUX_PARAMETER_MK_SENSORS: Final = [ - "parameters.ID_Einst_MK1Typ_akt", - "parameters.ID_Einst_MK2Typ_akt", - "parameters.ID_Einst_MK3Typ_akt", -] - - class LuxRoomThermostatType(Enum): """LuxMkTypes etc.""" @@ -241,12 +234,13 @@ class LuxParameter(StrEnum): P0016_HEATING_CIRCUIT2_CURVE_NIGHT_TEMPERATURE: Final = ( "parameters.ID_Einst_HzMK1ABS_akt" # 0 ) + # P0036_SECOND_HEAT_GENERATOR: Final = "parameters.ID_Einst_ZWE1Art_akt" # = 1 --> Heating and domestic water - Is second heat generator activated 1=electrical heater P0042_MIXING_CIRCUIT1_TYPE: Final = "parameters.ID_Einst_MK1Typ_akt" P0047_DHW_THERMAL_DESINFECTION_TARGET: Final = "parameters.ID_Einst_LGST_akt" P0049_PUMP_OPTIMIZATION: Final = "parameters.ID_Einst_Popt_akt" - P0033_ROOM_THERMOSTAT_TYPE: Final = "parameters.ID_Einst_RFVEinb_akt" + # P0033_ROOM_THERMOSTAT_TYPE: Final = "parameters.ID_Einst_RFVEinb_akt" # != 0 --> Has_Room_Temp P0074_DHW_HYSTERESIS: Final = "parameters.ID_Einst_BWS_Hyst_akt" - P0085_DHW_CHARGING_PUMP: Final = "parameters.ID_Einst_BWZIP_akt" + P0085_DHW_CHARGING_PUMP: Final = "parameters.ID_Einst_BWZIP_akt" # has_domestic_water_circulation_pump int() != 1 P0088_HEATING_HYSTERESIS: Final = "parameters.ID_Einst_HRHyst_akt" P0089_HEATING_MAX_FLOW_OUT_INCREASE_TEMPERATURE: Final = ( "parameters.ID_Einst_TRErhmax_akt" @@ -295,13 +289,30 @@ class LuxParameter(StrEnum): "parameters.ID_Einst_Effizienzpumpe_Minimal_akt" ) P0869_EFFICIENCY_PUMP: Final = "parameters.ID_Einst_Effizienzpumpe_akt" - P0870_AMOUNT_COUNTER_ACTIVE: Final = "parameters.ID_Einst_Waermemenge_akt" + # P0870_AMOUNT_COUNTER_ACTIVE: Final = "parameters.ID_Einst_Waermemenge_akt" P0874_SERIAL_NUMBER: Final = "parameters.ID_WP_SerienNummer_DATUM" P0875_SERIAL_NUMBER_MODEL: Final = "parameters.ID_WP_SerienNummer_HEX" + + # "852 ID_Waermemenge_Seit ": "2566896", + # "853 ID_Waermemenge_WQ ": "0", + # "854 ID_Waermemenge_Hz ": "3317260", + # "855 ID_Waermemenge_WQ_ges ": "0", + # "878 ID_Waermemenge_BW ": "448200", + # "879 ID_Waermemenge_SW ": "0", + # "880 ID_Waermemenge_Datum ": "1483648906", <-- Unix timestamp! 5.1.2017 + + # "1059 ID_Waermemenge_ZWE ": "0", + # "1060 ID_Waermemenge_Reset ": "535051", + # "1061 ID_Waermemenge_Reset_2 ": "0", + + # Calc + # "154 ID_WEB_WMZ_Seit ": "25668.9", + P0882_SOLAR_OPERATION_HOURS: Final = "parameters.ID_BSTD_Solar" P0883_SOLAR_PUMP_MAX_TEMPERATURE_COLLECTOR: Final = ( "parameters.ID_Einst_TDC_Koll_Max_akt" ) + # P0894_VENTILATION_MODE: Final = "parameters.ID_Einst_BA_Lueftung_akt" # "Automatic", "Party", "Holidays", "Off" P0966_COOLING_TARGET_TEMPERATURE_MK3: Final = "parameters.ID_Sollwert_KuCft3_akt" P0979_HEATING_MIN_FLOW_OUT_TEMPERATURE: Final = ( "parameters.ID_Einst_Minimale_Ruecklaufsolltemperatur" @@ -321,10 +332,19 @@ class LuxParameter(StrEnum): ) P1136_HEAT_ENERGY_INPUT: Final = "parameters.Unknown_Parameter_1136" P1137_DHW_ENERGY_INPUT: Final = "parameters.Unknown_Parameter_1137" + # ? P1138_SWIMMING_POOL_ENERGY_INPUT: Final = "parameters.Unknown_Parameter_1138" --> + # ? P1139_COOLING_ENERGY_INPUT: Final = "parameters.Unknown_Parameter_1139" + # ? P1140_SECOND_HEAT_SOURCE_DHW_ENERGY_INPUT: Final = "parameters.Unknown_Parameter_1140" # endregion Lux parameters +LUX_PARAMETER_MK_SENSORS: Final = [ + LuxParameter.P0042_MIXING_CIRCUIT1_TYPE, + LuxParameter.P0130_MIXING_CIRCUIT2_TYPE, + LuxParameter.P0780_MIXING_CIRCUIT3_TYPE, +] + # region Lux calculations class LuxCalculation(StrEnum): @@ -346,10 +366,13 @@ class LuxCalculation(StrEnum): C0027_SOLAR_BUFFER_TEMPERATURE: Final = "calculations.ID_WEB_Temperatur_TSS" C0029_DEFROST_END_FLOW_OKAY: Final = "calculations.ID_WEB_ASDin" C0031_EVU_UNLOCKED: Final = "calculations.ID_WEB_EVUin" + # C0032_HIGH_PRESSURE_OKAY: Final = "calculations.ID_WEB_HDin" # True/False -> Hochdruck OK C0034_MOTOR_PROTECTION: Final = "calculations.ID_WEB_MOTin" C0037_DEFROST_VALVE: Final = "calculations.ID_WEB_AVout" C0038_DHW_RECIRCULATION_PUMP: Final = "calculations.ID_WEB_BUPout" C0039_CIRCULATION_PUMP_HEATING: Final = "calculations.ID_WEB_HUPout" + # C0040_MIXER1_OPENED: Final = "calculations.ID_WEB_MA1out" # True/False -> Mischer 1 auf + # C0041_MIXER1_CLOSED: Final = "calculations.ID_WEB_MZ1out" # True/False -> Mischer 1 zu C0043_PUMP_FLOW: Final = "calculations.ID_WEB_VBOout" C0044_COMPRESSOR: Final = "calculations.ID_WEB_VD1out" C0045_COMPRESSOR2: Final = "calculations.ID_WEB_VD2out" @@ -357,7 +380,10 @@ class LuxCalculation(StrEnum): C0047_ADDITIONAL_CIRCULATION_PUMP: Final = "calculations.ID_WEB_ZUPout" C0048_ADDITIONAL_HEAT_GENERATOR: Final = "calculations.ID_WEB_ZW1out" C0049_DISTURBANCE_OUTPUT: Final = "calculations.ID_WEB_ZW2SSTout" + # C0051: Final = "calculations.ID_WEB_FP2out" # True/False -> FBH Umwälzpumpe 2 C0052_SOLAR_PUMP: Final = "calculations.ID_WEB_SLPout" + # C0054_MIXER2_CLOSED: Final = "calculations.ID_WEB_MZ2out" # True/False -> Mischer 2 zu + # C0055_MIXER2_OPENED: Final = "calculations.ID_WEB_MA2out" # True/False -> Mischer 2 auf C0056_COMPRESSOR1_OPERATION_HOURS: Final = "calculations.ID_WEB_Zaehler_BetrZeitVD1" C0057_COMPRESSOR1_IMPULSES: Final = "calculations.ID_WEB_Zaehler_BetrZeitImpVD1" C0058_COMPRESSOR2_OPERATION_HOURS: Final = "calculations.ID_WEB_Zaehler_BetrZeitVD2" @@ -385,6 +411,8 @@ class LuxCalculation(StrEnum): C0081_FIRMWARE_VERSION: Final = "calculations.ID_WEB_SoftStand" C0095_ERROR_TIME: Final = "calculations.ID_WEB_ERROR_Time0" C0100_ERROR_REASON: Final = "calculations.ID_WEB_ERROR_Nr0" + # TODO: ! + # C0105_ERROR_COUNTER: Final = "calculations.ID_WEB_AnzahlFehlerInSpeicher" C0117_STATUS_LINE_1: Final = "calculations.ID_WEB_HauptMenuStatus_Zeile1" C0118_STATUS_LINE_2: Final = "calculations.ID_WEB_HauptMenuStatus_Zeile2" C0119_STATUS_LINE_3: Final = "calculations.ID_WEB_HauptMenuStatus_Zeile3" @@ -621,6 +649,7 @@ class SensorKey(StrEnum): COOLING_TARGET_TEMPERATURE_MK2 = "cooling_target_temperature_mk2" COOLING_TARGET_TEMPERATURE_MK3 = "cooling_target_temperature_mk3" + # endregion Keys @@ -668,4 +697,5 @@ class SensorAttrKey(StrEnum): TIMER_DEFROST = "Abtauen in ID_WEB_Time_AbtIn" TIMER_HOT_GAS = "ID_WEB_Time_Heissgas" + # endregion Attr Keys diff --git a/custom_components/luxtronik/manifest.json b/custom_components/luxtronik/manifest.json index a245d83..d1120e0 100755 --- a/custom_components/luxtronik/manifest.json +++ b/custom_components/luxtronik/manifest.json @@ -9,7 +9,7 @@ "after_dependencies": [], "codeowners": ["@BenPru"], "iot_class": "local_polling", - "version": "2023.10.20", + "version": "2023.10.21", "homeassistant": "2023.1.0", "dhcp": [ { "macaddress": "000E8C*" }, From d60df8d234f89279ff6344fd4969eb31811636a2 Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:31:26 +0200 Subject: [PATCH 06/16] Create validate.yaml --- .github/workflows/validate.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/validate.yaml diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml new file mode 100644 index 0000000..c422ec3 --- /dev/null +++ b/.github/workflows/validate.yaml @@ -0,0 +1,18 @@ +name: Validate + +on: + push: + pull_request: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + validate-hacs: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v3" + - name: HACS validation + uses: "hacs/action@main" + with: + category: "integration" From a73a95420d67014c91b55e0325ca404507e80dae Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:35:32 +0200 Subject: [PATCH 07/16] Update validate.yaml --- .github/workflows/validate.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index c422ec3..1941e3f 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -16,3 +16,18 @@ jobs: uses: "hacs/action@main" with: category: "integration" + +name: Validate with hassfest + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +jobs: + validate: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v4" + - uses: "home-assistant/actions/hassfest@master" From 294b733c96a8e01d2779fef65cd544f8fb3b66cc Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:37:41 +0200 Subject: [PATCH 08/16] Update validate.yaml --- .github/workflows/validate.yaml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index 1941e3f..c422ec3 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -16,18 +16,3 @@ jobs: uses: "hacs/action@main" with: category: "integration" - -name: Validate with hassfest - -on: - push: - pull_request: - schedule: - - cron: '0 0 * * *' - -jobs: - validate: - runs-on: "ubuntu-latest" - steps: - - uses: "actions/checkout@v4" - - uses: "home-assistant/actions/hassfest@master" From 9d97a80b4d5f22f379dbd459a0614f6ada0b49ca Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:38:42 +0200 Subject: [PATCH 09/16] Create hassfest.yml --- .github/workflows/hassfest.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/hassfest.yml diff --git a/.github/workflows/hassfest.yml b/.github/workflows/hassfest.yml new file mode 100644 index 0000000..d203eda --- /dev/null +++ b/.github/workflows/hassfest.yml @@ -0,0 +1,14 @@ +name: Validate with hassfest + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +jobs: + validate: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v4" + - uses: "home-assistant/actions/hassfest@master" From 10247200e2f44d7c67e021858e60c99a98506170 Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:43:57 +0200 Subject: [PATCH 10/16] Update validate.yaml --- .github/workflows/validate.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index c422ec3..9ab6117 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -1,4 +1,4 @@ -name: Validate +name: HACS Action on: push: From 44a99e962f18e78c673b976cc36d2064c788faa8 Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:55:12 +0200 Subject: [PATCH 11/16] Delete .github/workflows/validate.yaml --- .github/workflows/validate.yaml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .github/workflows/validate.yaml diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml deleted file mode 100644 index 9ab6117..0000000 --- a/.github/workflows/validate.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: HACS Action - -on: - push: - pull_request: - schedule: - - cron: "0 0 * * *" - workflow_dispatch: - -jobs: - validate-hacs: - runs-on: "ubuntu-latest" - steps: - - uses: "actions/checkout@v3" - - name: HACS validation - uses: "hacs/action@main" - with: - category: "integration" From 8e9bc379193c637b6a9508d2291d820b697614fd Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:55:43 +0200 Subject: [PATCH 12/16] Create validate-hacs.yaml --- .github/workflows/validate-hacs.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/validate-hacs.yaml diff --git a/.github/workflows/validate-hacs.yaml b/.github/workflows/validate-hacs.yaml new file mode 100644 index 0000000..9ab6117 --- /dev/null +++ b/.github/workflows/validate-hacs.yaml @@ -0,0 +1,18 @@ +name: HACS Action + +on: + push: + pull_request: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + validate-hacs: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v3" + - name: HACS validation + uses: "hacs/action@main" + with: + category: "integration" From 8299f663c5be60c2232a9148ba3115c6dec03f0e Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:56:48 +0200 Subject: [PATCH 13/16] Delete .github/workflows/hassfest.yml --- .github/workflows/hassfest.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .github/workflows/hassfest.yml diff --git a/.github/workflows/hassfest.yml b/.github/workflows/hassfest.yml deleted file mode 100644 index d203eda..0000000 --- a/.github/workflows/hassfest.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Validate with hassfest - -on: - push: - pull_request: - schedule: - - cron: '0 0 * * *' - -jobs: - validate: - runs-on: "ubuntu-latest" - steps: - - uses: "actions/checkout@v4" - - uses: "home-assistant/actions/hassfest@master" From 84053bb38238418e0906b37735af8c6a04f6fecc Mon Sep 17 00:00:00 2001 From: rhammen <75572839+rhammen@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:57:12 +0200 Subject: [PATCH 14/16] Create hassfest.yaml --- .github/workflows/hassfest.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/hassfest.yaml diff --git a/.github/workflows/hassfest.yaml b/.github/workflows/hassfest.yaml new file mode 100644 index 0000000..d203eda --- /dev/null +++ b/.github/workflows/hassfest.yaml @@ -0,0 +1,14 @@ +name: Validate with hassfest + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +jobs: + validate: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v4" + - uses: "home-assistant/actions/hassfest@master" From ac57e65f579844c7dc78a5a43fcf2349e4c9b19f Mon Sep 17 00:00:00 2001 From: BenPru Date: Sun, 22 Oct 2023 21:43:18 +0200 Subject: [PATCH 15/16] * Add cause and remedy texts de --- .../luxtronik/translations/de.json | 182 +++++++++++++++++- .../luxtronik/translations/en.json | 8 +- 2 files changed, 179 insertions(+), 11 deletions(-) diff --git a/custom_components/luxtronik/translations/de.json b/custom_components/luxtronik/translations/de.json index 3329ad7..f6fb295 100644 --- a/custom_components/luxtronik/translations/de.json +++ b/custom_components/luxtronik/translations/de.json @@ -192,13 +192,13 @@ "cooling_stop_delay_hours": { "name": "Ende Verz\u00f6gerung" }, - "cooling_target_temperature_mk1": { + "cooling_target_temperature_mk1": { "name": "K\u00fchlung Ziel" }, - "cooling_target_temperature_mk2": { + "cooling_target_temperature_mk2": { "name": "K\u00fchlung Ziel" }, - "cooling_target_temperature_mk3": { + "cooling_target_temperature_mk3": { "name": "K\u00fchlung Ziel" } }, @@ -301,6 +301,168 @@ "792": "LIN-Verbindung unterbrochen", "793": "Schwerw. Inverter Fehler", "-1": "Unbekannter Fehler" + }, + "state_attributes": { + "timestamp": { + "name": "Zeitpunkt" + }, + "cause": { + "name": "Ursache", + "state": { + "701": "Niederdruckpressostat im K\u00e4ltekreis hat mehrmals angesprochen \u0028LW\u0029 oder l\u00e4nger als 20 Sekunden \u0028SW\u0029.", + "702": "Nur bei L\u002fW-Ger\u00e4ten m\u00f6glich\u003a Niederdruck im K\u00e4ltekreis hat angesprochen. Nach einiger Zeit automatischer WP-Neuanlauf.", + "703": "Nur bei L\u002fW-Ger\u00e4ten m\u00f6glich\u003a L\u00e4uft die W\u00e4rmepumpe und wird die Temperatur im Vorlauf \u003c 5 \u00b0C, wird auf Frostschutz erkannt.", + "704": "Maximale Temperatur im Heissgas-K\u00e4ltekreis \u00fcberschritten. Automatischer WP-Neuanlauf nach hh\u003amm.", + "705": "Nur bei L\u002fW-Ger\u00e4ten m\u00f6glich\u003a Motorschutz des Ventilators hat angesprochen.", + "706": "Nur bei S\u002fW- und W\u002fW-Ger\u00e4ten m\u00f6glich\u003a Motorschutz der Sole- oder Brunnenwasserumw\u00e4lzpumpe oder des Verdichters hat angesprochen.", + "707": "Bruch oder Kurzschluss der Kodierungsbr\u00fccke in WP nach der Ersteinschaltung.", + "708": "Bruch oder Kurzschluss des R\u00fccklauff\u00fchlers.", + "709": "Bruch oder Kurzschluss des Vorlauff\u00fchlers.\nKeine St\u00f6rabschaltung bei S\u002fW- und W\u002fW-Ger\u00e4ten.", + "710": "Bruch oder Kurzschluss des Heissgasf\u00fchlers im K\u00e4ltekreis.", + "711": "Bruch oder Kurzschluss des Aussentemperaturf\u00fchlers.\nKeine St\u00f6rabschaltung. Festwert auf -5 \u00b0C.", + "712": "Bruch oder Kurzschluss des Warmwasserf\u00fchlers.\nKeine St\u00f6rabschaltung.", + "713": "Bruch oder Kurzschluss des W\u00e4rmequellenf\u00fchlers \u0028Eintritt\u0029.", + "714": "Thermische Einsatzgrenze der WP \u00fcberschritten.\nWarmwasserbereitung gesperrt f\u00fcr hh\u003amm.", + "715": "Hochdruckpressostat im K\u00e4ltekreis hat angesprochen. Nach einiger Zeit automatischer WP-Neuanlauf.", + "716": "Hochdruckpressostat im K\u00e4ltekreis hat mehrfach angesprochen.", + "717": "Durchflussschalter bei W\u002fW-Ger\u00e4ten hat w\u00e4hrend der Vorsp\u00fclzeit oder des Betriebs angesprochen.", + "718": "Nur bei L\u002fW-Ger\u00e4ten m\u00f6glich\u003a Aussentemperatur hat zul\u00e4ssigen Maximalwert \u00fcberschritten.", + "719": "Nur bei L\u002fW-Ger\u00e4ten m\u00f6glich\u003a Aussentemperatur hat zul\u00e4ssigen Minimalwert unterschritten.", + "720": "Nur bei S\u002fW- und W\u002fW-Ger\u00e4ten m\u00f6glich\u003a Temperatur am Verdampferaustritt ist auf WQ-Seite mehrfach unter den Sicherheitswert gefallen. Automatischer WP-Neuanlauf nach hh\u003amm.", + "721": "Niederdruckpressostat im K\u00e4ltekreis hat angesprochen. Nach einiger Zeit automatischer WP-Neuanlauf \u0028SW und WW\u0029.", + "722": "Temperaturspreizung im Heizbetrieb ist negativ \u0028\u003dfehlerhaft\u0029.", + "723": "Temperaturspreizung im Warmwasserbetrieb ist negativ \u0028\u003dfehlerhaft\u0029.", + "724": "Temperaturspreizung im Heizkreis ist w\u00e4hrend des Abtauens \u003e 15 K \u0028\u003dFrostgefahr\u0029.", + "725": "Warmwasserbetrieb gest\u00f6rt, gew\u00fcnschte Speichertemperatur ist weit unterschritten.", + "726": "Bruch oder Kurzschluss des Mischkreisf\u00fchlers.", + "727": "Soledruckpressostat hat w\u00e4hrend Vorsp\u00fclzeit oder w\u00e4hrend des Betriebs angesprochen.", + "728": "Bruch oder Kurzschluss des W\u00e4rmequellenf\u00fchlers am WQ-Austritt.", + "729": "Verdichter nach dem Einschalten ohne Leistung.", + "730": "Das Ausheizprogramm konnte eine VL-Temperaturstufe nicht im vorgegebenen Zeitintervall erreichen. Ausheizprogramm l\u00e4uft weiter.", + "732": "Die Heizwassertemperatur von 16 \u00b0C wurde mehrfach unterschritten.", + "733": "St\u00f6rmeldeeingang der Fremdstromanode hat angesprochen.", + "734": "Fehler 733 liegt seit mehr als zwei Wochen an und Warmwasserbereitung ist gesperrt.", + "735": "Nur bei eingebauter Comfort-\u002fErweiterungs-Platine m\u00f6glich\u003a Bruch oder Kurzschluss des F\u00fchlers Externe Energiequelle.", + "736": "Nur bei eingebauter Comfort-\u002fErweiterungs-Platine m\u00f6glich\u003a Bruch oder Kurzschluss des F\u00fchlers Solarkollektor.", + "737": "Nur bei eingebauter Comfort-\u002fErweiterungs-Platine m\u00f6glich\u003a Bruch oder Kurzschluss des F\u00fchlers Solarspeicher.", + "738": "Nur bei eingebauter Comfort-\u002fErweiterungs-Platine m\u00f6glich\u003a Bruch oder Kurzschluss des F\u00fchlers Mischkreis2.", + "750": "Bruch oder Kurzschluss des externen R\u00fccklauff\u00fchlers.", + "751": "Phasenfolgerelais hat angesprochen.", + "752": "Phasenfolgerelais oder Durchflussschalter hat angesprochen.", + "755": "Ein Slave hat f\u00fcr mehr als 5 Minuten nicht geantwortet.", + "756": "Ein Master hat f\u00fcr mehr als 5 Minuten nicht geantwortet.", + "757": "Niederdruckpressostat bei WW-Ger\u00e4t hat mehrmals oder l\u00e4nger als 20 Sekunden angesprochen.", + "758": "Die Abtauung wurde 5mal in Folge \u00fcber zu niedrige Vorlauftemperatur beendet.", + "759": "Thermische Desinfektion konnte 3mal in Folge nicht korrekt durchgef\u00fchrt werden.", + "760": "Abtauung wurde 5mal in Folge \u00fcber Maximalzeit beendet \u0028starker Wind trifft auf Verdampfer\u0029.", + "761": "LIN-Timeout", + "762": "F\u00fchlerfehler T\u00fc \u0028Ansaug Verdichter\u0029.", + "763": "F\u00fchlerfehler T\u00fc1 \u0028Ansaug Verdampfer\u0029.", + "764": "F\u00fchlerfehler Verdichterheizung.", + "765": "\u00dcberhitzung l\u00e4nger als 5 Minuten unter 2K.", + "766": "Betrieb 5 Minuten außerhalb des Einsatzbereichs des Verdichters.", + "767": "STB des Heizstabs am SEC wurde aktiviert.", + "770": "\u00dcberhitzung liegt \u00fcber einen l\u00e4ngeren Zeitraum unter dem Grenzwert.", + "771": "\u00dcberhitzung liegt \u00fcber einen l\u00e4ngeren Zeitraum \u00fcber dem Grenzwert.", + "776": "Verdichter arbeitet \u00fcber l\u00e4ngeren Zeitraum außerhalb seiner Einsatzgrenzen.", + "777": "Expansionsventil defekt.", + "778": "Niederdruckf\u00fchler defekt.", + "779": "Hochdruckf\u00fchler defekt.", + "780": "EVI-F\u00fchler defekt.", + "781": "Temperaturf\u00fchler Fl\u00fcssig vor Ex-Ventil defekt.", + "782": "Temperaturf\u00fchler EVI Sauggas defekt.", + "783": "Kommunikation zwischen SEC u. Inverter gest\u00f6rt", + "784": "Inverter gesperrt", + "785": "Fehler im SEC Board festgestellt.", + "786": "St\u00f6rung der Kommunikation zwischen SEC und HZIO von SEC festgestellt.", + "787": "Verdichter meldet Fehler.", + "788": "Fehler im Inverter", + "789": "Bedienteil konnte keine Kodierung feststellen. Entweder ist die LIN-Verbindung unterbrochen oder der Kodierungswiderstand wird nicht erkannt.", + "790": "Fehler in der Stromversorgung des Inverters \u002f Verdichters.", + "791": "SEC-Board seit einiger Zeit nicht mehr erreichbar. 791 wird ausgel\u00f6st, wenn zwar eine HZIO-Platine gefunden worden ist \u0028ohne separate Kodierung\u0029, allerdings kein SEC-Board daran erkannt werden kann.", + "792": "Es konnte keine Grundplatine und auch sonst keine Konfiguration gefunden werden.", + "793": "Temperaturfehler im Inverter", + "-1": "Unbekannter Fehler" + } + }, + "remedy": { + "name": "Abhilfe", + "state": { + "701": "WP auf Leckage, Schaltpunkt Pressostat, Abtauung und TA-min \u00fcberpr\u00fcfen.", + "702": "WP auf Leckage, Schaltpunkt Pressostat, Abtauung und TA-min \u00fcberpr\u00fcfen.", + "703": "WP-Leistung, Abtauventil und Heizanlage \u00fcberpr\u00fcfen.", + "704": "K\u00e4ltemittelmenge, Verdampfung, \u00dcberhitzung Vorlauf, R\u00fccklauf und WQ-min \u00fcberpr\u00fcfen.", + "705": "Ventilator \u00fcberpr\u00fcfen.", + "706": "Eingestellte Werte, Verdichter, BOSUP \u00fcberpr\u00fcfen.", + "707": "Kodierungswiderstand in WP, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "708": "R\u00fccklauff\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "709": "Vorlauff\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "710": "Heissgasf\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "711": "Aussentemperaturf\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "712": "Warmwasserf\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "713": "W\u00e4rmequellenf\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen", + "714": "Durchfluss Warmwasser, W\u00e4rmetauscher, Warmwasser-Temperatur und Umw\u00e4lzpumpe Warmwasser \u00fcberpr\u00fcfen.", + "715": "Durchfluss HW, \u00fcberstr\u00f6mer, Temperatur und Kondensation \u00fcberpr\u00fcfen.", + "716": "Durchfluss HW, \u00fcberstr\u00f6mer, Temperatur und Kondensation \u00fcberpr\u00fcfen.", + "717": "Durchfluss, Schaltpunkt DFS, Filter, Luftfreiheit \u00fcberpr\u00fcfen", + "718": "Aussentemperatur und eingestellten Wert \u00fcberpr\u00fcfen.", + "719": "Aussentemperatur und eingestellten Wert \u00fcberpr\u00fcfen.", + "720": "Durchfluss, Filter, Luftfreiheit, Temperatur \u00fcberpr\u00fcfen.", + "721": "Schaltpunkt Pressostat, Durchfluss WQ-Seite \u00fcberpr\u00fcfen.", + "722": "Funktion und Platzierung der Vor- und R\u00fccklauff\u00fchler \u00fcberpr\u00fcfen.", + "723": "Funktion und Platzierung der Vor- und R\u00fccklauff\u00fchler \u00fcberpr\u00fcfen.", + "724": "Funktion und Platzierung der Vor- und R\u00fccklauff\u00fchler, F\u00f6rderleistung HUP, \u00fcberstr\u00f6mer und Heizkreise \u00fcberpr\u00fcfen.", + "725": "Umw\u00e4lzpumpe WW, Speicherf\u00fcllung, Absperrschieber und 3-Wege-Ventil \u00fcberpr\u00fcfen. Heizwasser und WW entl\u00fcften.", + "726": "Mischkreisf\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "727": "Soledruck und Soledruckpressostat \u00fcberpr\u00fcfen.", + "728": "W\u00e4rmequellenf\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "729": "Drehfeld und Verdichter \u00fcberpr\u00fcfen.", + "730": "Leistungsbedarf w\u00e4hrend des Ausheizens \u00fcberpr\u00fcfen.", + "732": "Mischer und Heizungsumw\u00e4lzpumpe \u00fcberpr\u00fcfen.", + "733": "Verbindungsleitung Anode und Potenziostat \u00fcberpr\u00fcfen. WW-Speicher f\u00fcllen.", + "734": "Fehler vor\u00fcbergehend quittieren, um Warmwasserbereitung wieder freizugeben. Fehler 733 beheben.", + "735": "F\u00fchler Externe Energiequelle, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "736": "F\u00fchler Solarkollektor, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "737": "F\u00fchler Solarspeicher, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "738": "F\u00fchler Mischkreis2, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "750": "Externer R\u00fccklauff\u00fchler, Stecker und Verbindungsleitung \u00fcberpr\u00fcfen.", + "751": "\u00fcberpr\u00fcfung Drehfeld und Phasenfolgerelais.", + "752": "siehe Fehler Nr. 751 und Nr. 717", + "755": "Netzwerkverbindung, Switch und IPAdressen pr\u00fcfen. Gegebenenfalls WP-Suche erneut ausf\u00fchren.", + "756": "Netzwerkverbindung, Switch und IPAdressen pr\u00fcfen. Gegebenenfalls WP-Suche erneut ausf\u00fchren.", + "757": "Bei 3maligem Auftreten dieser St\u00f6rung kann die Anlage nur vom authorisierten Servicepersonal freigeschaltet werden!", + "758": "Durchfluss und Vorlaufsensor pr\u00fcfen", + "759": "Einstellung Zweiter W\u00e4rmeerzeuger und Sicherheitstemperaturbegrenzer pr\u00fcfen", + "760": "Ventilator und Verdampfer vor starkem Wind sch\u00fctzen", + "761": "Kabel\u002fKontakt pr\u00fcfen", + "762": "F\u00fchler pr\u00fcfen, evtl. tauschen", + "763": "F\u00fchler pr\u00fcfen, evtl. tauschen", + "764": "F\u00fchler pr\u00fcfen, evtl. tauschen", + "765": "Bei Ersteinschaltung. Drehfeld pr\u00fcfen, sonst Kundendienst rufen", + "766": "Drehfeld pr\u00fcfen", + "767": "Heizstab \u00fcberpr\u00fcfen und Sicherung wieder reindr\u00fccken", + "770": "Temperaturf\u00fchler, Drucksensor und Expansionsventil pr\u00fcfen", + "771": "Temperaturf\u00fchler, Drucksensor, F\u00fcllmenge und Expansionsventil pr\u00fcfen", + "776": "Thermodynamik pr\u00fcfen", + "777": "Expansionsventil, Verbindungskabel und ggf. SEC-Board pr\u00fcfen", + "778": "Sensor, Stecker und Verbindungsleitung pr\u00fcfen", + "779": "Sensor, Stecker und Verbindungsleitung pr\u00fcfen", + "780": "Sensor, Stecker und Verbindungsleitung pr\u00fcfen", + "781": "Sensor, Stecker und Verbindungsleitung pr\u00fcfen", + "782": "Sensor, Stecker und Verbindungsleitung pr\u00fcfen", + "783": "Verbindungskabel, Entst\u00f6rkondensatoren und Verkabelung pr\u00fcfen", + "784": "Komplette Anlage 2 Minuten lang spannungslos schalten. Bei wiederholtem Auftreten Inverter und Verdichter pr\u00fcfen", + "785": "SEC Board austauschen", + "786": "Kabelverbindung HZ\u002fIO SEC-Board pr\u00fcfen", + "787": "St\u00f6rung quittieren. Falls Fehler mehrfach auftritt, autorisiertes Servicepersonal \u0028\u003d Kundendienst\u0029 rufen", + "788": "Inverter pr\u00fcfen", + "789": "Verbindungskabel LIN \u002f Kodierwiderstand pr\u00fcfen", + "790": "Verkabelung, Inverter und Verdichter pr\u00fcfen", + "791": "Sofern es sich um die SECKonfiguration handelt, das ModBus-Kabel zwischen HZIO und SEC Board pr\u00fcfen. Ebenso das SEC-Board pr\u00fcfen, ob alles blinkt, wie es soll. Falls es KEINE Konfiguration mit SEC-Board ist \u0028z.B., weil es sich um ein P184-Ger\u00e4t handelt\u0029, dann den Kodierungswiderstand der HZIO pr\u00fcfen.", + "792": "Kodierungsstecker auf LINPlatine\u0028n\u0029 pr\u00fcfen", + "793": "Fehler behebt sich selbst" + } + } } }, "switchoff_reason": { @@ -467,16 +629,16 @@ "name": "R\u00fccklauf Soll Temperatur" }, "operation_hours_heating": { - "name":"Betriebsstunden" + "name": "Betriebsstunden" }, "heat_amount_heating": { - "name":"Z\u00e4hler W\u00e4rmemenge Heizung" + "name": "Z\u00e4hler W\u00e4rmemenge Heizung" }, "heat_amount_flow_rate": { - "name":"Z\u00e4hler W\u00e4rmemenge Durchfluss" + "name": "Z\u00e4hler W\u00e4rmemenge Durchfluss" }, "heat_source_flow_rate": { - "name":"Z\u00e4hler W\u00e4rmequelle Durchfluss" + "name": "Z\u00e4hler W\u00e4rmequelle Durchfluss" }, "heat_energy_input": { "name": "Eingesetzte Energie Heizung" @@ -558,8 +720,8 @@ "timeout": "Wenn das Netzwerk oder die W\u00e4rmepumpe tr\u00e4ge sind, kann man hier fein einstellen.", "max_data_length": "Wenn das Netzwerk oder die W\u00e4rmepumpe tr\u00e4ge sind, kann man hier fein einstellen." } - }, - "options": { + }, + "options": { "description": "Einstellungen zur Luxtronik W\u00e4rmepumpe {name}.\nDiese Einstellungen k\u00F6nnen auch sp\u00e4ter unter Integrationen ge\u00e4ndert werden.", "data": { "ha_sensor_indoor_temperature": "Sensor ID f\u00fcr die Innentemperatur", @@ -571,7 +733,7 @@ "control_mode_home_assistant": "Wenn das Home Assistant Thermostat im Status Leerlauf ist, wird Luxtronik der Status Aus \u00fcbermittelt und Luxtronik kann dieses Element nicht starten.", "ha_sensor_prefix": "Wichtig wenn mehreren W\u00e4rmepumpen verwendet werden.\nBei einer einzelnen kann einfach 'luxtronik' verwendet werden." } - } + } } }, "options": { diff --git a/custom_components/luxtronik/translations/en.json b/custom_components/luxtronik/translations/en.json index 4053a8a..be37057 100644 --- a/custom_components/luxtronik/translations/en.json +++ b/custom_components/luxtronik/translations/en.json @@ -301,8 +301,14 @@ "792": "LIN-connection lost", "793": "Major VSS fault", "-1": "Unknown error" + }, + "cause": { + "name": "Cause" + }, + "remedy": { + "name": "Remedy" } - }, + }, "switchoff_reason": { "name": "Switchoff reason", "state": { From 598383416cdf789e10c64fc685c55909d2996d38 Mon Sep 17 00:00:00 2001 From: BenPru Date: Sun, 22 Oct 2023 21:43:41 +0200 Subject: [PATCH 16/16] * Version --- custom_components/luxtronik/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/luxtronik/manifest.json b/custom_components/luxtronik/manifest.json index d1120e0..ab19865 100755 --- a/custom_components/luxtronik/manifest.json +++ b/custom_components/luxtronik/manifest.json @@ -9,7 +9,7 @@ "after_dependencies": [], "codeowners": ["@BenPru"], "iot_class": "local_polling", - "version": "2023.10.21", + "version": "2023.10.22", "homeassistant": "2023.1.0", "dhcp": [ { "macaddress": "000E8C*" },