TinyC script for Tasmota · your meter, spoken in the dialect a PV battery understandsTinyC-Script für Tasmota · dein Zähler, in der Sprache die eine PV-Batterie versteht
A PV battery needs to know the grid power to hit zero feed-in. Most of them cannot read your meter, but nearly all of them speak to one of a few popular energy meters. This script makes your Tasmota device answer as one of them.
| EcoTracker | Simple: one HTTP endpoint with a JSON document. Found over mDNS. |
|---|---|
| Shelly Pro 3EM | Shelly's RPC dialect over HTTP and UDP. What most batteries expect. |
| Shelly Pro EM50 | The single-channel Shelly. Same dialect, one power value instead of three phases. |
| Shelly EM Gen3 | The current generation. Same dialect again, but it answers three RPCs the others do not have and reports current, voltage, power factor and frequency per phase. |
Works with Marstek, Jackery, NOAH, Hoymiles and others. For Marstek there is a third option that coordinates several batteries: the CT002 emulator.
Requirements: ESP32, Tasmota with TinyC and USE_SML, a reading head. Meter setup is described under SML.
Eine PV-Batterie muss die Netzleistung kennen, um auf Nulleinspeisung zu regeln. Die wenigsten können deinen Zähler lesen, aber fast alle sprechen mit einem von wenigen verbreiteten Energiezählern. Dieses Script lässt dein Tasmota-Gerät als einer davon antworten.
| EcoTracker | Einfach: ein HTTP-Endpunkt mit einem JSON-Dokument. Wird über mDNS gefunden. |
|---|---|
| Shelly Pro 3EM | Shellys RPC-Dialekt über HTTP und UDP. Das, was die meisten Akkus erwarten. |
| Shelly Pro EM50 | Der einkanalige Shelly. Gleicher Dialekt, ein Leistungswert statt drei Phasen. |
| Shelly EM Gen3 | Die aktuelle Generation. Wieder derselbe Dialekt, beantwortet aber drei RPCs, die die anderen nicht kennen, und meldet Strom, Spannung, Leistungsfaktor und Frequenz je Phase. |
Funktioniert mit Marstek, Jackery, NOAH, Hoymiles und anderen. Für Marstek gibt es eine dritte Möglichkeit, die mehrere Akkus koordiniert: den CT002-Emulator.
Voraussetzungen: ESP32, Tasmota mit TinyC und USE_SML, ein Lesekopf. Die Zählereinrichtung steht unter SML.
sml_eco_shelly.tc (or sml_chart_eco_shelly.tc for charts) and upload it into slot 0.Slot 0 only. The HTTP endpoints are webOn handlers, and Tasmota dispatches those to slot 0.
Only one emulator per device. Two meters answering on the same network confuse a battery more than none.
sml_eco_shelly.tc kompilieren (oder sml_chart_eco_shelly.tc für Diagramme) und in Slot 0 hochladen.Nur Slot 0. Die HTTP-Endpunkte sind webOn-Handler, und die reicht Tasmota an Slot 0 weiter.
Nur ein Emulator pro Gerät. Zwei Zähler, die im selben Netz antworten, verwirren einen Akku mehr als gar keiner.
| Mode | EcoTracker, Shelly Pro 3EM, Pro EM50 or EM Gen3. Takes effect after a restart of the script — the mDNS name and the UDP socket are claimed once at start. |
|---|---|
| UDP port | Pro 3EM only. 1010 is Shelly's own port. Marstek B2500 expects 2220 — if the battery does not find the meter, this is the first thing to try. The row is shown in every mode; where the port is not yours to pick it is greyed out — 2223 for the Pro EM50 and 2222 for the EM Gen3, each of which always binds its own, and nothing for EcoTracker, which uses no UDP at all. |
Which one does your battery want? If the manual names a supported meter, follow it. Otherwise start with Shelly Pro 3EM; it is the most widely supported of the three.
Pro EM50 mode is the newest and the least tested. EM1.GetStatus — the call a battery actually polls — is solid; the full Shelly.GetStatus document is derived from the device's structure rather than from a real EM50. If you own one, a comparison would be welcome.
EM Gen3 mode follows a Scripter emulation that is already in the field and works with the Marstek app, so its wire format is not guesswork. Three values it reports are fixed rather than measured: 230 V, power factor 1 and 50 Hz — an SML meter supplies none of them. The per-phase current is derived from the power at 230 V so it stays consistent with the figures next to it.
| Modus | EcoTracker, Shelly Pro 3EM, Pro EM50 oder EM Gen3. Wirkt erst nach einem Neustart des Scripts — der mDNS-Name und der UDP-Socket werden einmal beim Start belegt. |
|---|---|
| UDP-Port | Nur beim Pro 3EM. 1010 ist Shellys eigener Port. Der Marstek B2500 erwartet 2220 — wenn der Akku den Zähler nicht findet, ist das das Erste, was man probiert. Die Zeile steht in jedem Modus da; wo der Port nicht zur Wahl steht, ist sie ausgegraut — 2223 beim Pro EM50 und 2222 beim EM Gen3, die beide fest auf ihrem liegen, und leer beim EcoTracker, der gar kein UDP nutzt. |
Was will dein Akku? Wenn im Handbuch ein unterstützter Zähler steht, danach richten. Sonst mit Shelly Pro 3EM anfangen; der wird am häufigsten unterstützt.
Der Pro-EM50-Modus ist der neueste und am wenigsten erprobte. EM1.GetStatus — der Aufruf, den ein Akku tatsächlich pollt — ist sicher; das vollständige Shelly.GetStatus ist aus der Gerätestruktur abgeleitet, nicht an einem echten EM50 gemessen. Wer einen hat: Vergleich willkommen.
Der EM-Gen3-Modus folgt einer Scripter-Emulation, die bereits im Einsatz ist und mit der Marstek-App funktioniert — das Drahtformat ist also nicht geraten. Drei Werte meldet er fest statt gemessen: 230 V, Leistungsfaktor 1 und 50 Hz; ein SML-Zähler liefert nichts davon. Der Strom je Phase wird aus der Leistung bei 230 V gerechnet, damit er zu den Zahlen daneben passt.
| Offset [W] | Shifts the reported power. A positive value makes the battery aim for that much import instead of exactly zero — a safety margin against feeding into the grid. Negative aims the other way. |
|---|---|
| Regulator tweak | Shapes the value instead of passing it through: above the offset it is damped to a quarter, below it is exaggerated. The battery then approaches from above carefully and corrects downwards quickly. Helps against oscillation; if your battery already regulates calmly, leave it OFF. |
| Update rate [s] | How often the value is recalculated. 1 s is fine. Slower makes the whole loop calmer at the cost of response time. |
| Force sending | Shelly mode only. Repeats the last answer over UDP even without a request. Some firmwares regulate better with a steady stream; most do not need it. |
The To battery row on the main page shows what actually leaves the device, after offset and shaping. Compare it with the raw power to see what the settings do.
The 3 phases option lives in the meter settings, not here — it says whether your meter delivers per-phase power at all. With it on, the sample payloads below carry three real values instead of zeros in powerPhase2, powerPhase3 and b_act_power, c_act_power. The total stays the netted meter value either way — that is what the battery regulates on.
| Offset [W] | Verschiebt die gemeldete Leistung. Ein positiver Wert lässt den Akku auf so viel Bezug statt auf genau null regeln — ein Sicherheitsabstand gegen Einspeisung. Negativ geht in die andere Richtung. |
|---|---|
| Regleroptimierung | Formt den Wert, statt ihn durchzureichen: oberhalb des Offsets wird er auf ein Viertel gedämpft, unterhalb überzeichnet. Der Akku nähert sich dadurch von oben vorsichtig an und korrigiert nach unten schnell. Hilft gegen Schwingen; wenn dein Akku ohnehin ruhig regelt, auf AUS lassen. |
| Update-Rate [s] | Wie oft der Wert neu berechnet wird. 1 s ist gut. Langsamer beruhigt den ganzen Regelkreis, kostet aber Reaktionszeit. |
| Senden erzwingen | Nur im Shelly-Modus. Wiederholt die letzte Antwort über UDP auch ohne Anfrage. Manche Firmware regelt mit einem stetigen Strom besser; die meisten brauchen es nicht. |
Die Zeile An den Akku auf der Hauptseite zeigt, was das Gerät tatsächlich verlässt — nach Offset und Formung. Im Vergleich mit der Rohleistung sieht man, was die Einstellungen bewirken.
Die Option 3 Phasen steht bei den Zähler-Einstellungen, nicht hier — sie sagt aus, ob der Zähler überhaupt Werte je Phase liefert. Ist sie an, tragen die Beispiel-Antworten weiter unten drei echte Werte statt Nullen in powerPhase2, powerPhase3 sowie b_act_power und c_act_power. Der Gesamtwert bleibt in beiden Fällen der saldierte Zählerwert — darauf regelt der Akku.
You can call all of these from a browser to check what the battery sees.
/v1/json | EcoTracker. Power, smoothed power, per-phase power and both energy counters in Wh. |
|---|---|
/rpc/EM.GetStatus | Shelly. Power per phase and total. |
/rpc/Shelly.GetStatus | Shelly. The same plus the energy counters. |
/rpc/EM1.GetStatus | Pro EM50 and EM Gen3. The one channel's power. |
/rpc/EMData.GetStatus | EM Gen3. The energy counters on their own. |
| UDP 1010 / 2220 / 2223 / 2222 | Shelly. The same RPC methods, answer wrapped with the device id. 2223 is the Pro EM50, 2222 the EM Gen3. |
{"power":-440,"powerAvg":-217,"agePower":1000,
"powerPhase1":-440,"powerPhase2":0,"powerPhase3":0,
"energyCounterIn":26714950,"energyCounterOut":659775}
Power is reported on phase 1 only, all three phases summed. That is what a single-value meter reading gives us, and it is what a battery regulating against the total needs.
The device announces itself over mDNS as ecotracker-<mac>, shellypro3em-<mac>, shellyproem50-<mac> or shellyemg3-<mac>, using the ESP's own MAC.
Alle davon kannst du im Browser aufrufen, um zu sehen, was der Akku sieht.
/v1/json | EcoTracker. Leistung, gemittelte Leistung, Leistung je Phase und beide Energiezähler in Wh. |
|---|---|
/rpc/EM.GetStatus | Shelly. Leistung je Phase und Summe. |
/rpc/Shelly.GetStatus | Shelly. Dasselbe plus die Energiezähler. |
/rpc/EM1.GetStatus | Pro EM50 und EM Gen3. Die Leistung des einen Kanals. |
/rpc/EMData.GetStatus | EM Gen3. Nur die Energiezähler. |
| UDP 1010 / 2220 / 2223 / 2222 | Shelly. Dieselben RPC-Methoden, Antwort mit der Geräte-ID umhüllt. 2223 ist der Pro EM50, 2222 der EM Gen3. |
{"power":-440,"powerAvg":-217,"agePower":1000,
"powerPhase1":-440,"powerPhase2":0,"powerPhase3":0,
"energyCounterIn":26714950,"energyCounterOut":659775}
Die Leistung steht komplett auf Phase 1, alle drei Phasen summiert. Mehr gibt ein saldierender Zählerwert nicht her, und genau das braucht ein Akku, der gegen die Summe regelt.
Das Gerät meldet sich über mDNS als ecotracker-<mac>, shellypro3em-<mac>, shellyproem50-<mac> bzw. shellyemg3-<mac>, mit der eigenen MAC des ESP.
You do not need a battery to find out whether the emulator answers. Shelly-EcoTracker Tester.ps1 is a small Windows program that asks the same questions a battery asks — right-click, Run with PowerShell.
Enter the device's IP at the top, then pick two things:
| Device | Sets the port for you: Pro 3EM 1010, the same with a Marstek B2500 2220, Pro EM50 2223, EM Gen3 2222. EcoTracker speaks no RPC and is answered over HTTP. |
|---|---|
| Method | Fills in the request. The list follows the device — only the EM Gen3 offers EMData.GetStatus, because only it answers that one. |
The protocol switch at the very top decides how the request goes out: over UDP as the bare method name, over HTTP as the /rpc/ path. The same selection serves both.
Two more modes are worth knowing:
An answer in the tool proves the emulator works, not that the battery accepts it. If the tool gets valid JSON and the app still finds nothing, the fault is in discovery or in the port — not in the readings.
Ob der Emulator antwortet, lässt sich ohne Akku prüfen. Shelly-EcoTracker Tester.ps1 ist ein kleines Windows-Programm, das dieselben Fragen stellt wie ein Akku — Rechtsklick, Mit PowerShell ausführen.
Oben die IP des Geräts eintragen, dann zwei Dinge wählen:
| Gerät | Setzt den Port für dich: Pro 3EM 1010, derselbe mit einem Marstek B2500 2220, Pro EM50 2223, EM Gen3 2222. Der EcoTracker kennt kein RPC und wird über HTTP gefragt. |
|---|---|
| Methode | Trägt die Anfrage ein. Die Liste richtet sich nach dem Gerät — nur der EM Gen3 bietet EMData.GetStatus an, weil nur er das beantwortet. |
Der Protokollschalter ganz oben entscheidet, wie die Anfrage rausgeht: über UDP als blanker Methodenname, über HTTP als /rpc/-Pfad. Dieselbe Auswahl bedient also beides.
Zwei weitere Modi lohnen sich:
Eine Antwort im Testprogramm beweist, dass der Emulator funktioniert — nicht, dass der Akku sie annimmt. Kommt dort gültiges JSON und die App findet trotzdem nichts, liegt es an der Erkennung oder am Port, nicht an den Messwerten.
| Battery finds nothing | Wrong mode, or the UDP port. Try 2220 in Pro 3EM mode; the Pro EM50 only ever answers on 2223, the EM Gen3 on 2222. Both must be on the same network segment — mDNS does not cross subnets or most guest networks. |
|---|---|
| Found, but 0 W | No meter readings. Check the meter under SML; the endpoints answer even without them. |
| Battery oscillates | Turn on Regulator tweak, or raise the update rate. An offset of 20–50 W also calms things down. |
| Feeds into the grid anyway | Raise the offset. The battery always lags the meter a little; the offset buys that time back. |
| Worked, then stopped | Restart the script — the mDNS name is claimed once at start, and Tasmota's own discovery can win the race after a Wi-Fi reconnect. |
| Akku findet nichts | Falscher Modus oder falscher UDP-Port. Im Pro-3EM-Modus 2220 probieren; der Pro EM50 antwortet nur auf 2223, der EM Gen3 auf 2222. Beide müssen im selben Netzsegment sein — mDNS kommt weder über Subnetze noch durch die meisten Gastnetze. |
|---|---|
| Gefunden, aber 0 W | Keine Zählerwerte. Zähler unter SML prüfen; die Endpunkte antworten auch ohne. |
| Akku schwingt | Regleroptimierung einschalten oder die Update-Rate erhöhen. Ein Offset von 20–50 W beruhigt ebenfalls. |
| Speist trotzdem ein | Offset erhöhen. Der Akku hinkt dem Zähler immer etwas hinterher; der Offset kauft diese Zeit zurück. |
| Ging, geht jetzt nicht mehr | Script neu starten — der mDNS-Name wird einmal beim Start belegt, und Tasmotas eigene Discovery kann das Rennen nach einem WLAN-Neuaufbau gewinnen. |