Shelly 1PM Plus (Gen4) – Steuerung per InfluxDB

[ Shelly Automation Version 2 ] [ Energiemonitor ]
Die Entwicklung der Shelly Produkte und der HomeMatic Haussteuerung schreiten weiter voran. Dieser Bereich dient der grafischen Anzeige von vielen Shelly und HomeMatic Lösungen., sowie einer Shelly Steuerung Version 2. Es können bis zu 50 Geräte ausgelesen und angezeigt werden. Mit der Steuerung können bis zu 5 Shelly Relais gesteuert werden. Die Cloud wird dazu nicht benutzt. Alles passiert rein lokal.

Moderator: Ulrich

Benutzeravatar
Schwarzermann
Beiträge: 371
Registriert: Sa 9. Okt 2021, 11:16
Wohnort: 87733
Hat sich bedankt: 9 Mal
Danksagung erhalten: 11 Mal

Shelly 1PM Plus (Gen4) – Steuerung per InfluxDB

Beitrag von Schwarzermann »

Code: Alles auswählen

// ###########################################################
// Shelly 1PM Plus (Gen4) Script zur Steuerung über InfluxDB
// ###########################################################
//
// Dieses Skript fragt alle 30 Sekunden einen Wert ("Sonnenstrahlung")
// aus der InfluxDB ab und schaltet das Relais abhängig von einem
// einstellbaren Schwellenwert ("threshold").
//
// Zusätzlich kann festgelegt werden, ob das Relais eingeschaltet wird,
// wenn der Wert >= threshold ("greater") oder <= threshold ("less") ist.
//
// Die Konfiguration (threshold + mode) wird dauerhaft im Shelly gespeichert,
// sodass sie nach einem Neustart erhalten bleibt.
// ###########################################################


// -------------------------------
// 1. Verbindungs-Einstellungen
// -------------------------------
let influxHost  = "192.168.178.54";   // IP-Adresse des InfluxDB-Servers (hier Raspberry Pi mit Solaranzeige)
let dbName      = "wunderweather";    // Name der Influx-Datenbank
let measurement = "weather";          // Measurement, in dem die Daten stehen
let field       = "Sonnenstrahlung";  // Feldname (Column), dessen Wert abgefragt wird
let interval    = 30000;              // Abfrageintervall in Millisekunden (30000 ms = 30 Sekunden)


// -------------------------------
// 2. Script-Verwaltung
// -------------------------------
// Die Script-ID ist im Shelly-Webinterface unter "Scripts" zu sehen.
// Wenn nur ein Script läuft, ist die ID fast immer 0.
let scriptId    = 0;


// -------------------------------
// 3. Konfigurierbare Parameter
// -------------------------------
// Diese Werte können fest im Code geändert werden oder per RPC (Script.SetData)
// von außen gesetzt werden.
let threshold   = 68;                // Schwellwert, Standardwert
let mode        = "less";          // Vergleichsmodus:
//    "greater" = Relais EIN, wenn Wert >= threshold
//    "less"    = Relais EIN, wenn Wert <= threshold


// -------------------------------
// 4. Interner Status
// -------------------------------
// Wird benutzt, um nur bei einer Änderung den Schaltbefehl zu senden.
let lastState   = null;


// -------------------------------
// 5. Beim Start gespeicherte Werte laden
// -------------------------------
Shelly.call("Script.GetData", { id: scriptId }, function(res) {
  if (res && res.data) {
    // Falls Daten gespeichert sind, überschreiben wir die Standardwerte
    if (res.data.threshold !== undefined) threshold = res.data.threshold;
    if (res.data.mode) mode = res.data.mode;

    print("Geladene Einstellungen: threshold =", threshold, "mode =", mode);
  } else {
    print("Standardwerte: threshold =", threshold, "mode =", mode);
  }
});


