Skip to content

Instantly share code, notes, and snippets.

@Davc0m
Created November 24, 2025 16:53
Show Gist options
  • Select an option

  • Save Davc0m/dc419aa3147ec3c3d6e7289f89dc0ed8 to your computer and use it in GitHub Desktop.

Select an option

Save Davc0m/dc419aa3147ec3c3d6e7289f89dc0ed8 to your computer and use it in GitHub Desktop.
Shelly Pro 3EM: Saldierende Energiemessung (Net Metering) mit Home Assistant Auto-Discovery
/**
* 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();
}
}
});
@Davc0m
Copy link
Author

Davc0m commented Dec 3, 2025

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:

  • ✅ 100% korrekter Eigenverbrauch
  • ✅ Entlastet Home Assistant (keine Template-Sensoren nötig)
  • Auto-Discovery: Die neuen Sensoren tauchen automatisch in HA auf.

Schritt 1: MQTT im Shelly aktivieren

Damit das Script die Daten an Home Assistant senden kann, muss MQTT aktiv sein.

  1. Öffne das Web-Interface deines Shelly Pro 3EM.
  2. Gehe auf Settings -> MQTT.
  3. Setze folgende Haken:
    • Enable MQTT Control
    • Enable RPC over MQTT
    • RPC status notifications over MQTT
  4. WICHTIG: Trage bei Server die IP-Adresse deines Home Assistant Brokers ein (z.B. 192.168.178.XX:1883).
  5. Falls nötig, User & Passwort eintragen.
  6. Klicke auf Save und starte den Shelly neu (Settings -> Device Reboot).

Schritt 2: Script installieren

  1. Gehe im Shelly-Menü links auf Scripts.
  2. Klicke auf "Create Script".
  3. Gib dem Script einen Namen, z.B. Saldierung HA.
  4. Kopiere den Code aus der Datei shelly_pro3em_net_metering.js hier oben.
  5. Füge den Code in das Editor-Fenster im Shelly ein.
  6. Klicke oben auf "Save".

Schritt 3: Script aktivieren (Wichtig!)

  1. Setze im Script-Menü den Schalter "Enable" (neben dem Namen), damit es nach einem Neustart automatisch läuft.
  2. Klicke auf den Start-Button (Play-Symbol).
  3. Der Status sollte auf "Running" wechseln.

Schritt 4: In Home Assistant einbinden

Das Script unterstützt Auto-Discovery. Du musst keine YAML-Dateien bearbeiten!

  1. Gehe in Home Assistant auf Einstellungen -> Geräte & Dienste.
  2. Suche die Integration MQTT -> Klicke auf Geräte.
  3. Suche nach deinem Shelly Pro 3EM.
  4. Du findest dort nun zwei neue Entitäten:
    • Saldierend Import
    • Saldierend Export

Schritt 5: Energie-Dashboard umstellen

  1. Gehe zu Einstellungen -> Dashboards -> Energie.
  2. Ändere bei "Netzverbrauch" die Quelle auf den neuen Sensor: sensor.shelly_pro_3em_saldierend_import.
  3. Ändere bei "Zurück ins Netz" die Quelle auf: sensor.shelly_pro_3em_saldierend_export.

Fertig! Ab sofort stimmen dein Eigenverbrauch und deine Einspeisung exakt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment