Created
November 24, 2025 16:53
-
-
Save Davc0m/dc419aa3147ec3c3d6e7289f89dc0ed8 to your computer and use it in GitHub Desktop.
Shelly Pro 3EM: Saldierende Energiemessung (Net Metering) mit Home Assistant Auto-Discovery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Shelly Pro 3EM - Net Metering (Saldierung) & Home Assistant Auto-Discovery | |
| * | |
| * This script calculates the total active power across all 3 phases (A+B+C). | |
| * It simulates a "net metering" utility meter: | |
| * - If Total Power > 0: Increases "Import" counter | |
| * - If Total Power < 0: Increases "Export" counter | |
| * | |
| * FEATURES: | |
| * - Precise integration (runs every 0.5s) | |
| * - Persists counters to KVS (flash memory) to survive reboots | |
| * - MQTT Auto-Discovery: Automatically creates sensors in Home Assistant | |
| * | |
| * SETUP: | |
| * 1. Enable MQTT in Shelly Settings | |
| * 2. Add this script in the "Scripts" section | |
| * 3. Enable "Start on boot" | |
| */ | |
| let CONFIG = { | |
| updateInterval: 500, // Calculation cycle in ms | |
| saveInterval: 300, // Save to KVS every 300 cycles (~2.5 min) | |
| mqttPrefix: "homeassistant", // Standard HA discovery prefix | |
| }; | |
| let SHELLY_ID = undefined; | |
| let energyReturnedWs = 0.0; | |
| let energyConsumedWs = 0.0; | |
| let energyReturnedKWh = 0.0; | |
| let energyConsumedKWh = 0.0; | |
| let saveCounter = 0; | |
| let lastPublishedConsumed = ""; | |
| // 1. Get Device ID and start | |
| Shelly.call("Mqtt.GetConfig", "", function (res, err_code, err_msg, ud) { | |
| SHELLY_ID = res["topic_prefix"]; | |
| if (!SHELLY_ID) { | |
| print("ERROR: MQTT not configured or no topic_prefix found!"); | |
| } else { | |
| print("Shelly ID found: " + SHELLY_ID); | |
| LoadCounters(); | |
| // Announce device to Home Assistant after a short delay | |
| Timer.set(2000, false, AnnounceHA); | |
| } | |
| }); | |
| // 2. Home Assistant Auto-Discovery | |
| function AnnounceHA() { | |
| let haTopic = CONFIG.mqttPrefix + "/sensor/shellypro3em-" + SHELLY_ID; | |
| let deviceData = { | |
| "ids": [SHELLY_ID], | |
| "name": "Shelly Pro 3EM", | |
| "mf": "Shelly", | |
| "mdl": "Pro 3EM", | |
| "sw": "Script-Saldierung" | |
| }; | |
| // Sensor 1: Import (Grid Consumption) | |
| let payloadImport = JSON.stringify({ | |
| "name": "Saldierend Import", | |
| "uniq_id": SHELLY_ID + "_sald_import", | |
| "stat_t": SHELLY_ID + "/energy_counter/consumed", | |
| "unit_of_meas": "kWh", | |
| "dev_cla": "energy", | |
| "stat_cla": "total_increasing", | |
| "dev": deviceData | |
| }); | |
| MQTT.publish(haTopic + "-import/config", payloadImport, 0, true); | |
| // Sensor 2: Export (Return to Grid) | |
| let payloadExport = JSON.stringify({ | |
| "name": "Saldierend Export", | |
| "uniq_id": SHELLY_ID + "_sald_export", | |
| "stat_t": SHELLY_ID + "/energy_counter/returned", | |
| "unit_of_meas": "kWh", | |
| "dev_cla": "energy", | |
| "stat_cla": "total_increasing", | |
| "dev": deviceData | |
| }); | |
| MQTT.publish(haTopic + "-export/config", payloadExport, 0, true); | |
| print("Home Assistant Auto-Discovery sent."); | |
| } | |
| // 3. Load/Save Persistence (KVS) | |
| function LoadCounters() { | |
| Shelly.call("KVS.Get", { "key": "EnergyConsumedKWh" }, function (res) { | |
| if (res && res.value) energyConsumedKWh = Number(res.value); | |
| }); | |
| Shelly.call("KVS.Get", { "key": "EnergyReturnedKWh" }, function (res) { | |
| if (res && res.value) energyReturnedKWh = Number(res.value); | |
| }); | |
| } | |
| function SaveCounters() { | |
| Shelly.call("KVS.Set", { "key": "EnergyConsumedKWh", "value": energyConsumedKWh }); | |
| Shelly.call("KVS.Set", { "key": "EnergyReturnedKWh", "value": energyReturnedKWh }); | |
| print("Counters saved to KVS."); | |
| } | |
| // 4. Main Calculation Loop | |
| Timer.set(CONFIG.updateInterval, true, function () { | |
| if (!SHELLY_ID) return; | |
| let em = Shelly.getComponentStatus("em", 0); | |
| if (typeof em.total_act_power !== 'undefined') { | |
| let power = em.total_act_power; | |
| let energyStep = power * (CONFIG.updateInterval / 1000.0); // Energy in Watt-Seconds | |
| // Logic: Net Metering | |
| if (power >= 0) { | |
| energyConsumedWs += energyStep; | |
| } else { | |
| energyReturnedWs -= energyStep; // power is negative, make positive for counter | |
| } | |
| // Convert Ws to kWh (1 kWh = 3,600,000 Ws) | |
| // We use a small buffer (3600 Ws = 1 Wh) to reduce float errors | |
| if (energyConsumedWs >= 3600) { | |
| let chunk = Math.floor(energyConsumedWs / 3600); | |
| energyConsumedKWh += chunk / 1000.0; | |
| energyConsumedWs -= chunk * 3600; | |
| } | |
| if (energyReturnedWs >= 3600) { | |
| let chunk = Math.floor(energyReturnedWs / 3600); | |
| energyReturnedKWh += chunk / 1000.0; | |
| energyReturnedWs -= chunk * 3600; | |
| } | |
| // Publish to MQTT if value changed | |
| let valC = energyConsumedKWh.toFixed(3); | |
| let valR = energyReturnedKWh.toFixed(3); | |
| if (valC !== lastPublishedConsumed) { | |
| MQTT.publish(SHELLY_ID + "/energy_counter/consumed", valC, 0, false); | |
| MQTT.publish(SHELLY_ID + "/energy_counter/returned", valR, 0, false); | |
| lastPublishedConsumed = valC; | |
| } | |
| // Periodic Save | |
| saveCounter++; | |
| if (saveCounter >= CONFIG.saveInterval) { | |
| saveCounter = 0; | |
| SaveCounters(); | |
| } | |
| } | |
| }); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Anleitung: Shelly Pro 3EM Saldierung (Net Metering) für Home Assistant
Wer den Shelly Pro 3EM mit einer PV-Anlage (Balkonkraftwerk etc.) nutzt, kennt das Problem: Der Shelly saldiert nicht von Haus aus. Das verfälscht den Eigenverbrauch in Home Assistant massiv.
Hier ist die Lösung per Script direkt auf dem Shelly. Das Script verrechnet die Phasen intern in Echtzeit und sendet nur noch zwei saubere Werte (Import & Export) an Home Assistant.
Vorteile:
Schritt 1: MQTT im Shelly aktivieren
Damit das Script die Daten an Home Assistant senden kann, muss MQTT aktiv sein.
192.168.178.XX:1883).Schritt 2: Script installieren
Saldierung HA.shelly_pro3em_net_metering.jshier oben.Schritt 3: Script aktivieren (Wichtig!)
Schritt 4: In Home Assistant einbinden
Das Script unterstützt Auto-Discovery. Du musst keine YAML-Dateien bearbeiten!
Saldierend ImportSaldierend ExportSchritt 5: Energie-Dashboard umstellen
sensor.shelly_pro_3em_saldierend_import.sensor.shelly_pro_3em_saldierend_export.Fertig! Ab sofort stimmen dein Eigenverbrauch und deine Einspeisung exakt.