From 852451ca5833a0bf19f7eb82a5b95bcf5df12655 Mon Sep 17 00:00:00 2001 From: seaspotter Date: Wed, 16 Sep 2026 16:27:39 +0200 Subject: [PATCH 1/2] IDM: Absturz beim Schreiben der Modbus-Register beheben MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit write_register() ohne data_type fällt auf eine ungewandelte Schreibfunktion zurück, die float-Werte nicht verarbeiten kann (struct.error, required argument is not an integer). Betrifft alle 5 Register in send_values() und das Register in set_power_limit() - Konsumenten mit IDM-Wärmepumpe waren dadurch permanent im Fehlerzustand. Register-Kodierung (FLOAT_32 mit wordorder=Little für die kW-Werte, INT_16 für den Batteriefüllstand) gegen das offizielle IDM-Protokoll ("Gebäudeleittechnik-Smartfox") sowie eine funktionierende ioBroker- Modbus-Konfiguration auf echter Hardware verifiziert. --- .../modules/consumers/idm/idm/consumer.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/modules/consumers/idm/idm/consumer.py b/packages/modules/consumers/idm/idm/consumer.py index 8f50b9b19c..17e8753680 100644 --- a/packages/modules/consumers/idm/idm/consumer.py +++ b/packages/modules/consumers/idm/idm/consumer.py @@ -46,15 +46,19 @@ def send_values(values: CurrentValues) -> None: battery_soc = int(values.bat_soc) if values.bat_soc is not None else -1 # Reg 74: Aktueller PV-Überschuss [kW] - client.write_register(74, surplus / 1000, wordorder=Endian.Little, unit=modbus_id) + client.write_register(74, surplus / 1000, data_type=ModbusDataType.FLOAT_32, + wordorder=Endian.Little, unit=modbus_id) # Reg 78: Aktuelle PV-Produktion [kW] - client.write_register(78, pv_power / 1000, wordorder=Endian.Little, unit=modbus_id) + client.write_register(78, pv_power / 1000, data_type=ModbusDataType.FLOAT_32, + wordorder=Endian.Little, unit=modbus_id) # Reg 82: Hausverbrauch [kW], Default 0 - client.write_register(82, values.home_consumption / 1000, wordorder=Endian.Little, unit=modbus_id) + client.write_register(82, values.home_consumption / 1000, data_type=ModbusDataType.FLOAT_32, + wordorder=Endian.Little, unit=modbus_id) # Reg 84: Batterieentladung [kW], Default 0 (negativ = Ladung) - client.write_register(84, values.bat_power / 1000, wordorder=Endian.Little, unit=modbus_id) + client.write_register(84, values.bat_power / 1000, data_type=ModbusDataType.FLOAT_32, + wordorder=Endian.Little, unit=modbus_id) # Reg 86: Batteriefüllstand [%], Default -1 (= kein Speicher) - client.write_register(86, battery_soc, unit=modbus_id) + client.write_register(86, battery_soc, data_type=ModbusDataType.INT_16, unit=modbus_id) def update() -> ConsumerState: if config.configuration.version == 1: @@ -63,7 +67,7 @@ def update() -> ConsumerState: else: power = client.read_input_registers( 4122, ModbusDataType.FLOAT_32, unit=config.configuration.modbus_id) - power *= 100 + power *= 1000 imported, exported = sim_counter.sim_count(power) return ConsumerState( @@ -77,8 +81,8 @@ def set_power_limit(power_limit: float, data: SetLimitData) -> None: # Keine echte Leistungsvorgabe - die IDM-Regelung berechnet ihre Strategie selbst anhand dieses Wertes. # Hinweis: Dies überschreibt den intern berechneten PV-Überschuss der IDM-Regelung und kann # die PV-Eigenverbrauchs-Statistik im IDM-Portal verfälschen. - client.write_register(74, max(power_limit, 0) / 1000, wordorder=Endian.Little, - unit=config.configuration.modbus_id) + client.write_register(74, max(power_limit, 0) / 1000, data_type=ModbusDataType.FLOAT_32, + wordorder=Endian.Little, unit=config.configuration.modbus_id) return ConfigurableConsumer(consumer_config=config, initializer=initializer, From 30ecda724a305940e53765abb66ee668475494d2 Mon Sep 17 00:00:00 2001 From: seaspotter Date: Wed, 16 Sep 2026 16:34:54 +0200 Subject: [PATCH 2/2] IDM: Vorzeichen der Batterieleistung an Register 84 korrigieren MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit openWBs bat_power-Konvention ist negativ=Entladung, positiv=Ladung (siehe z.B. sungrow_sh/bat.py: is_discharging -> negativ, is_charging -> positiv). Register 84 "Batterieentladung" der IDM-Schnittstelle erwartet die umgekehrte Konvention (negativ=Ladung, siehe eigener Code-Kommentar) - der Wert wurde bisher unverändert durchgereicht und dadurch mit falschem Vorzeichen an die WP gemeldet. --- packages/modules/consumers/idm/idm/consumer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/modules/consumers/idm/idm/consumer.py b/packages/modules/consumers/idm/idm/consumer.py index 17e8753680..f5f0650c82 100644 --- a/packages/modules/consumers/idm/idm/consumer.py +++ b/packages/modules/consumers/idm/idm/consumer.py @@ -54,8 +54,10 @@ def send_values(values: CurrentValues) -> None: # Reg 82: Hausverbrauch [kW], Default 0 client.write_register(82, values.home_consumption / 1000, data_type=ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=modbus_id) - # Reg 84: Batterieentladung [kW], Default 0 (negativ = Ladung) - client.write_register(84, values.bat_power / 1000, data_type=ModbusDataType.FLOAT_32, + # Reg 84: Batterieentladung [kW], Default 0 (negativ = Ladung). values.bat_power kommt roh aus + # process.py (negativ = Entladung, positiv = Ladung, gleiche Konvention wie z.B. bei Sungrow) -> + # Vorzeichen drehen, um auf die von IDM erwartete Konvention zu kommen + client.write_register(84, -values.bat_power / 1000, data_type=ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=modbus_id) # Reg 86: Batteriefüllstand [%], Default -1 (= kein Speicher) client.write_register(86, battery_soc, data_type=ModbusDataType.INT_16, unit=modbus_id)