Skip to content

Commit

Permalink
Merge pull request #19 from rhammen/main
Browse files Browse the repository at this point in the history
Several enhancements
  • Loading branch information
BenPru authored Nov 14, 2022
2 parents 99bf92d + 0762c7e commit 5940811
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 48 deletions.
54 changes: 34 additions & 20 deletions custom_components/luxtronik/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,28 @@
CONF_HA_SENSOR_INDOOR_TEMPERATURE,
CONF_LANGUAGE_SENSOR_NAMES, CONF_PARAMETERS,
CONF_VISIBILITIES, DEFAULT_TOLERANCE, DOMAIN, LOGGER,

LUX_SENSOR_DOMESTIC_WATER_CURRENT_TEMPERATURE,
LUX_SENSOR_DOMESTIC_WATER_TARGET_TEMPERATURE,
LUX_SENSOR_MODE_DOMESTIC_WATER, LUX_SENSOR_MODE_HEATING,
LUX_SENSOR_HEATING_TEMPERATURE_CORRECTION,
LUX_SENSOR_COOLING_TARGET,
LUX_SENSOR_COOLING_THRESHOLD,
LUX_SENSOR_OUTDOOR_TEMPERATURE,

LUX_SENSOR_MODE_DOMESTIC_WATER,
LUX_SENSOR_MODE_HEATING,
LUX_SENSOR_MODE_COOLING,

LUX_SENSOR_STATUS, LUX_SENSOR_STATUS1, LUX_SENSOR_STATUS3,
LUX_STATUS1_WORKAROUND, LUX_STATUS3_WORKAROUND,
LUX_STATUS_COOLING, LUX_STATUS_DEFROST,
LUX_STATUS_DOMESTIC_WATER, LUX_STATUS_EVU,
LUX_STATUS_HEATING, LUX_STATUS_HEATING_EXTERNAL_SOURCE,
LUX_STATUS_DOMESTIC_WATER,
LUX_STATUS_EVU,
LUX_STATUS_HEATING,
LUX_STATUS_HEATING_EXTERNAL_SOURCE,
LUX_STATUS_NO_REQUEST, LUX_STATUS_SWIMMING_POOL_SOLAR,
PRESET_SECOND_HEATSOURCE, LuxMode)
PRESET_SECOND_HEATSOURCE, PRESET_AUTO,
LuxMode)
from .helpers.helper import get_sensor_text