// -------------------------------
// 6. Funktion zum Speichern neuer Werte
// -------------------------------
// Diese Funktion kann aus einem RPC-Aufruf heraus genutzt werden.
// Beispiel:
// curl -X POST http://192.168.178.60/rpc/Script.SetData -d '{"id":0,"data":{"threshold":100,"mode":"less"}}'
function saveConfig(newThreshold, newMode) {
  let cfg = { threshold: newThreshold, mode: newMode };

  Shelly.call("Script.SetData", { id: scriptId, data: cfg });

  // Werte auch im Script direkt setzen
  threshold = newThreshold;
  mode = newMode;

  print("Neue Konfiguration gespeichert:", JSON.stringify(cfg));
}


// -------------------------------
// 7. Hauptfunktion: checkSun()
// -------------------------------
// Abfrage der InfluxDB und Schalten des Relais
function checkSun() {
  // InfluxQL Query vorbereiten:
  // SELECT last("Sonnenstrahlung") FROM "weather"
  // → hier URL-encoded wegen Sonderzeichen
  let query = "SELECT%20last(%22" + field + "%22)%20FROM%20%22" + measurement + "%22";
  let url = "http://" + influxHost + ":8086/query?db=" + dbName + "&q=" + query;

  // HTTP GET an InfluxDB
  Shelly.call("HTTP.GET", { url: url }, function(result) {
    if (!result || result.code !== 200) {
      print("HTTP Fehler:", result ? result.code : "kein Ergebnis");
      return;
    }

    try {
      // JSON-Antwort parsen
      let data = JSON.parse(result.body);
      let value = data.results[0].series[0].values[0][1];

      print("Sonnenstrahlung:", value, "(threshold:", threshold, "mode:", mode, ")");

      // Schaltlogik je nach Modus
      let newState = false;
      if (mode === "greater") {
        newState = value >= threshold;
      } else if (mode === "less") {
        newState = value <= threshold;
      }

      // Nur schalten, wenn sich der Zustand geändert hat
      if (lastState === null || newState !== lastState) {
        Shelly.call("Switch.Set", { id: 0, on: newState });
        print("Relais", newState ? "EIN" : "AUS");
        lastState = newState;
      } else {
        print("Keine Änderung – Relais bleibt", newState ? "EIN" : "AUS");
      }

    } catch (e) {
      print("Parsing Fehler:", e);
    }
  });
}


// -------------------------------
// 8. Timer starten
// -------------------------------
// Alle 30 Sekunden wird checkSun() automatisch ausgeführt.
Timer.set(interval, true, checkSun);

// Einmal direkt beim Start ausführen
checkSun();
;
Ich habe mich mal wieder mit Chat GPT ausgetauscht was den ein Shelly ( hier ein shelly 1pm plus gen4 ) den so alles kann.
shelly_influx_control_documentation.pdf
(4.5 KiB) 1-mal heruntergeladen

Und das ist dabei raus gekommen, ich kann hier zb mit dem Wert der Sonneneinstrahlung meiner Wetterstation aktuell mein Licht im Arbeitszimmer ein und ausschalten.
Das ganze abhängig nach dem Wert und ob dieser grösser oder eben kleiner als der Wert ist.
Worin sehe ich den Vorteil ganz klar volle flexibilität das Skript läuft auf dem Shelly und ist somit Eigenständig.

Nachteil an der Geschichte man muss die Werte im Skript ändern, was aber mit der Dokumentation auch im Skript problemlos möglich sein sollte.
Aktuell hab ich es mit meinem Shelly 1 pm plus gen4 getestet es funktioniert, nun werde ich versuchen das ganze auch auf Shelly 2 pm plus zu bekommen, dann kann man zb bei Rollos hier nach der echten Helligkeit die Rollos aufund zu fahren lassen.



*****************************ACHTUNG********ACHTUNG********************ACHTUNG**************ACHTUNG************************************************
Ich weise Ausdrücklich daruaf hin das programierungen mit Skripten funktionieren können und nicht müssen hier ist jeder selbst dafür verantwortlich und muss auch alle Sicherheitsregeln beachten alle meine Angaben sind somit ohne Gewähr und rechtlichkeit verbunden.
Der mit sympatischen Vollmeise
viewtopic.php?p=10570#p10570 USB Zuweisungen.
viewtopic.php?p=41308#p41308 Shelly in Grafana schalten
viewtopic.php?p=32232#p32232

