Beiträge von towiat

    Ich habe das Script umformuliert, weil deine Version mit hoher Wahrscheinlichkeit nicht das tut, was du erwartest.

    Das Problem ist (und darüber stolpern viele Neulinge), dass JavaScript nicht wartet, während du die Abfragen an den Pro2 schickst - statt dessen läuft das Script in der Zwischenzeit einfach weiter. Für dein Script bedeutet das:

    JavaScript
    function startControl() {
      // Setze eine Funktion zur regelmäßigen Überprüfung alle 10 Sekunden
      Timer.set(6000, true, function() {
        updateSwitchStatus(); // Frage Switch 0 vom Pro2 ab
        updateSwitchStatus2(); // Frage Switch 1 from Pro2 ab
        // Die folgenden beiden Zeilen werden ausgeführt, bevor der PRO2 geantwortet hat
        print("Das Netz wurde", switch_status ? "auf Netzbetrieb" : "auf Akkubetrieb", "umgeschaltet");
        setRelayState(switch_status && switch_status2); // Aktualisiere den gewünschten Relaiszustand
      });
    }

    Das bedeutet, dass dein Script nicht auf den aktuellen Stand des Pro2 reagiert, sondern auf den Stand vom letzten Durchlauf (also sechs Sekunden früher).

    Wenn du das vermeiden willst, musst du die Statusabfrage im Callback der Abfrage verarbeiten (was die Hauptänderung in meiner geposteten Version ist). Wenn dich diese Verzögerung nicht stört, kannst du natürlich auch damit leben...

    Der folgende Code sollte funktionieren und (auf etwas einfachere Art) exakt das tun, was deine derzeitige Version macht (machen sollte).

    Allerdings sagst du, dass du den Pro 1 einschalten willst, wenn beide INPUTS des Pro2 AUS sind - derzeit fragst du aber ab, ob die OUTPUTS EIN sind. Ist das Absicht oder missverstehe ich da etwas?

    Unter der Annahme, dass du mit Timer.set() arbeitest:

    intern nutzen die shellys zur zeitbasierten Ausführung einen cron deamon.

    Für Timer stimmt das nicht - die arbeiten mit der Uptime des Gerätes. Das geht auch implizit aus der Dokumentation der (in FW 1.5.x neuen) Timer.getInfo() Methode hervor:

    Der Inhalt kann nicht angezeigt werden, da Sie keine Berechtigung haben, diesen Inhalt zu sehen.

    Das macht ja auch Sinn, weil Timer damit auch auf Geräten funktionieren, die mangels Internetzugang keine Zeitsynchronisation durchführen können.

    Meine Vermutung ist, dass die interne Uhr des Shellys zu schnell läuft und daher ein Drift zwischen Uptime und Realzeit auftritt. Das könntest du überprüfen, indem du z. B. die Differenz in der Uptime innerhalb von exakt 24 Stunden misst.

    Wenn diese Vermutung zutrifft, wäre die Lösung - wie von thgoebel vorgeschlagen - ein Schedule, weil der natürlich an der Systemzeit hängt.

    Hallo Coloschni ,

    Eine Berechnung nach dem Durchschnittspreis wird vom Script nicht unterstützt.

    Du könntest ein ähnliches Resultat erzielen, indem du das Script so aufsetzt, dass es nur die zwölf günstigsten Stunden des Tages schaltet:

    JavaScript
    let switchOnDuration = 12; // minimum 1, maximum 24
    let timeWindowStartHour = 0; // minimum 0, maximum 23
    let timeWindowEndHour = 0; // minimum 0, maximum 23
    let blockMode = false; // set calculation mode
    let priceLimit = Infinity; // in cent/kWh

    Das liefert natürlich andere Resultate als eine Durchschnittspreisberechnung, bei der die Anzahl der geschalteten Stunden abhängig von der Preisstruktur des Tages schwanken würde - aber vielleicht reicht es ja für deine Zwecke.

    Es kann passieren, dass ein Script die Shelly-CPU derartig auslastet, dass sie nicht mehr antworten kann. Das könnte z. B. durch eine Endlosschleife im Script ausgelöst werden (die hier offensichtlich nicht vorliegt). Und wenn das Script auf Autostart steht, geht es nach einem Reboot sofort wieder los.

    Keine Ahnung warum der Shelly bei diesem Script so rumzickt, aber um ihn wieder ansprechbar zu machen könntest du versuchen, das Script mittels RPC zu stoppen.

    Dazu müsstest du den RPC http://192.168.1.126/rpc/Script.Stop?id=1 (unter der Annahme, dass das Script die ID 1 hat) via Browser/curl/iwr so oft aufrufen, bis er durchkommt - das kann durchaus ein paar Versuche benötigen...

    Um einen Schedule auf demselben Gerät anzulegen, würde ich übrigens nicht über HTTP.GET gehen, sondern den RPC direkt aufrufen - das würde dann so aussehen:

    JavaScript
    Shelly.call("Schedule.Create", {
     enable: true,
     timespec: "0 16 3 * * 0",
     calls: [{ method: "Cover.Open", params: { id: 0 } }],
    });

    Der Hinweis von tvbshell für die CONFIG ist völlig richtig - jetzt musst du nur noch die geschweiften Klammern beim Call weglassen. Statt Shelly.call("Switch.Set", {CONFIG.Switch1_On}); muss es Shelly.call("Switch.Set", CONFIG.Switch1_On); sein.

    The property for the content type in the HTTP.POST RPC is named content_type, not Content-Type - this could already be the solution for this:

    JavaScript
    let parms = {
          "url": "http://<INTERNAL_IP>/php/controls.php",
          "content_type":"application/x-www-form-urlencoded",
          "body": body
        };

    Du kannst keine Werte aus dem Shelly.call ins Hauptprogramm zurückgeben. Du kannst allerdings die Variablen im Hauptprogramm anlegen und sie dann aus dem Shelly.call heraus updaten:

    In vielen Fällen ist das allerdings nicht das, was du willst.

    Die Frage ist: soll direkt nach der Abfrage der Werte eine Aktion mit diesen Werten ausgeführt werden?

    Wenn die Antwort darauf "ja" ist, solltest du die entsprechende Logik direkt in der Funktion ausführen und nicht im Hauptteil des Scriptes. Wenn du beschreibst, was du nach der Abfrage der Werte machen willst, können wir das noch genauer diskutieren.

    Du könntest dem Benutzer einen Link geben, der die Autorisierung mit der URL in der Form http://admin:password@x.x.x.x/script/x/Dauerbetrieb mitschickt - damit wäre das Passwort natürlich dem Benutzer gegenüber exponiert.

    Ansonsten fiele mir nur ein Zwischenschritt ein - z. B. ein minimaler Webserver, der das HTML ausliefert und im Hintergrund dann den autorisierten Aufruf an den Shelly schickt...

    Grundsätzlich sollte das funktionieren - Fehler -104 ist ein Timeout und deutet stark darauf hin, dass die IP-Adresse nicht korrekt ist.

    Es ist aber generell keine gute Praxis, das eigene Gerät über seine Netzwerkadresse abzufragen. Es gibt zwei Möglichkeiten, wie du das anders lösen kannst:

    1. Könntest du einfach die IP-Adresse 127.0.0.1 verwenden - das ist die Loopbackadresse, die immer auf das eigene Gerät verweist:

    JavaScript
    Shelly.call(
     "HTTP.GET",
     {
       url: "http://127.0.0.1/rpc/Shelly.GetStatus",
     },
     function (result, error) {
       print(result);
       print(error);
     },
    );

    2. Könntest du GetStatus direkt und ohne Umweg über HTTP.GET aufrufen:

    JavaScript
    Shelly.call("Shelly.GetStatus", {}, function (result, error) {
     print(result);
     print(error);
    });

    Diese Variante hätte den Vorteil, dass in result schon ein fertiges JSON-Objekt steckt und du nicht JSON.Parse() verwenden musst, um die Antwort in ein JSON zu konvertieren.

    Beide Möglichkeiten sollten dich ans Ziel bringen...