Ich wollte den Stromverbrauch meiner NIBE S40 sauber in Home Assistant haben. Lokal, ohne Cloud, mit ehrlichen Zahlen. Genau dabei bin ich in eine fiese Falle getappt, und die erspare ich dir hier. Diese Anleitung zeigt den kompletten Aufbau: die Modbus-Verbindung, die zuverlässigen Register, und vor allem die Strommessung, die am Ende wirklich stimmt.
Update (Juni 2026): Im Video lese ich die „aktuelle Leistungsaufnahme" direkt aus Register 2305 und baue darauf den Verbrauch auf. Das war ein Fehler. Der Wert ist bei der S40 unzuverlässig, er meldet auch Leistung, wenn der Verdichter gar nicht läuft. Warum das so ist und wie es richtig geht, steht weiter unten im Abschnitt „Die Falle". Die YAML hier ist die korrigierte Version, geprüft gegen meinen echten Stromzähler.
Warum überhaupt Modbus?
Die Standard-Integration von NIBE liefert viele Entitäten, aber die wichtigen Verbrauchswerte sind oft deaktiviert oder kryptisch benannt. Modbus gibt mir direkten, lokalen Zugriff auf die Register der Wärmepumpe. Keine Cloud, keine API-Limits, und du bestimmst selbst, wie oft abgefragt wird.
Die NIBE S40 bringt die Modbus-Schnittstelle ab Werk mit. Du aktivierst sie einmal am Display der Wärmepumpe (unter den Kommunikationseinstellungen, Modbus TCP), danach läuft alles über dein Netzwerk.
Für Einsteiger: Modbus ist nur ein Protokoll, über das die Wärmepumpe ihre internen Werte herausgibt. Jeder Wert hat eine feste „Adresse", das Register. Du sagst Home Assistant: „Lies Adresse 2291 und nenn das Ergebnis Heizenergie." Mehr ist es nicht.
Schritt 1: Modbus-Verbindung anlegen
Leg dir eine eigene Datei an, zum Beispiel packages/nibe.yaml. Trag die lokale IP deiner Wärmepumpe ein (findest du in deinem Router, bei mir der FritzBox).
1modbus:
2 - name: "nibeS40"
3 type: tcp
4 host: 192.168.0.50 # IP deiner Wärmepumpe
5 port: 502
6 sensors:
7 # die Sensoren aus den nächsten Schritten kommen hier reinSchritt 2: Die zuverlässigen Register
Diese Werte kannst du bedenkenlos nutzen: Energie pro Stunde getrennt nach Heizung und Warmwasser, dazu Status und Betriebszeiten. Alles direkt unter sensors: im Modbus-Block von oben.
1 # --- Energie der letzten Stunde (kWh) ---
2 - name: "Nibe Energie Heizung (Stunde)"
3 unique_id: nibe_energie_heizung_stunde
4 address: 2291
5 input_type: input
6 data_type: int16
7 scale: 0.01
8 precision: 2
9 unit_of_measurement: "kWh"
10 state_class: measurement
11 slave: 1
12 scan_interval: 150
13
14 - name: "Nibe Energie Warmwasser (Stunde)"
15 unique_id: nibe_energie_warmwasser_stunde
16 address: 2293
17 input_type: input
18 data_type: int16
19 scale: 0.01
20 precision: 2
21 unit_of_measurement: "kWh"
22 state_class: measurement
23 slave: 1
24 scan_interval: 150
25
26 # --- Status ---
27 - name: "Nibe Betriebsmodus"
28 address: 1028
29 input_type: input
30 data_type: uint16
31 slave: 1
32
33 - name: "Nibe Zusatzheizung aktiv"
34 address: 1029
35 input_type: input
36 data_type: uint16
37 slave: 1
38
39 - name: "Nibe Verdichter Betriebsstunden"
40 address: 1491
41 input_type: input
42 data_type: uint32
43 scale: 0.1
44 unit_of_measurement: "h"
45 state_class: total_increasing
46 slave: 1Hinweis: Die Register 2291 und 2293 sind der echte Verdichter-Verbrauch (Heizung und Warmwasser). Die Zusatzheizungs-Register (2299, 2301) liste ich bewusst nicht auf. Genau die sind bei meiner S40 unzuverlässig, dazu gleich mehr.
Die Falle: „aktuelle Leistungsaufnahme" lügt
Im Video lese ich Register 2305 als „aktuelle Leistungsaufnahme" und packe ein Gauge drauf. Sieht gut aus, ist aber falsch. Mir ist später aufgefallen: Das Gauge stand konstant bei rund 6 kW, auch nachts, auch wenn die Wärmepumpe nachweislich nichts tat.
Der Grund: Die S40 rechnet in diesen Wert eine geschätzte Zusatzheizung mit ein, die physikalisch gar nicht zieht. Ich habe es gegengeprüft. Bei stehendem Verdichter meldete Register 2305 weiter 6,01 kW, während mein echter Stromzähler am Hausanschluss faktisch keinen zusätzlichen Bezug sah. Erst wenn der Verdichter wirklich lief, war der Wert plausibel, rund 1,1 kW, und das deckte sich dann exakt mit dem Zähler.
Was heißt das? Wer ein Gauge oder eine Energie-Integration direkt auf Register 2305 baut, bekommt einen Verbrauch, der schnell das Zehnfache des realen Werts anzeigt. Genau das war mein Fehler im Video.
Auch myUplink ist betroffen: Der „Gesamtverbrauch" aus der myUplink-Cloud zog bei mir an einem Tag um über 60 kWh hoch, obwohl das ganze Haus laut Zähler nur rund 6 kWh gebraucht hat. Verlass dich für den Stromverbrauch also weder blind auf Register 2305 noch auf den myUplink-Verbrauchszähler.
Schritt 3: Leistung nur zählen, wenn der Verdichter läuft
Der Trick ist einfach. Ich nehme den Leistungswert nur dann, wenn der Verdichter tatsächlich arbeitet, sonst setze ich ihn auf 0. Das tötet das Phantom zuverlässig.
Als „läuft der Verdichter?"-Signal brauchst du einen Wert, der bei stehendem Verdichter sauber auf 0 fällt. Bei mir ist das die Verdichter-Ausgangsleistung aus der offiziellen NIBE-Integration (sensor.power_eb101_ep14, intern Register 31807). Sie ist 0, wenn der Verdichter aus ist, und größer 0, sobald er läuft. Das ist die Wärmeleistung, also nicht der Stromverbrauch selbst, aber ein perfektes An/Aus-Signal.
Wichtig: Nimm
power_eb101_ep14nicht als Verbrauch. Das ist die abgegebene Wärme (rund das COP-fache des Stroms), nicht die elektrische Aufnahme. Hier dient sie nur als Schalter. Wenn du rein über Modbus arbeitest, geht genauso die Verdichter-Frequenz oder ein Verdichter-Status-Register. Prüf vorher unter Entwicklerwerkzeuge → Zustände, dass dein Signal bei stehendem Verdichter wirklich 0 ist.
Den eigentlichen Leistungswert nehme ich aus sensor.energy_log_current_power_consumption (Register 32306, in kW). Das ist derselbe Wert wie Register 2305, nur sauber benannt.
1template:
2 - sensor:
3 - name: "WP Leistung elektrisch"
4 unique_id: nibe_wp_leistung_elektrisch
5 unit_of_measurement: "W"
6 device_class: power
7 state_class: measurement
8 state: >
9 {% set laeuft = states('sensor.power_eb101_ep14') | float(0) > 0 %}
10 {% set p = states('sensor.energy_log_current_power_consumption') | float(0) %}
11 {{ (p * 1000) | round(0) if laeuft else 0 }}Was passiert hier: Läuft der Verdichter (laeuft ist wahr), nehme ich die aktuelle Leistung in kW, rechne sie in Watt um (mal 1000) und runde. Steht er, kommt 0 raus. Das Phantom ist weg.
Für Einsteiger: Den Block kopierst du in deine
packages/nibe.yaml. Die beiden Sensornamen heißen je nach Modell etwas anders, oft hängt eine Registernummer hinten dran, etwasensor.power_eb101_ep14_31807odersensor.energy_log_current_power_consumption_32306. Schau unter Entwicklerwerkzeuge → Zustände nach, wie deine genau heißen, und trag sie im Template ein.
Schritt 4: Aus Leistung wird Energie
Eine Leistung in Watt ist eine Momentaufnahme. Fürs Energie-Dashboard und die Kosten brauchst du Kilowattstunden. Die Riemann-Integration summiert die Leistung über die Zeit genau dafür auf.
1sensor:
2 - platform: integration
3 source: sensor.wp_leistung_elektrisch
4 name: WP Energie elektrisch
5 unique_id: nibe_wp_energie_elektrisch
6 unit_prefix: k
7 round: 3
8 method: leftDaraus entsteht sensor.wp_energie_elektrisch in kWh, ein sauber steigender Zähler. method: left passt hier gut, weil unsere Leistung in Stufen springt (an oder aus) und nicht weich verläuft.
Schritt 5: Tag, Monat, Jahr und Kosten
Mit Utility-Metern bekommst du den Verbrauch pro Tag, Monat und Jahr. Auf den Jahreswert setze ich dann die Kosten.
1utility_meter:
2 wp_energie_tag:
3 source: sensor.wp_energie_elektrisch
4 cycle: daily
5 wp_energie_monat:
6 source: sensor.wp_energie_elektrisch
7 cycle: monthly
8 wp_energie_jahr:
9 source: sensor.wp_energie_elektrisch
10 cycle: yearly1 - name: "WP Kosten Jahr"
2 unique_id: wp_kosten_jahr
3 unit_of_measurement: "€"
4 state: >
5 {{ (states('sensor.wp_energie_jahr') | float(0)
6 * states('sensor.dein_strompreis') | float(0)) | round(2) }}Wichtig zum Kopieren: Dieser Kosten-Sensor gehört unter denselben
template:-Block wie „WP Leistung elektrisch" weiter oben. Häng ihn dort einfach als weiteren- name:-Eintrag an. Leg kein zweitestemplate:in derselben Datei an, sonst überschreibt der eine Block den anderen. Dasselbe gilt fürsensor:undutility_meter:: jeder dieser Schlüssel darf pro Datei nur einmal vorkommen.
Tausch sensor.dein_strompreis gegen deinen Preis-Sensor (zum Beispiel aus Tibber) oder trag eine feste Zahl ein, etwa 0.30 für 30 Cent.
Schritt 6: Ab ins Energie-Dashboard
Geh in Home Assistant auf Einstellungen → Dashboards → Energie → Gerät hinzufügen und wähle sensor.wp_energie_elektrisch. Ab da läuft die Wärmepumpe als eigener Verbraucher in deiner Energie-Übersicht mit, sauber neben dem Rest vom Haushalt.
Wenn du die aktuelle Leistung zusätzlich als Gauge und 24-Stunden-Verlauf auf einem eigenen Dashboard sehen willst, zeige ich die passenden Lovelace-Karten im Beitrag NIBE Wärmepumpe: Stromverbrauch auslesen und überwachen.
Hinweis: Ein neuer Sensor taucht erst nach der nächsten vollen Stunde im Energie-Dashboard auf. Home Assistant verdichtet die Langzeit-Statistik nur stündlich. Nicht wundern, wenn die Wärmepumpe direkt nach dem Anlegen noch fehlt.
Alles in einem Block zum Kopieren
Wer nicht jedes Snippet einzeln zusammensetzen will: Hier ist die komplette Konfiguration in einem Stück, genau so gültig in einer Datei wie packages/nibe.yaml. Pass die IP oben und den Strompreis-Sensor unten an, einmal Home Assistant neu laden, fertig.
1modbus:
2 - name: "nibeS40"
3 type: tcp
4 host: 192.168.0.50 # IP deiner Wärmepumpe
5 port: 502
6 sensors:
7 - name: "Nibe Energie Heizung (Stunde)"
8 unique_id: nibe_energie_heizung_stunde
9 address: 2291
10 input_type: input
11 data_type: int16
12 scale: 0.01
13 precision: 2
14 unit_of_measurement: "kWh"
15 state_class: measurement
16 slave: 1
17 scan_interval: 150
18
19 - name: "Nibe Energie Warmwasser (Stunde)"
20 unique_id: nibe_energie_warmwasser_stunde
21 address: 2293
22 input_type: input
23 data_type: int16
24 scale: 0.01
25 precision: 2
26 unit_of_measurement: "kWh"
27 state_class: measurement
28 slave: 1
29 scan_interval: 150
30
31 - name: "Nibe Betriebsmodus"
32 address: 1028
33 input_type: input
34 data_type: uint16
35 slave: 1
36
37 - name: "Nibe Zusatzheizung aktiv"
38 address: 1029
39 input_type: input
40 data_type: uint16
41 slave: 1
42
43 - name: "Nibe Verdichter Betriebsstunden"
44 address: 1491
45 input_type: input
46 data_type: uint32
47 scale: 0.1
48 unit_of_measurement: "h"
49 state_class: total_increasing
50 slave: 1
51
52template:
53 - sensor:
54 - name: "WP Leistung elektrisch"
55 unique_id: nibe_wp_leistung_elektrisch
56 unit_of_measurement: "W"
57 device_class: power
58 state_class: measurement
59 state: >
60 {% set laeuft = states('sensor.power_eb101_ep14') | float(0) > 0 %}
61 {% set p = states('sensor.energy_log_current_power_consumption') | float(0) %}
62 {{ (p * 1000) | round(0) if laeuft else 0 }}
63
64 - name: "WP Kosten Jahr"
65 unique_id: wp_kosten_jahr
66 unit_of_measurement: "€"
67 state: >
68 {{ (states('sensor.wp_energie_jahr') | float(0)
69 * states('sensor.dein_strompreis') | float(0)) | round(2) }}
70
71sensor:
72 - platform: integration
73 source: sensor.wp_leistung_elektrisch
74 name: WP Energie elektrisch
75 unique_id: nibe_wp_energie_elektrisch
76 unit_prefix: k
77 round: 3
78 method: left
79
80utility_meter:
81 wp_energie_tag:
82 source: sensor.wp_energie_elektrisch
83 cycle: daily
84 wp_energie_monat:
85 source: sensor.wp_energie_elektrisch
86 cycle: monthly
87 wp_energie_jahr:
88 source: sensor.wp_energie_elektrisch
89 cycle: yearlyWenn du es zu 100 Prozent genau willst
Die gegatete Methode erfasst den Verdichter sehr gut, und der ist im Sommer praktisch dein gesamter Wärmepumpen-Verbrauch. Springt im Winter wirklich mal der Heizstab an, kann die NIBE diesen Anteil aber nicht verlässlich melden, genau das ist ja das Phantom-Problem. Wer auch das aufs Watt genau will, hängt einen physischen Zähler an den Wärmepumpen-Stromkreis, zum Beispiel einen Shelly Pro 3EM. Der misst direkt am Kabel und ist unabhängig von dem, was die NIBE intern schätzt.
Mein Fazit
Modbus ist der richtige Weg, um die NIBE lokal und detailliert in Home Assistant zu holen. Energie, Status und Betriebszeiten kommen sauber rein. Nur beim reinen Leistungswert musst du aufpassen: Register 2305 allein lügt. Mit dem Gate auf den laufenden Verdichter wird daraus eine ehrliche Messung, die sich mit deinem Stromzähler deckt. Genau so läuft es jetzt bei mir.
Für Profis: Wenn dich der Hintergrund interessiert: Die S40 schätzt die elektrische Zusatzheizung über einen Laufzeitzähler, der bei mir deutlich zu schnell hochlief, und rechnet diese Schätzung in „current power consumption" mit ein. Deshalb steht der Wert auch im reinen Bereitschaftsbetrieb auf mehreren Kilowatt. Der Verdichter-Anteil (Register 2291, 2293) ist davon nicht betroffen, der bleibt korrekt. Wer mag, kann den Verbrauch alternativ auch komplett aus 2291 plus 2293 aufsummieren, statt über die gegatete Leistung zu gehen.