Benutzeravatar
Schwarzermann
Beiträge: 371
Registriert: Sa 9. Okt 2021, 11:16
Wohnort: 87733
Hat sich bedankt: 9 Mal
Danksagung erhalten: 11 Mal

Re: Shelly 1PM Plus (Gen4) Shelly 2 pm (Gen 4) – Steuerung per InfluxDB

Beitrag von Schwarzermann »

Code: Alles auswählen

// ###########################################################
// Shelly 2PM Plus (Gen4) – Switch & Roller Steuerung über InfluxDB
// ###########################################################
//
// Dieses Skript fragt regelmäßig einen Wert aus der InfluxDB ab
// und steuert den Shelly 2PM Plus je nach Modus:
//
// - SWITCH-Modus: Relais 0 und 1 unabhängig mit eigenem Threshold/Mode
// - ROLLER-Modus (Cover): Rollladen mit AUF / ZU / STOP
//
// ###########################################################


// -------------------------------
// 1. Einstellungen
// -------------------------------
let influxHost  = "192.168.178.54";   // InfluxDB-Server
let dbName      = "wunderweather";    // Datenbankname
let measurement = "weather";          // Measurement
let field       = "Sonnenstrahlung";  // Feldname
let interval    = 30000;              // Abfrageintervall (ms)

// Modus auswählen: "switch" oder "roller"
let deviceMode  = "switch";

// Switch-Konfiguration: getrennte Schwellenwerte
let switchConfig = [
  { id: 0, threshold: 200, mode: "greater", lastState: null }, // Relais 0
  { id: 1, threshold: 500, mode: "less",    lastState: null }  // Relais 1
];

// Roller-Konfiguration
let rollerThreshold = 300;
let rollerMode      = "greater";
let lastStateRoller = null;


// -------------------------------
// 2. Steuerfunktionen
// -------------------------------

// SWITCH-Modus: Relais unabhängig steuern
function controlSwitch(value) {
  for (let i = 0; i < switchConfig.length; i++) {
    let cfg = switchConfig[i];
    let newState = (cfg.mode === "greater") ? (value >= cfg.threshold) : (value <= cfg.threshold);

    if (cfg.lastState === null || cfg.lastState !== newState) {
      Shelly.call("Switch.Set", { id: cfg.id, on: newState });
      print("Relais", cfg.id, newState ? "EIN" : "AUS", "(threshold:", cfg.threshold, "mode:", cfg.mode, ")");
      switchConfig[i].lastState = newState;
    } else {
      print("Relais", cfg.id, "keine Änderung – bleibt", newState ? "EIN" : "AUS");
    }
  }
}

// ROLLER-Modus (Cover): AUF, ZU oder STOP
function controlRoller(value) {
  let newState = (rollerMode === "greater") ? (value >= rollerThreshold) : (value <= rollerThreshold);

  if (lastStateRoller === null || newState !== lastStateRoller) {
    if (newState) {
      Shelly.call("Cover.Open", { id: 0 });
      print("Cover fährt AUF");
    } else {
      Shelly.call("Cover.Close", { id: 0 });
      print("Cover fährt ZU");
    }
    lastStateRoller = newState;

  } else {
    Shelly.call("Cover.Stop", { id: 0 });
    print("Cover STOP (keine Änderung)");
  }
}


// -------------------------------
// 3. Hauptfunktion: Influx abfragen
// -------------------------------
function checkSun() {
  let query = "SELECT%20last(%22" + field + "%22)%20FROM%20%22" + measurement + "%22";
  let url   = "http://" + influxHost + ":8086/query?db=" + dbName + "&q=" + query;

  Shelly.call("HTTP.GET", { url: url }, function(result) {
    if (!result || result.code !== 200) {
      print("HTTP Fehler:", result ? result.code : "kein Ergebnis");
      return;
    }

    try {
      let data = JSON.parse(result.body);
      let value = data.results[0].series[0].values[0][1];
      print("Sonnenstrahlung:", value);

      if (deviceMode === "switch") {
        controlSwitch(value);
      } else if (deviceMode === "roller") {
        controlRoller(value);
      } else {
        print("Unbekannter deviceMode:", deviceMode);
      }

    } catch (e) {
      print("Parsing Fehler:", e);
    }
  });
}