# endregion Imports
Expand Down Expand Up @@ -98,13 +110,11 @@ async def async_setup_entry(

deviceInfoCooling = hass.data[f"{DOMAIN}_DeviceInfo_Cooling"]
if deviceInfoCooling is not None:
# Future use: cooling
# text_cooling = get_sensor_text(lang, 'cooling')
text_cooling = get_sensor_text(lang, 'cooling')
entities += [
# TODO:
# LuxtronikCoolingThermostat(hass, luxtronik, deviceInfoCooling, name=text_cooling,
# control_mode_home_assistant=control_mode_home_assistant,
# current_temperature_sensor=LUX_SENSOR_DOMESTIC_WATER_CURRENT_TEMPERATURE, entity_category=None)
LuxtronikCoolingThermostat(
hass, luxtronik, deviceInfoCooling, name=text_cooling, control_mode_home_assistant=control_mode_home_assistant,
current_temperature_sensor=LUX_SENSOR_OUTDOOR_TEMPERATURE, entity_category=None)
]

async_add_entities(entities)
Expand Down Expand Up @@ -132,7 +142,7 @@ class LuxtronikThermostat(ClimateEntity, RestoreEntity):
_status_sensor: Final = LUX_SENSOR_STATUS
_target_temperature_sensor: str = None

_heat_status = [LUX_STATUS_HEATING, LUX_STATUS_DOMESTIC_WATER]
_heat_status = [LUX_STATUS_HEATING, LUX_STATUS_DOMESTIC_WATER, LUX_STATUS_COOLING]

_cold_tolerance = DEFAULT_TOLERANCE
_hot_tolerance = DEFAULT_TOLERANCE
Expand Down Expand Up @@ -367,7 +377,9 @@ class LuxtronikDomesticWaterThermostat(LuxtronikThermostat):
_attr_icon = 'mdi:water-boiler'
_attr_device_class: Final = f"{DOMAIN}__{_attr_unique_id}"

_attr_target_temperature_step = 2.5
_attr_target_temperature_step = 1.0
_attr_min_temp = 40.0
_attr_max_temp = 58.0

_target_temperature_sensor: Final = LUX_SENSOR_DOMESTIC_WATER_TARGET_TEMPERATURE
_heater_sensor: Final = LUX_SENSOR_MODE_DOMESTIC_WATER
Expand All @@ -379,23 +391,25 @@ class LuxtronikHeatingThermostat(LuxtronikThermostat):
_attr_icon = 'mdi:radiator'
_attr_device_class: Final = f"{DOMAIN}__{_attr_unique_id}"

_attr_target_temperature = 20.5
_attr_target_temperature_step = 0.1
_attr_min_temp = 18.0
_attr_max_temp = 23.0
#_attr_target_temperature = 20.5
_attr_target_temperature_step = 0.5
_attr_min_temp = -5.0
_attr_max_temp = +5.0

_target_temperature_sensor: Final = LUX_SENSOR_HEATING_TEMPERATURE_CORRECTION
_heater_sensor: Final = LUX_SENSOR_MODE_HEATING

_heat_status: Final = [LUX_STATUS_HEATING]

class LuxtronikCoolingThermostat(LuxtronikThermostat):
_attr_unique_id = 'cooling'
_attr_icon = 'mdi:snowflake'
_attr_device_class: Final = f"{DOMAIN}__{_attr_unique_id}"

_attr_target_temperature = 20.5
_target_temperature_sensor = LUX_SENSOR_COOLING_THRESHOLD
_attr_target_temperature_step = 0.5
_attr_min_temp = 18.0
_attr_max_temp = 30.0
_attr_preset_modes = [PRESET_NONE]

# _heater_sensor: Final = LUX_SENSOR_MODE_HEATING

Expand All @@ -410,5 +424,5 @@ class LuxtronikCoolingThermostat(LuxtronikThermostat):
# parameters.ID_Einst_Kuhl_Zeit_Aus_akt
# stop cooling after this timeout
# 12.0
_heater_sensor = 'calculations.ID_WEB_FreigabKuehl'
_heat_status = ['cooling']
_heater_sensor = LUX_SENSOR_MODE_COOLING
_heat_status = [LUX_STATUS_COOLING]
32 changes: 23 additions & 9 deletions custom_components/luxtronik/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
CONF_LOCK_TIMEOUT: Final = "lock_timeout"
CONF_UPDATE_IMMEDIATELY_AFTER_WRITE: Final = "update_immediately_after_write"

CONF_PARAMETERS: Final = "parameters"
CONF_PARAMETERS: Final = "parameters"
CONF_CALCULATIONS: Final = "calculations"
CONF_VISIBILITIES: Final = "visibilities"

Expand Down Expand Up @@ -109,7 +109,7 @@ class LuxtronikSensorEntityDescription(SensorEntityDescription):

MIN_TIME_BETWEEN_UPDATES: Final = timedelta(seconds=10)


PRESET_AUTO: Final = 'automatic'
PRESET_SECOND_HEATSOURCE: Final = "second_heatsource"

# region Lux Modes
Expand Down Expand Up @@ -137,6 +137,7 @@ class LuxMode(Enum):
LUX_STATUS_NO_REQUEST: Final = "no request" # 5
LUX_STATUS_HEATING_EXTERNAL_SOURCE: Final = "heating external source" # 6
LUX_STATUS_COOLING: Final = "cooling" # 7
LUX_STATUS_THERMAL_DESINFECTION: Final = "thermal desinfection"

LUX_STATUS_NONE: Final = "None"
LUX_STATUS_UNKNOWN: Final = "unknown"
Expand Down Expand Up @@ -190,20 +191,25 @@ class LuxMode(Enum):

# region Luxtronik Sensor ids
LUX_SENSOR_DETECT_COOLING: Final = "calculations.ID_WEB_FreigabKuehl"
LUX_SENSOR_STATUS: Final = "calculations.ID_WEB_WP_BZ_akt"
LUX_SENSOR_STATUS: Final = "calculations.ID_WEB_WP_BZ_akt"
LUX_SENSOR_STATUS1: Final = "calculations.ID_WEB_HauptMenuStatus_Zeile1"
LUX_SENSOR_STATUS3: Final = "calculations.ID_WEB_HauptMenuStatus_Zeile3"

LUX_SENSOR_REMOTE_MAINTENANCE: Final = "parameters.ID_Einst_Fernwartung_akt"

LUX_SENSOR_HEATING_TEMPERATURE_CORRECTION: Final = "parameters.ID_Einst_WK_akt"
LUX_SENSOR_HEATING_THRESHOLD: Final = "parameters.ID_Einst_Heizgrenze"
LUX_SENSOR_HEATING_THRESHOLD_TEMPERATURE: Final = "parameters.ID_Einst_Heizgrenze_Temp"
LUX_SENSOR_OUTDOOR_TEMPERATURE: Final = "calculations.ID_WEB_Temperatur_TA"

LUX_SENSOR_HEATING_TEMPERATURE_CORRECTION: Final = "parameters.ID_Einst_WK_akt"
LUX_SENSOR_HEATING_THRESHOLD: Final = "parameters.ID_Einst_Heizgrenze"
LUX_SENSOR_HEATING_THRESHOLD_TEMPERATURE: Final = "parameters.ID_Einst_Heizgrenze_Temp"
LUX_SENSOR_HEATING_MIN_FLOW_OUT_TEMPERATURE: Final = "parameters.ID_Einst_Minimale_Ruecklaufsolltemperatur"
LUX_SENSOR_MODE_HEATING: Final = "parameters.ID_Ba_Hz_akt"
LUX_SENSOR_MODE_HEATING: Final = "parameters.ID_Ba_Hz_akt"

LUX_SENSOR_COOLING_THRESHOLD: Final = "parameters.ID_Einst_KuehlFreig_akt"
LUX_SENSOR_MODE_COOLING: Final = "parameters.ID_Ba_Hz_akt"
LUX_SENSOR_COOLING_THRESHOLD: Final = "parameters.ID_Einst_KuehlFreig_akt"
LUX_SENSOR_COOLING_START_DELAY: Final = "parameters.ID_Einst_Kuhl_Zeit_Ein_akt"
LUX_SENSOR_COOLING_STOP_DELAY: Final = "parameters.ID_Einst_Kuhl_Zeit_Aus_akt"
LUX_SENSOR_COOLING_TARGET: Final = "parameters.ID_Sollwert_KuCft2_akt"
LUX_SENSOR_MODE_COOLING: Final = "parameters.ID_Einst_BA_Kuehl_akt"
# Future use:
# LUX_SENSOR_MODE_COOLING: Final = 'parameters.ID_Einst_BA_Kuehl_akt'

Expand Down Expand Up @@ -295,6 +301,14 @@ class LuxMode(Enum):
# unit_of_measurement=TEMP_CELSIUS,
sensor_key="calculations.ID_WEB_Temperatur_TA",
),
LuxtronikSensorEntityDescription(
key="indoor_RBE_temperature",
# name=f"{text_outdoor} {text_temp}",
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
# unit_of_measurement=TEMP_CELSIUS,
sensor_key="calculations.ID_WEB_RBE_RT_Ist",
),
LuxtronikSensorEntityDescription(
key="outdoor_temperature_average",
# name=f"{text_average} {text_outdoor} {text_temp}",
Expand Down
45 changes: 40 additions & 5 deletions custom_components/luxtronik/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
STATE_CLASS_MEASUREMENT)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (DEVICE_CLASS_TEMPERATURE, ENTITY_CATEGORIES,
TEMP_CELSIUS)
TEMP_CELSIUS,
TIME_HOURS)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
Expand All @@ -18,6 +19,9 @@
from . import LuxtronikDevice
from .const import (CONF_LANGUAGE_SENSOR_NAMES, DOMAIN, LOGGER,
LUX_SENSOR_COOLING_THRESHOLD,
LUX_SENSOR_COOLING_START_DELAY,
LUX_SENSOR_COOLING_STOP_DELAY,
LUX_SENSOR_COOLING_TARGET,
LUX_SENSOR_DOMESTIC_WATER_TARGET_TEMPERATURE,
LUX_SENSOR_HEATING_MIN_FLOW_OUT_TEMPERATURE,
LUX_SENSOR_HEATING_TEMPERATURE_CORRECTION,
Expand Down Expand Up @@ -87,17 +91,48 @@ async def async_setup_entry(
hass, luxtronik, deviceInfoDomesticWater,
number_key=LUX_SENSOR_DOMESTIC_WATER_TARGET_TEMPERATURE,
unique_id='domestic_water_target_temperature', name=f"{text_domestic_water} {text_target} {text_temp}",
icon='mdi:water-boiler', unit_of_measurement=TEMP_CELSIUS, min_value=40.0, max_value=60.0, step=2.5, mode=MODE_BOX)
icon='mdi:water-boiler', unit_of_measurement=TEMP_CELSIUS, min_value=40.0, max_value=60.0, step=1.0, mode=MODE_BOX)
]

deviceInfoCooling = hass.data[f"{DOMAIN}_DeviceInfo_Cooling"]
if deviceInfoCooling is not None:
text_cooling_threshold_temperature = get_sensor_text(
lang, 'cooling_threshold_temperature')
text_cooling_start_delay_hours = get_sensor_text(
lang, 'cooling_start_delay_hours')
text_cooling_stop_delay_hours = get_sensor_text(
lang, 'cooling_stop_delay_hours')
text_cooling_target_temperature = get_sensor_text(
lang, 'cooling_target_temperature')
entities += [
LuxtronikNumber(hass, luxtronik, deviceInfoCooling, number_key=LUX_SENSOR_COOLING_THRESHOLD,
unique_id='cooling_threshold_temperature', name=f"{text_cooling_threshold_temperature}",
icon='mdi:upload-outline', unit_of_measurement=TEMP_CELSIUS, min_value=18.0, max_value=30.0, step=0.5, mode=MODE_BOX)
LuxtronikNumber(hass, luxtronik, deviceInfoCooling,
number_key=LUX_SENSOR_COOLING_THRESHOLD,
unique_id='cooling_threshold_temperature',
name=f"{text_cooling_threshold_temperature}",
icon='mdi:sun-thermometer',
unit_of_measurement=TEMP_CELSIUS,
min_value=18.0, max_value=30.0, step=0.5, mode=MODE_BOX),
LuxtronikNumber(hass, luxtronik, deviceInfoCooling,
number_key=LUX_SENSOR_COOLING_TARGET,
unique_id='cooling_target_temperature',
name=f"{text_cooling_target_temperature}",
icon='mdi:snowflake-thermometer',
unit_of_measurement=TEMP_CELSIUS,
min_value=18.0, max_value=25.0, step=1.0, mode=MODE_BOX),
LuxtronikNumber(hass, luxtronik, deviceInfoCooling,
number_key=LUX_SENSOR_COOLING_START_DELAY,
unique_id='cooling_start_delay_hours',
name=f"{text_cooling_start_delay_hours}",
icon='mdi:clock-start',
unit_of_measurement=TIME_HOURS,
min_value=0.0, max_value=12.0, step=0.5, mode=MODE_BOX),
LuxtronikNumber(hass, luxtronik, deviceInfoCooling,
number_key=LUX_SENSOR_COOLING_STOP_DELAY,
unique_id='cooling_stop_delay_hours',
name=f"{text_cooling_stop_delay_hours}",
icon='mdi:clock-end',
unit_of_measurement=TIME_HOURS,
min_value=0.0, max_value=12.0, step=0.5, mode=MODE_BOX),
]

