NEWS
Howto: Shelly Pro2 Notprogramm bei Boilersteuerung
-
Hallo Gemeinde
Ich steuere die Boiler per Shelly Pro2.
Dieses wird wiederum vom RPI mit ioBroker angesteuert.
Hab mir nun ein Shelly Script geschrieben, welches aktiv wird, wenn 2 Tage keine Zustandsveränderung der internen Shelly-Relais stattgefunden hat.
Das Script schaltet in diesem Fall die beiden Relais um 10:00 Uhr für 4h ein.
Die oben fett geschriebenen Werte können im Script-Kopf angepasst werden.
let debug = true; dient zum Einrichten. So sieht man unter "Diagnostics" mehr Log Output und die Zeiten werden auf ein paar Minuten gekürzt.Wenn das RPI abschmiert und ich (für längere Zeit) nicht zuhause bin (zBsp Urlaub), heizen die Boiler trotzdem auf.
Ohne Warmwasser hätte der Mieter wohl nicht so Freude ^^Folgend das Script, welches direkt ins Shelly geschrieben wird.
// Konfiguration let debug = false; // Debug ein/aus let startHour = 10; // Startzeit (Stunden) für das tägliche Einschalten let startMinute = 0; // Startzeit (Minuten) für das tägliche Einschalten let daysDelay = 2; // Nach Tagen Relais einschalten let duration = 240; // Einschaltdauer (Minuten) //////////////////////////////////////////////////////////////////////// if (debug) { print("Skript gestartet."); print("Debug Modus. Einschaltdauer auf 2 Minuten gesetzt!"); duration = 2; // 2 Minuten für den Debug-Modus } duration = duration * 60 * 1000; // Umrechnung von Minuten in Millisekunden let maxNoChangeTime; if (!debug) { maxNoChangeTime = daysDelay * 24 * 60 * 60 * 1000; // Tage in Millisekunden } else { maxNoChangeTime = 60 * 1000; // 60 Sekunden in Millisekunden } // Variablen let ignoreRelayChange = false; // Flag, um Relaisänderungen zu ignorieren let lastRelayChange = Date.now(); // Zeitpunkt der letzten Relais-Änderung let backupModeActive = false; // Gibt an, ob der Backup-Modus aktiv ist let boilerOnTimer = null; // Timer-Referenz für das automatische Ausschalten // Funktion: Boiler einschalten function turnOnBoilers() { if (ignoreRelayChange) return; // Verhindern, dass Relaisänderungen während des Einschaltens erkannt werden print("Schalte Boiler ein (Relais 1 und 2)"); ignoreRelayChange = true; // Relaisänderungen bis zum Ausschalten ignorieren Shelly.call("Switch.Set", { id: 0, on: true }, function(response) { if (response.error) { print("Fehler beim Einschalten von Relais 1:", response.error); } else { print("Relais 1 eingeschaltet"); } }); Shelly.call("Switch.Set", { id: 1, on: true }, function(response) { if (response.error) { print("Fehler beim Einschalten von Relais 2:", response.error); } else { print("Relais 2 eingeschaltet"); } }); // Nach 2 Sekunden das Flag zurücksetzen, um Relaisänderungen zuzulassen Timer.set(2000, false, function() { ignoreRelayChange = false; // Nach 2 Sekunden dürfen Relais-Events wieder verarbeitet werden }); } // Funktion: Boiler ausschalten function turnOffBoilers() { print("Schalte Boiler aus (Relais 1 und 2)"); Shelly.call("Switch.Set", { id: 0, on: false }, function(response) { if (response.error) { print("Fehler beim Ausschalten von Relais 1:", response.error); } else { print("Relais 1 ausgeschaltet"); } }); Shelly.call("Switch.Set", { id: 1, on: false }, function(response) { if (response.error) { print("Fehler beim Ausschalten von Relais 2:", response.error); } else { print("Relais 2 ausgeschaltet"); } }); } // Funktion: Backup-Modus starten function startBackupMode() { if (!backupModeActive) { print("Backup-Modus aktiviert, Boiler schalten täglich für {duration} Stunden ein."); backupModeActive = true; } } // Funktion: Backup-Modus beenden function stopBackupMode() { if (backupModeActive) { print("Backup-Modus deaktiviert, Steuerung erfolgt wieder über Relais-Änderungen."); backupModeActive = false; // Sicherstellen, dass Boiler ausgeschaltet sind und Timer gestoppt wird if (boilerOnTimer) { Timer.clear(boilerOnTimer); boilerOnTimer = null; } turnOffBoilers(); } } // Funktion: Überprüfen, ob eingeschaltet werden muss function checkAndTurnOn() { let now = new Date(); // Aktuelle Zeit let timeElapsed = Date.now() - lastRelayChange; if (debug) { print("Aktuelle Zeit:", now.toString()); // Debug-Ausgabe: Aktuelle Zeit print("Zeit seit der letzten Relais-Änderung (ms):", timeElapsed); // Debug-Ausgabe: Zeit seit der letzten Änderung } if (timeElapsed > maxNoChangeTime) { startBackupMode(); // Berechne den Zielzeitpunkt für den aktuellen Tag (Startzeit) let targetTimeMillis = now.getTime(); // Aktuellen Zeitpunkt in Millisekunden holen // Berechne die Zeitdifferenz bis zur Startzeit let targetTimeMillisAdjusted = targetTimeMillis - (now.getHours() * 3600000) // Stunden in Millisekunden subtrahieren - (now.getMinutes() * 60000) // Minuten in Millisekunden subtrahieren - (now.getSeconds() * 1000) // Sekunden in Millisekunden subtrahieren - now.getMilliseconds(); // Millisekunden subtrahieren // Füge die Startzeit hinzu targetTimeMillisAdjusted += (startHour * 3600000) + (startMinute * 60000); if (targetTimeMillisAdjusted < now.getTime()) { // Falls Zielzeit in der Vergangenheit liegt, setzen wir den nächsten Tag targetTimeMillisAdjusted += 24 * 60 * 60 * 1000; // 24 Stunden in Millisekunden } // Zielzeitpunkt erstellen let targetDate = new Date(targetTimeMillisAdjusted); if (debug) { print("Zielzeitpunkt:", targetDate.toString()); // Debug-Ausgabe: Zielzeitpunkt } // Berechne die Zeitdifferenz let timeDiff = Math.abs(now.getTime() - targetDate.getTime()); // Zeitdifferenz if (debug) { print("Zeitdifferenz (Millisekunden):", timeDiff); // Debug-Ausgabe: Zeitdifferenz } if (timeDiff < 60 * 1000 || debug) { // 1-Minuten-Fenster print("Es ist Zeit, die Boiler einzuschalten."); turnOnBoilers(); // Timer setzen, um die Boiler nach der Dauer auszuschalten if (!boilerOnTimer) { boilerOnTimer = Timer.set(duration, false, function () { print("{duration} Stunden vergangen, schalte Boiler aus."); turnOffBoilers(); boilerOnTimer = null; }); } } else { if (debug) { print("Es ist noch nicht Zeit, die Boiler einzuschalten."); // Debug-Ausgabe, wenn es noch nicht Zeit ist } } } else { // Deaktivieren des Backup-Modus, wenn eine Relais-Änderung festgestellt wurde stopBackupMode(); } } // Funktion: Relais-Event überwachen Shelly.addEventHandler(function (event) { // Prüfen, ob das Event von einem Relais kommt und ob wir gerade Relaisänderungen ignorieren if ((event.component === "switch:0" || event.component === "switch:1") && !ignoreRelayChange) { print("Relais-Event erkannt:", event.component); // Aktualisiere die Zeit der letzten Änderung lastRelayChange = new Date().getTime(); backupModeActive = false; if (debug) { print("Relais-Status geändert, Zeit aktualisiert:", lastRelayChange); } } }); // Timer: Überprüfe alle 3 Minuten Timer.set(180 * 1000, true, function () { checkAndTurnOn(); });
Nach dem Speichern des Scripts nicht vergessen, Run on startup einzuschalten und Status auf Play ( > klicken) zu bringen! Wenn Running! drunter steht, ist alles in Ordnung.