Files
ha_froeling_lambdatronic_mo…/custom_components/froeling_lambdatronic_modbus/number.py
2025-02-19 01:47:28 +01:00

143 lines
7.2 KiB
Python

from homeassistant.components.number import NumberEntity
from pymodbus.client.sync import ModbusTcpClient
import logging
from datetime import timedelta
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.translation import async_get_translations
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, config_entry, async_add_entities):
data = config_entry.data
translations = await async_get_translations(hass, hass.config.language, "entity")
def create_numbers():
numbers = []
if data.get('kessel', False):
numbers.extend([
FroelingNumber(hass, translations, data, "Kessel_Solltemperatur", 40001, "°C", 2, 0, 70, 90),
FroelingNumber(hass, translations, data, "Bei_welcher_RL_Temperatur_an_der_Zirkulationsleitung_soll_die_Pumpe_ausschalten", 40601, "°C", 2, 0, 20, 120)
])
if data.get('hk01', False):
numbers.extend([
FroelingNumber(hass, translations, data, "HK1_Vorlauf_Temperatur_10C_Aussentemperatur", 41032, "°C", 2, 0, 10, 110),
FroelingNumber(hass, translations, data, "HK1_Vorlauf_Temperatur_minus_10C_Aussentemperatur", 41033, "°C", 2, 0, 10, 110),
FroelingNumber(hass, translations, data, "HK1_Heizkreispumpe_ausschalten_wenn_Vorlauf_Soll_kleiner_ist_als", 41040, "°C", 2, 0, 10, 30),
FroelingNumber(hass, translations, data, "HK1_Absenkung_der_Vorlauftemperatur_im_Absenkbetrieb", 41034, "°C", 2, 0, 0, 70),
FroelingNumber(hass, translations, data, "HK1_Aussentemperatur_unter_der_die_Heizkreispumpe_im_Heizbetrieb_einschaltet", 41037, "°C", 2, 0, -20, 50),
FroelingNumber(hass, translations, data, "HK1_Aussentemperatur_unter_der_die_Heizkreispumpe_im_Absenkbetrieb_einschaltet", 41038, "°C", 2, 0, -20, 50),
FroelingNumber(hass, translations, data, "HK1_Frostschutztemperatur", 41039, "°C", 2, 0, 10, 20),
FroelingNumber(hass, translations, data, "HK1_Temp_am_Puffer_oben_ab_der_der_Ueberhitzungsschutz_aktiv_wird", 41048, "°C", 1, 0, 60, 120)
])
if data.get('hk02', False):
numbers.extend([
FroelingNumber(hass, translations, data, "HK2_Vorlauf_Temperatur_10C_Aussentemperatur", 41062, "°C", 2, 0, 10, 110),
FroelingNumber(hass, translations, data, "HK2_Vorlauf_Temperatur_minus_10C_Aussentemperatur", 41063, "°C", 2, 0, 10, 110),
FroelingNumber(hass, translations, data, "HK2_Heizkreispumpe_ausschalten_wenn_Vorlauf_Soll_kleiner_ist_als", 41070, "°C", 2, 0, 10, 30),
FroelingNumber(hass, translations, data, "HK2_Absenkung_der_Vorlauftemperatur_im_Absenkbetrieb", 41064, "°C", 2, 0, 0, 70),
FroelingNumber(hass, translations, data, "HK2_Aussentemperatur_unter_der_die_Heizkreispumpe_im_Heizbetrieb_einschaltet", 41067, "°C", 2, 0, -20, 50),
FroelingNumber(hass, translations, data, "HK2_Aussentemperatur_unter_der_die_Heizkreispumpe_im_Absenkbetrieb_einschaltet", 41068, "°C", 2, 0, -20, 50),
FroelingNumber(hass, translations, data, "HK2_Frostschutztemperatur", 41069, "°C", 2, 0, -10, 20),
FroelingNumber(hass, translations, data, "HK2_Temp_am_Puffer_oben_ab_der_der_Ueberhitzungsschutz_aktiv_wird", 41079, "°C", 1, 0, 60, 120)
])
if data.get('boiler01', False):
numbers.extend([
FroelingNumber(hass, translations, data, "Boiler_1_Gewuenschte_Boilertemperatur", 41632, "°C", 2, 0, 10, 100),
FroelingNumber(hass, translations, data, "Boiler_1_Nachladen_wenn_Boilertemperatur_unter", 41633, "°C", 2, 0, 1, 90)
])
if data.get('austragung', False):
numbers.extend([
FroelingNumber(hass, translations, data, "Pelletlager_Restbestand", 40320, "t", 10, 1, 0, 100)
])
return numbers
numbers = create_numbers()
async_add_entities(numbers)
update_interval = timedelta(seconds=data.get('update_interval', 60))
for number in numbers:
async_track_time_interval(hass, number.async_update, update_interval)
class FroelingNumber(NumberEntity):
def __init__(self, hass, translations, data, entity_id, register, unit, scaling_factor, decimal_places=0, min_value=0, max_value=0):
self._hass = hass
self._translations = translations
self._host = data['host']
self._port = data['port']
self._device_name = data['name']
self._entity_id = entity_id
self._register = register
self._unit = unit
self._scaling_factor = scaling_factor
self._decimal_places = decimal_places
self._min_value = min_value
self._max_value = max_value
self._value = None
@property
def unique_id(self):
return f"{self._device_name}_{self._entity_id}"
@property
def name(self):
translated_name = self._translations.get(f"component.froeling_lambdatronic_modbus.entity.number.{self._entity_id}.name", self._entity_id)
return f"{self._device_name} {translated_name}"
@property
def native_value(self):
return self._value
@property
def native_unit_of_measurement(self):
return self._unit
@property
def native_min_value(self):
return self._min_value
@property
def native_max_value(self):
return self._max_value
@property
def device_info(self):
return {
"identifiers": {(DOMAIN, self._device_name)},
"name": self._device_name,
"manufacturer": "Froeling",
"model": "Lambdatronic Modbus",
"sw_version": "1.0",
}
async def async_set_native_value(self, value):
client = ModbusTcpClient(self._host, port=self._port)
if client.connect():
try:
scaled_value = int(value * self._scaling_factor)
client.write_register(self._register - 40001, scaled_value, unit=2)
self._value = value
except Exception as e:
_LOGGER.error("Exception during Modbus communication: %s", e)
finally:
client.close()
async def async_update(self, _=None):
client = ModbusTcpClient(self._host, port=self._port)
if client.connect():
try:
result = client.read_holding_registers(self._register - 40001, 1, unit=2)
if result.isError():
_LOGGER.error("Error reading Modbus holding register %s", self._register - 40001)
self._value = None
else:
raw_value = result.registers[0]
_LOGGER.debug("Error reading Modbus holding register %s", self._register - 40001)
self._value = round(raw_value / self._scaling_factor, self._decimal_places)
_LOGGER.debug("processed Modbus holding register %s: raw_value=%s, _value=%s", self._register - 40001, raw_value, self._value)
except Exception as e:
_LOGGER.error("Exception during Modbus communication: %s", e)
finally:
client.close()