async_add_entities(entities)
Expand Down
32 changes: 31 additions & 1 deletion custom_components/luxtronik/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
LUX_STATUS3_WORKAROUND,
LUX_STATUS_HEATING,
LUX_STATUS_NO_REQUEST,
LUX_STATUS_THERMAL_DESINFECTION,
PLATFORMS,
SECOUND_TO_HOUR_FACTOR,
UNITS,
Expand Down Expand Up @@ -161,6 +162,7 @@ async def async_setup_entry(
text_time = get_sensor_text(lang, "time")
text_temp = get_sensor_text(lang, "temperature")
text_external = get_sensor_text(lang, "external")
text_pump = get_sensor_text(lang, "pump")
text_heat_source_output = get_sensor_text(lang, "heat_source_output")
text_heat_source_input = get_sensor_text(lang, "heat_source_input")
text_outdoor = get_sensor_text(lang, "outdoor")
Expand Down Expand Up @@ -322,16 +324,37 @@ async def async_setup_entry(
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
entity_category=EntityCategory.DIAGNOSTIC,
),
LuxtronikSensor(
hass,
luxtronik,
device_info,
"calculations.ID_WEB_Freq_VD",
"pump frequency",
f"{text_pump} Frequency",
entity_category=None,
icon="mdi:sine-wave",
unit_of_measurement='Hz'
),
]

device_info_heating = hass.data[f"{DOMAIN}_DeviceInfo_Heating"]
if device_info_heating is not None:
text_flow_in = get_sensor_text(lang, "flow_in")
text_flow_out = get_sensor_text(lang, "flow_out")
text_room = get_sensor_text(lang, "room")
text_target = get_sensor_text(lang, "target")
text_operation_hours_heating = get_sensor_text(lang, "operation_hours_heating")
text_heat_amount_heating = get_sensor_text(lang, "heat_amount_heating")
entities += [
LuxtronikSensor(
hass,
luxtronik,
device_info_heating,
"calculations.ID_WEB_RBE_RT_Ist",
"room_temperature",
f"{text_room} {text_temp}",
entity_category=None,
),
LuxtronikSensor(
hass,
luxtronik,
Expand Down Expand Up @@ -585,15 +608,22 @@ def native_value(self): # -> float | int | None:
"""Return the state of the sensor."""
value = self._luxtronik.get_value(self._sensor_key)

if self._sensor_key == LUX_SENSOR_STATUS:
status3 = self._luxtronik.get_value(LUX_SENSOR_STATUS3)
if status3 == LUX_STATUS_THERMAL_DESINFECTION:
# map thermal desinfection to Domestic Water iso Heating
return LUX_STATUS_DOMESTIC_WATER

# region Workaround Luxtronik Bug: Status shows heating but status 3 = no request!
if self._sensor_key == LUX_SENSOR_STATUS and value == LUX_STATUS_HEATING:
status1 = self._luxtronik.get_value(LUX_SENSOR_STATUS1)
status3 = self._luxtronik.get_value(LUX_SENSOR_STATUS3)
if status1 in LUX_STATUS1_WORKAROUND and status3 in LUX_STATUS3_WORKAROUND:
# pump forerun
return LUX_STATUS_NO_REQUEST
# endregion Workaround Luxtronik Bug: Status shows heating but status 3 = no request!
# endregion Workaround Luxtronik Bug: Status shows heating but status 3 = no request!


return value if self._factor is None else round(value * self._factor, 2)

@property
Expand Down
19 changes: 18 additions & 1 deletion custom_components/luxtronik/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
from . import LuxtronikDevice
from .binary_sensor import LuxtronikBinarySensor
from .const import (CONF_LANGUAGE_SENSOR_NAMES, DOMAIN, LOGGER,
LUX_SENSOR_MODE_DOMESTIC_WATER, LUX_SENSOR_MODE_HEATING,
LUX_SENSOR_MODE_DOMESTIC_WATER,
LUX_SENSOR_MODE_HEATING,
LUX_SENSOR_MODE_COOLING,
LuxMode, LUX_SENSOR_HEATING_THRESHOLD, LUX_SENSOR_REMOTE_MAINTENANCE)
from .helpers.helper import get_sensor_text

Expand Down Expand Up @@ -85,6 +87,21 @@ async def async_setup_entry(
name=text_domestic_water_mode_auto, icon='mdi:water-boiler',
device_class=DEVICE_CLASS_HEAT)
]

deviceInfoCooling = hass.data[f"{DOMAIN}_DeviceInfo_Cooling"]
if deviceInfoCooling is not None:
text_cooling_mode_auto = get_sensor_text(
lang, 'cooling_mode_auto')
entities += [
LuxtronikSwitch(
on_state=LuxMode.automatic.value, off_state=LuxMode.off.value,
hass=hass, luxtronik=luxtronik,
deviceInfo=deviceInfoCooling,
sensor_key=LUX_SENSOR_MODE_COOLING,
unique_id='cooling',
name=text_cooling_mode_auto, icon='mdi:snowflake',
device_class=DEVICE_CLASS_HEAT)
]

async_add_entities(entities)
# endregion Setup
Expand Down
3 changes: 2 additions & 1 deletion custom_components/luxtronik/translations/sensor.de.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
},
"luxtronik2__status_line_2": {
"since": "seit",
"in": "in"
"in": "in",
"unknown": "Unbekannt"
},
"luxtronik2__status_line_3": {
"heating": "heizt",
Expand Down
3 changes: 2 additions & 1 deletion custom_components/luxtronik/translations/sensor.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
},
"luxtronik2__status_line_2": {
"since": "since",
"in": "in"
"in": "in",
"unknown": "unknown"
},
"luxtronik2__status_line_3": {
"heating": "heating",
Expand Down
Loading

0 comments on commit 5940811

Please sign in to comment.