Inhaltsverzeichnis
- Der Plan, der hätte funktionieren sollen
- Die Wand: Writes verweigert, Reads sauber
- Der Schwenk: lokal lesen, in der Cloud schreiben
- Was die Cloud-Steuerung wirklich bringt: tagsüber Gratiswärme, morgens ein warmer Tank
- Den Split sehen, der das Ganze rechtfertigt
- Wohin das gehört
- Stufenlos statt Ein/Aus — darum geht es im Kern
- Drei Wege, einen Heizstab per PV-Überschuss zu steuern
- Die Automatisierung dahinter
An einem sonnigen Nachmittag macht mein Dach mehr Strom, als das Haus aufnehmen kann. Der Akku ist voll, der Wechselrichter würde den Rest am liebsten für fast nichts ins Netz geben, und unten im Keller steht ein 200-Liter-Tank mit kaltem Wasser. Der naheliegende Zug ist, diesen Überschuss in den Heizstab zu kippen und als Warmwasser zu speichern. Das Gerät dafür ist ein my-PV AC·THOR 9s — ein ohmscher PV-Überschuss-Diverter, der die Leistung in das Boiler-Heizelement moduliert, statt sie ins Netz abfließen zu lassen. Dieser Beitrag ist die Geschichte, wie ich ihn unter Home Assistant-Kontrolle gebracht habe — und die Wand, gegen die ich dabei lief.
Es ist Teil 03 davon, wie ich mein Haus selbst hoste. Teil 01 brachte Home Assistant auf einen Docker-Host, Teil 02 ergänzte HACS, und die Wechselrichter-Seite — ein Huawei SUN2000-8KTL-M1, über Modbus TCP per Huawei-SDongle ausgelesen, samt eines Akkus, dessen Laden und Entladen ich mitschreibe — war schon Vorarbeit. Überschuss ist für den AC·THOR schlicht das, was nach Hauslast und Akkuladung übrig bleibt. Das Schwere war also nicht die Energielogik. Es war die Steuerebene.
Der Plan, der hätte funktionieren sollen
Der AC·THOR spricht Modbus TCP, und mein ganzer Energie-Stack lebt schon auf Modbus, also schrieb sich das Design von selbst. Zwei Register machen alles: Register 5000 ist Heizung ein/aus (0 oder 1), und Register 5006 ist die Leistungsgrenze in Watt. Das Gerät hat zwei nützliche Modi — eine Eco-Einstellung mit 1500 W für reine Solarheizung und Full Power mit 3000 W, was zugleich sein Hardware-Maximum ist. Man kann live umschalten, während es heizt.
In Home Assistant habe ich das als kleine Steuerfläche modelliert: ein input_select für den Leistungsmodus, ein input_boolean für das Heizaktiv-Flag und eine Dashboard-Karte — AC·THOR Steuerung — mit schlichten Start- und Stopp-Knöpfen. Hinter den Knöpfen ein paar mbpoll-artige Writes: 5000 anstoßen zum Aktivieren, 5006 auf 1500 oder 3000 setzen. Ich testete erst die Reads, um Slave und Port sicher zu haben. Die Boiler-Temperatur kam sauber über Holding-Register 1001 (int16, in °C), alle 30 Sekunden abgefragt. Alles sah startklar aus.
Die Wand: Writes verweigert, Reads sauber
Dann schickte ich den ersten Write, und der AC·THOR schlug die Tür zu. Connection refused — kein Timeout, kein Fehler wegen falschem Wert, eine glatte Verweigerung auf Geräteebene. Ich prüfte Slave-ID, Register, Byte-Reihenfolge, Funktionscode. Nichts davon zählte. Das Ding nimmt schlicht keine Modbus-Write-Operationen an. Wirklich verwirrend war, dass dieselbe Verbindung bereitwillig Reads beantwortet: Register 1001 lieferte weiter alle 30 Sekunden die Boiler-Temperatur, am selben Host und Port, während jeder Write abprallte.
Ehrlich gesagt: das schmerzte. Ich hatte den ganzen Steuerpfad auf der Annahme gebaut, dass ein Gerät, das Modbus anbietet, es in beide Richtungen anbietet. Tut es hier nicht, und das ist eine bewusste Entscheidung von my-PV — die Register sind echt, nur über lokales Modbus eben nur lesbar. Mein stolzes, rein lokales Switch-Design war für die Steuerung also tot. Die Boiler-Temperatur-Überwachung überlebt unangetastet, weil das immer nur ein Read war.
# Modbus-Read funktioniert weiter — Boiler-Temp bleibt lokal; nur WRITES werden verweigert
- name: ac_thor
type: tcp
host: <LOCAL_IP> # geschwärzt — niemals die LAN-Adresse veröffentlichen
port: 502
delay: 1
timeout: 5
sensors:
- name: "Boiler-Temperatur"
slave: 1
address: 1001
input_type: holding
data_type: int16
unit_of_measurement: "°C"
scan_interval: 30Der Schwenk: lokal lesen, in der Cloud schreiben
Der Weg, der tatsächlich funktionierte, ist die my-PV Cloud-API. Jeder AC·THOR telefoniert nach Hause, und diese Cloud legt genau die Konfiguration offen, die die lokalen Writes berührt hätten: ein GET /data für Live-Monitoring und ein GET/PUT /setup zum Lesen und Ändern der Konfiguration. Der Split, den ich ausgeliefert habe, ist also lokal-lesen, Cloud-schreiben — die Boiler-Temperatur bleibt auf lokalem Modbus (Register 1001, alle 30 s, ohne Internet-Abhängigkeit), und jede Steuerung geht über die Cloud.
Es wurmte mich ein wenig. Von einer Hersteller-Cloud abhängig zu sein, nur um meinen eigenen Heizstab einzuschalten, ist genau die Abhängigkeit, der ich durch Selbsthosting entkommen will, und wenn ihre API ausfällt, hängt meine morgendliche Dusche an fremder Verfügbarkeit. Aber es ist der Split, der heute funktioniert, und er schaltet etwas frei, das das rein lokale Design nie konnte: echtes zeitgesteuertes Verhalten.
Ein Fallstrick ist einen Satz wert. Ein PUT auf /setup gibt sofort ok zurück, aber das Gerät wendet es erst nach weiteren 4 bis 6 Sekunden an. Wer sofort ein GET /setup zur Bestätigung hinterherschickt, liest die alten Werte und denkt, der Write sei ignoriert worden. Wurde er nicht — man muss nur warten und dann pollen.
Was die Cloud-Steuerung wirklich bringt: tagsüber Gratiswärme, morgens ein warmer Tank
Der interessante Teil ist nicht Ein/Aus — es sind zwei Temperaturziele und ein Zeitfenster. Der AC·THOR führt ein max. Solar-Ziel (ww1target) und ein niedrigeres Boost-Ziel (ww1boost). Tagsüber lasse ich den Überschuss den Tank bis zu einer hohen Solar-Obergrenze treiben — 65 °C — weil diese Wärme gratis ist; jedes Grad, das die Sonne einlagert, ist ein Grad, das ich nachts nicht kaufe. Temperaturen sind in Zehntelgrad codiert, 650 heißt also 65,0 °C und 400 heißt 40,0 °C, worüber man genau einmal stolpert.
Den Morgen erledigt der Sicherstellungsmodus der Cloud — Parameter bstmode. Ich setze ein Boost-Fenster von 01:00 bis 08:00 (bstton1=1, bsttof1=8) mit einem bescheidenen 40 °C-Bedarfsziel, sodass der Tank warm ist, bevor jemand duscht, egal ob die Nacht sonnig war. Ein zweites optionales Fenster gibt es, wenn man will. Tagsüber bleibt es solar-only bis zur hohen Obergrenze; die Nacht garantiert nur einen Boden.
# Lokale Modbus-Writes werden verweigert — Konfig stattdessen über die my-PV Cloud-API steuern.
# 40°C-Morgen-Boost-Fenster 01:00–08:00 setzen (Werte in Zehntelgrad: 400 = 40,0°C)
curl -X PUT "https://api.my-pv.com/api/v1/device/<SERIAL>/setup" \
-H "Authorization: <REDACTED_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"bstmode": 1, "ww1boost": 400, "bstton1": 1, "bsttof1": 8}'
# Die API antwortet sofort "ok"; das Gerät wendet es ~4–6 s später an, also mit GET /setup nachpollen.Den Split sehen, der das Ganze rechtfertigt
Warum sich der Aufwand lohnt, zeigt sich in zwei Sensoren: Solar-Heizleistung und Netz-Heizleistung, getrennt gemeldet. Der ganze Sinn der Überschuss-Umleitung ist, dass die erste Zahl groß und die zweite null ist — Wärme aus Sonne, die ich sonst exportiert hätte, nicht vom Zähler. Daneben beobachte ich die aktuelle Leistungsgrenze und die Boiler-Temperatur, und die Modbus-Reads des Wechselrichters liefern PV-Ertrag, Netzexport und -import sowie das tägliche Laden und Entladen des Akkus. Mit all dem an einem Ort sehe ich in Echtzeit, wie Überschuss zu Warmwasser wird.
Und eine leise Sicherheitsnotiz, die mich dem Setup vertrauen ließ: welche Leistung oder welches Ziel ich auch befehle, der AC·THOR erzwingt ohnehin seine eigenen internen Thermo- und Sicherheitsgrenzen. Software fragt an, Hardware schützt. Genau diese Trennung will man für ein 3-kW-Element in einem Wassertank — meine Automatisierung darf falsch sein, ohne gefährlich zu sein.
Wohin das gehört
Der Warmwasser-Diverter ist eine Scheibe eines Gesamthaus-Energie-Setups, kein Spielzeug. Dieselbe Home-Assistant-Installation fährt raumweise Heizkörperthermostate, die auf ein Absenk-Preset fallen, sobald ein Fensterkontakt öffnet, und einen geplanten hausweiten Nachtmodus um 21:00 mit Tagmodus zurück um 05:00 über ein gutes Dutzend Zonen. Das Warmwasser ist nur zufällig die Ecke, in der der naheliegende lokale Weg eine Sackgasse war und ich eine Cloud-Abhängigkeit schlucken musste, um zu liefern.
Wenn ich die Lektion verdichten müsste: ein Gerät, das ein Protokoll spricht, verspricht nicht, jedes Verb davon zu sprechen. Read ging, Write nicht, und der Fix war nicht, gegen das Gerät zu kämpfen — es war, den billigen, lokalen, internetfreien Read dort zu lassen, wo er hingehört, und nur die Writes auf den einen Transport zu verlegen, den der Hersteller tatsächlich erlaubt. Nicht die Architektur, die ich wollte. Die, die morgens warmes Wasser im Tank hatte.
Stufenlos statt Ein/Aus — darum geht es im Kern
Wenn du einen Satz aus diesem Artikel mitnimmst, dann diesen: ein Heizstab an einem Relais ist für PV-Überschuss die falsche Paarung, und keine Automatisierung repariert das. Ein Relais hat zwei Stellungen. Dein Überschuss hat sie nicht.
Nimm einen Stab mit 3 kW Nennleistung. Um vier Uhr nachmittags liegt der Überschuss bei 1,4 kW und fällt. Schaltest du das Relais ein, ziehst du die fehlenden 1,6 kW aus dem Netz — du heizt Wasser also mit gekauftem Strom und erzählst dir, es sei gratis. Lässt du es aus, gehen 1,4 kW ins Netz, für die Einspeisevergütung, und die ist hier nicht üppig.
Stufenlose Steuerung löst genau das. Ein Leistungssteller schneidet jede Netz-Halbwelle über den Phasenanschnitt an, sodass der Stab jeden Wert zwischen etwa null und seiner Nennleistung ziehen und der Überschusskurve kontinuierlich folgen kann. Das ist der einzige Grund, warum es Geräte wie den AC·THOR gibt und nicht bloß eine schaltbare Steckdose.
Und der Teil, der mich überrascht hat: mit so einem Gerät berechnet Home Assistant den Überschuss überhaupt nicht. Der AC·THOR misst selbst am Zähler und moduliert eigenständig. HA setzt Zielwerte und liest Zustände. Der Regelkreis sitzt in der Hardware — genau das habe ich bezahlt, und gemerkt habe ich es erst, als ich die Alternative auf Papier durchgerechnet habe.
Drei Wege, einen Heizstab per PV-Überschuss zu steuern
Es sind wirklich nur drei, und sie unterscheiden sich weit stärker im nötigen Aufwand als im Hardware-Preis.
1 — Relais, Ein/Aus. Ein Shelly plus Schütz, geschaltet von einer Home-Assistant-Automatisierung auf eine Überschuss-Schwelle. Mit Abstand am günstigsten. Es funktioniert vertretbar, wenn dein Speicher groß und dein Überschuss stabil ist, denn ein großer Puffer verzeiht grobe Regelung. Du nimmst an jeder Kante entweder Netzbezug oder verschenkten Überschuss in Kauf.
2 — Gestuft. Zwei oder drei Stäbe, oder ein Stab mit mehreren Anzapfungen, in Stufen geschaltet — 1 kW, 2 kW, 3 kW. Grobe Modulation mit reinen Relais. Mehr Verdrahtung, keine Elektronik, und näher am Überschuss als ein einzelnes Relais je kommt.
3 — Stufenloser Leistungssteller. Phasenanschnitt oder PWM, der dem Überschuss kontinuierlich folgt. Entweder ein fertiger Diverter oder ein selbst gebauter SSR-Steller. Am teuersten in Hardware, am günstigsten im Aufwand.
Ich habe Weg 3 genommen, und der ehrliche Grund ist nicht die Effizienz — es ist, dass Weg 1 Home Assistant zum Regler macht. Dann gehören dir die Überschussberechnung, die Hysterese, die Entprell-Verzögerungen und jeder Fehlerfall: was passiert, wenn die Zähler-Integration wegbricht, wenn ein Template-Sensor beim Neustart unknown liefert, wenn neunzig Sekunden eine Wolke durchzieht. Nichts davon ist schwer. Alles davon musst du am Laufen halten.
Wäre ich den günstigen Weg gegangen, sähe er ungefähr so aus. Beachte die zwei Schwellen — die Ausschaltschwelle liegt bewusst unter der Einschaltschwelle, denn eine einzige Schwelle plus ein schwankender Eingang ergibt ein Relais, das sich selbst zu Tode schaltet:
# Das Überschuss-Signal, wenn DU den Regelkreis besitzt und nicht das Gerät.
# Netzleistung ist der ehrliche Eingang: negativ = Einspeisung, positiv = Bezug.
template:
- sensor:
- name: "PV-Überschuss"
unit_of_measurement: "W"
state: >
{{ [0, (states('sensor.grid_power') | float(0)) * -1] | max | round(0) }}
automation:
- alias: "Heizstab bei Überschuss ein"
triggers:
- trigger: numeric_state
entity_id: sensor.pv_ueberschuss
above: 2200 # Nennleistung des Stabs plus Reserve, nicht die nackte Nennleistung
for: "00:05:00" # Wolken aussitzen statt das Relais klappern zu lassen
conditions:
- condition: numeric_state
entity_id: sensor.boiler_temperature
below: 55
actions:
- action: switch.turn_on
target: { entity_id: switch.heizstab }
mode: single
- alias: "Heizstab aus, wenn der Überschuss einbricht"
triggers:
- trigger: numeric_state
entity_id: sensor.pv_ueberschuss
below: 1800 # bewusst niedriger als die Einschaltschwelle = Hysterese
for: "00:03:00"
actions:
- action: switch.turn_off
target: { entity_id: switch.heizstab }
mode: singleDie for:-Dauern sind wichtiger als die Schwellen. Ohne sie taktet eine durchziehende Wolke ein Schütz, das für einige hunderttausend Schaltspiele ausgelegt ist, mehrmals pro Minute. Das ist der Fehlerfall, vor dem niemand warnt, und er ist mechanisch statt logisch — also zeigt ihn kein Test im Sommer.
Eines haben alle drei Wege gemeinsam: nimm die Netzleistung als Eingang, nicht die PV-Erzeugung. Die Erzeugung sagt dir, was das Dach macht; die Netzleistung sagt dir, was das Haus nicht aufnehmen konnte. Das sind zwei verschiedene Zahlen, und nur die zweite ist Überschuss. Ein Shelly mit Energiemessung liefert diesen Wert lokal, ohne Eingriff am Wechselrichter — und dasselbe Gerät kann das Relais aus Weg 1 sein, was sich hübsch trifft. Wie man ihn für lokales Schalten und Messen in Home Assistant einbindet, steht in einem eigenen Artikel.
Die Automatisierung dahinter
Sobald der Boiler die 55 °C erreicht, schalte ich den AC·THOR-Boost automatisch wieder ab – mit Push-Bestätigung aufs Handy. Genau diese Automatisierung läuft bei mir:
# Boost beenden, sobald der Boiler die 55 °C-Zieltemperatur erreicht
alias: "AC THOR: Boost bei 55 °C beenden"
triggers:
- trigger: numeric_state
entity_id: sensor.boiler_temperatur # eigener Sensor-Name
above: 55
for:
minutes: 5
conditions: []
actions:
- action: shell_command.acthor_disable_boost
- action: notify.mobile_app # generisch — kein Geräte-/Personenname
data:
title: "✅ AC·THOR Zieltemperatur erreicht"
message: "Boost aus bei {{ states('sensor.boiler_temperatur') }} °C"
mode: single
Mein PV-/Boiler-Dashboard in Home Assistant – Live-Werte: PV-Leistung, Batterie-SOC und Boiler-Temperatur auf einen Blick.
Der AC·THOR selbst hat auch einen eigenen Artikel — warum die lokalen Modbus-Schreibzugriffe verweigert wurden und wie am Ende die my-PV Cloud API das Steuern übernommen hat — falls dich die Steuerungs-Seite desselben Geräts interessiert.