// -------------------------------
// 4. Timer starten
// -------------------------------
Timer.set(interval, true, checkSun);
checkSun();
shelly_2pm_plus_influx_control.pdf
(5.14 KiB) 1-mal heruntergeladen
So und auch für die 2 pm gen4 funktioniert das ganze einmal als Roller und einmal als Switch, ich habe beides getestet, und beides funktioniert bei mir .
Viel Spass damit Hannes
*****************************ACHTUNG********ACHTUNG********************ACHTUNG**************ACHTUNG************************************************
Ich weise Ausdrücklich daruaf hin das programierungen mit Skripten funktionieren können und nicht müssen hier ist jeder selbst dafür verantwortlich und muss auch alle Sicherheitsregeln beachten alle meine Angaben sind somit ohne Gewähr und rechtlichkeit verbunden.
Der mit sympatischen Vollmeise
viewtopic.php?p=10570#p10570 USB Zuweisungen.
viewtopic.php?p=41308#p41308 Shelly in Grafana schalten
viewtopic.php?p=32232#p32232

Benutzeravatar
Schwarzermann
Beiträge: 371
Registriert: Sa 9. Okt 2021, 11:16
Wohnort: 87733
Hat sich bedankt: 9 Mal
Danksagung erhalten: 11 Mal

Re: Shelly 1PM Plus (Gen4) – Steuerung per InfluxDB

Beitrag von Schwarzermann »

Code: Alles auswählen

// ###########################################################
// Shelly 1PM Plus (Gen4) – folgt Tor (Shelly 2PM im Cover-Modus)
// mit Sonnenstands-Sperre (nur nachts aktiv)
// ###########################################################
//
// Endgültige Regeln (nur aktiv wenn es dunkel ist!):
// - Bei 20% öffnen              -> Licht EIN
// - Bei 100%                    -> Licht 20s EIN, danach AUS (nur einmal)
// - Wenn Tor von 100% auf <100% fährt (Start Schließen) -> Licht EIN
// - Bei 20% schließen           -> Licht AUS
//
// ###########################################################

// IP-Adresse des Shelly 2PM (Torsteuerung)
let sourceShelly = "192.168.178.195";

// Abfrageintervall (ms)
let interval = 2000;   // alle 2 Sekunden

// Haltezeit wenn Tor komplett offen (in Sekunden)
let holdTime = 20;

// interne Zustände
let lastOn = false;
let holdTimer = null;
let holdActive = false;
let lastPos = null;

// Sonnenauf-/untergang
let sunrise = null;
let sunset = null;

// Hilfsfunktionen
function switchLight(on) {
  Shelly.call("Switch.Set", { id: 0, on: on });
  lastOn = on;
  print("Licht", on ? "EIN" : "AUS");
}

function cancelHoldTimer() {
  if (holdTimer !== null) {
    Timer.clear(holdTimer);
    holdTimer = null;
    print("Hold-Timer abgebrochen");
  }
}

function isNight() {
  if (!sunrise || !sunset) return true; // wenn keine Werte -> sicherheitshalber aktiv
  let now = (new Date()).getTime() / 1000; // aktuelle Zeit in UNIX Sekunden
  return (now < sunrise || now > sunset);
}

function updateSunTimes() {
  Shelly.call("Sys.GetStatus", {}, function(res) {
    if (res && res.sunrise && res.sunset) {
      sunrise = res.sunrise;
      sunset = res.sunset;
      print("Sonnenaufgang:", sunrise, "Sonnenuntergang:", sunset);
    } else {
      print("Keine Sonnenzeiten gefunden – Nacht-Check immer TRUE");
    }
  });
}

// Hauptprüfung
function checkCover() {
  if (!isNight()) {
    // Tagsüber -> Licht sicher ausschalten und überspringen
    if (lastOn) {
      switchLight(false);
      cancelHoldTimer();
      holdActive = false;
    }
    print("Tag erkannt – Lichtsteuerung gesperrt");
    return;
  }

  let url = "http://" + sourceShelly + "/rpc/Cover.GetStatus?id=0";
  Shelly.call("HTTP.GET", { url: url }, function(res) {
    if (!res || res.code !== 200) {
      print("HTTP Fehler:", res ? res.code : "kein Ergebnis");
      return;
    }

    try {
      let data = JSON.parse(res.body);
      let pos = data.current_pos;
      if (typeof pos === "string") pos = parseFloat(pos);
      print("Tor-Position:", pos, "%", "(last:", lastPos, ")");

      // --- Regel 2: Bei 100% -> Licht 20s EIN, danach AUS (nur einmal)
      if (pos >= 100) {
        if (!holdActive) {
          holdActive = true;
          if (!lastOn) {
            switchLight(true);
            print("Licht EIN (Tor 100%, Timer gestartet)");
          }
          cancelHoldTimer();
          holdTimer = Timer.set(holdTime * 1000, false, function() {
            switchLight(false);
            print("Licht AUS (Timer abgelaufen bei 100%)");
          });
        }
        lastPos = pos;
        return;
      }

      // --- Regel 3: Start Schließen von 100% -> Licht EIN
      if (lastPos !== null && lastPos >= 100 && pos < 100) {
        if (!lastOn) {
          switchLight(true);
          print("Licht EIN (Start Schließen von 100% -> <100%)");
        }
        holdActive = false;
        cancelHoldTimer();
      }

      if (lastPos !== null) {
        // --- Regel 1: Bei 20% öffnen -> Crossing von <20% auf >=20%
        if (lastPos < 20 && pos >= 20) {
          if (!lastOn) {
            switchLight(true);
            print("Licht EIN (Öffnen: Crossing über 20%)");
          }
        }

        // --- Regel 4: Bei 20% schließen -> Crossing von >20% auf <=20%
        if (lastPos > 20 && pos <= 20) {
          if (lastOn) {
            switchLight(false);
            print("Licht AUS (Schließen: Crossing unter 20%)");
          }
          holdActive = false;
          cancelHoldTimer();
        }
      }

      lastPos = pos;

    } catch (e) {
      print("Parsing Fehler:", e);
    }
  });
}

// Timer starten
Timer.set(interval, true, checkCover);

// Sonnenauf-/untergang alle 10min aktualisieren
updateSunTimes();
Timer.set(600000, true, updateSunTimes); // 10 min
shelly_1pm_follow_cover_final_doc.pdf
(5.36 KiB) 1-mal heruntergeladen
So für heute glaube reicht es dieses Skript und die Test dazu waren mal richtig Aufwendig, nichts funktioierte in dieser Ausführung wie gewünscht .
Aber nun funktioniert diese Tor Licht Schaltung.
Was kann sie dieses Skript,es wird auf den Shelly 1 pm gen4 aufgespielt wo als Lichtsteuerung dient, er folgt per IP dem 2 pm der als Torsteuerung fungiert Achtung das ganze ist nur im Roller Modus getestet.

Bei mir funktioniert diese Steuerung nun Fehlerfrei, leider funktioniert die Tageslicht Regelung nicht da die so wie es aussieht bein gen 4 über das Skript nicht implementiert ist.
Was Schade ist so könnte man es so programieren das am Tag eben das Licht beim Tor öffnen nicht angeht, was ja wieder um Strom Sparen würde.

Aber das ist jammern auf hohem Niveau.und wieder der Hinweis
*****************************ACHTUNG********ACHTUNG********************ACHTUNG**************ACHTUNG************************************************
Ich weise Ausdrücklich darauf hin das programierungen mit Skripten funktionieren können, und nicht müssen, hier ist jeder selbst dafür verantwortlich und muss auch alle Sicherheitsregeln beachten alle meine Angaben sind somit ohne Gewähr und Rechtlichkeit verbunden.
Der mit sympatischen Vollmeise
viewtopic.php?p=10570#p10570 USB Zuweisungen.
viewtopic.php?p=41308#p41308 Shelly in Grafana schalten
viewtopic.php?p=32232#p32232

Zurück zu „Shelly + Solaranzeige + Steuerung + HomeMatic“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste