Beiträge von eiche

    Nachgereicht:

    Den Status eines Ausgangs per Methode "Switch.GetStatus", siehe auch https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Switch

    Code
    Shelly.call("switch.getstatus", {id:<Id des Ausgangs>},
        function(status) {Out[<Id des Ausgangs>] = status.output;} // nach Doku, Struktur nicht geprüft
    )

    Du kannst ein solches Resultat leicht abfragen per

    Code
    http://<shelly_IP-address>/rpc/switch.getstatus?id=<Id des Ausgangs>

    Der Firefox zeigt das JSON-Resultat gut lesbar an.

    Soeben geprüft - die Struktur stimmt -> obiger Code ( = status.output) muss passen.

    Edit: WICHTIG! Unbedingt beachten.

    Eine Abfrage per RPC bzw. Shelly.call ist immer asynchron, d.h. es ist unbekannt, wann die Methode das Resultat (hier status) liefert. Dann kann einige ms dauern.

    Deshalb muss das Resultat zwecks späterer Verwendung gespeichert werden oder etwas mit dem Eintreffen des Resultats in der callback Funktion ausgeführt werden.

    Notfalls kann man nach dem RPC Aufruf einen Timer für einige ms starten und in dessen callback Funktion das gespeicherte Resultat verarbeiten. Dies ist allerdings nur eine Notlösung und nicht empfehlenswert, wenn es anders gelingt.

    Obiger Code lässt sich auch sehr gut in Funktionen unterbringen und so die Usability beim Coden steigern.

    Edit: Code in checkiAll hinter return leicht verbessert im Sinne der Verständlichkeit. ... und geringfügig gekürzt

    Prinzip:

    Dort, wo eindeutig geschaltet wird lässt du den Status des jeweiligen Ausgangs in einer globalen Struktur speichern.

    Dies gelingt ausschließlich beim toggeln nicht. Dort kannst du den Status per Methode "Switch.GetStatus" abfragen und den Status in der callback-Funktion speichern.

    Alternative: Du lässt mit dem Start des Skripts alle Ausgänge abfragen und speicherst deren Status in der Struktur. Dann geht auch beim toggeln das synchrone Speichern, solange der Shelly fehlerfrei arbeitet und sich keine Störung ereignet.

    Als Struktur bietet sich ein Datenfeld (Array) mit so vielen Elementen an, wie der Shelly Ausgänge besitzt.

    Beispiel: Nicht geprüft, aber vermutlich fehlerfrei und funktionstüchtig.

    Wenn du weitere Infos brauchst, lasse es mich wissen!

    Zum abrunden der Möglichkeiten eine Zusammenstellung, die

    • die Schreibzugriffe in den nichtflüchtigen Speicher auf das notwendige Maß reduziert,
    • sehr einfachen Skriptcode enthält und
    • sehr zuverlässig arbeitet.
    1. Alle Schedule Jobs auflisten lassen, auch und insbesondere solche, die nicht per WebUI konfiguriert wurden. Insbesondere der Web Browser Firefox listet diese Jobs (JSON-Format) übersichtlich auf.
      http://<shelly_ip-address>/rpc/schedule.list
    2. Das einfache Skript:
      Es beinhaltet
      1. die globale Variable Status zur Speicherung des Status des digitalen Eingangs für synchronen Zugriff,
      2. das Eventhandling zu Änderungen des digitalen Eingangssignals,
      3. die Funktion switch_conditional() zum bedingten Einschalten des Ausgangs.

    Um dieses Skript nutzen zu können, sind Möglichkeiten von Schedule Jobs zu nutzen, die nicht in der WebUI zur Verfügung gestellt sind.

    Ein geeigneter Schedule Job kann wie folgt angelegt werden:

    Code
    http://<shelly_ip-address>/rpc/schedule.create?enable=true&timespec="0 15 17 * * *"&calls=[{"method":"script.eval","params":{"id":1,"code":"switch_conditional()"}}]

    Dieser Job ruft täglich um 17:15 Uhr die Funktion switch_conditional() im Skript mit der Id 1 auf. enable=true kann auch weggelassen werden, weil dies die default Einstellung ist.

    Die Syntax zu timespec ist hier zu finden: https://github.com/mongoose-os-libs/cron

    Ich setzte für weiteres voraus, dass dieser Schedule Job die Id 1 besitzt.

    Wenn die Schaltzeit geändert werden soll, kann die Methode Schedule.Update verwendet werden:

    Code
    http://<shelly_ip-address>/rpc/schedule.update?id=1&timespec="0 30 12 * * *"

    Dies ändert den Schedule Job mit der Id 1 so, dass täglich um 12:30 Uhr die Funktion switch_conditional() aufgerufen wird.

    Man kann einen Schedule Job leicht Wochentags spezifisch einrichten. Soll bspw. der obige Schedule Job (Id 1) nur montags und mittwochs aktiv sein, ist folgendes Update zielführend:

    Code
    http://<shelly_ip-address>/rpc/schedule.update?id=1&timespec="0 30 12 * * Mon,Wed"

    Auch kann sunrise und sunset in timespec verwendet werden.

    Da diese URLs etwas kryptisch sind, kann die usability per passend zusammengestellter Website unterstützt werden.

    In diese können die variierbaren Parameter für timespec per Eingabefelder eingegeben oder per Auswahllisten selektiert werden.

    Eine solche Website kann

    • lokal auf dem Benutzer-Endgerät (Notebook, Tablet, Smartphone) oder
    • im world wide web platziert werden.

    Ich betone, dass dies eine Implementationsvariante ist, welche nicht von der derzeitigen WebUI-Konfiguration unterstützt wird, aber technische Vorteile gegenüber der interessanten Lösung von ostfriese besitzt.

    Dessen Variante hat den Vorteil, dass die per WebUI konfigurierbaren Schedule Jobs (höhere usability) genutzt werden können. Es sind aber dieselben Schedule Jobs wie die per RPC (s.o.) eingerichteten. Diese Konfiguration ist nur eingeschränkt und nutzt nicht alle Möglichkeiten des in der Firmware enthaltenen Betriebssystems.

    Edit:

    Skript für den Zweck des TE geringfügig korrigiert.

    TomyH

    Mein Workaround per HTTPServer.registerEndpoint() testete ich vorhin erstmalig.

    Auch bin ich nicht sicher, ob die Benutzer-Konfiguration von Schedule Jobs die Nutzung zulässt.

    Es gibt ein besseres Verfahren zum eintragen von Schedule Jobs - mit der Methode "Schedule.Create" bzw. "Schedule.Update" und im Code die Nutzung von "Script.Eval".

    Dies gibt die derzeitige WebUI aber nicht her. Evtl. ließe sich mein Workaround per Cloud nutzen, ich finde aber eine Cloud-Nutzung für solche Zwecke unpassend.

    Vielleicht wird Allterco die Konfiguration von Schedules offener gestalten. Spätestens dann wären die Schedules noch deutlich flexibler konfigurierbar - aber nicht für DAUs geeignet.

    Man kann per Webseite eine solche Schedule Konfiguration sehr flexibel gestalten. Dies habe ich bereits in einem Projekt erprobt.

    Ob ich für dich eine solche Webseite erstellen würde, hängt auch davon ab, was du wünschst.

    Auch bin ich nicht sicher

    Noch nicht ausgereift, aber prinzipiell funktionstüchtig:

    Hier fehlt noch die response ...

    Per http://<ip-address>/script/<script-id>/switch_conditional lässt sich die Funktion des Einschaltens, wenn dig. Input true ist, bereits nutzen.

    Diesen URL könntest du in deine Schedule Jobs eintragen, ...

    Vorteil:

    Im nichtflüchtigen Speicher (NVS) finden seltener Schreibvorgänge statt - immer dann, wenn du einen Zeitplan änderst.

    Edit:

    Du kannst statt "switch_conditional" jeden sonstigen Text einsetzen, welcher dir zusagt.

    Edit 1:

    Beispiel-URL: "http://127.0.0.1/script/1/switch_conditional"

    Nicht getestet, sollte logischerweise aber funktionieren, wenn ein solcher URL in einem Schedule Job konfiguriert werden kann.

    Deine Idee gefällt mir.

    Kleiner Nachteil:

    Jedes mal, wenn der dig. Input sich ändert, wird im NVS - hier den schedule jobs - geändert. Das ergibt relativ viele Änderungen.

    Das lässt sich selbstverständlich vertreten.

    In diesem Zusammenhang habe ich mir mal HTTPServer.registerEndpoint() angeschaut, ist aber noch schwach dokumentiert.

    Evtl. ließe sich hiermit ein Workaround für eine nicht konfigurierbare Methode Script.Eval implementieren.

    Bisher war ich noch nicht erfolgreich damit.

    TomyH

    Codebeispiel, nicht komplett:

    Nun bleibt noch die Frage, wie du das Skript mit einem Schedule Job verbinden kannst.

    Es gibt dafür die Methode "script.eval", diese wird aber derzeit wohl nicht in der Shelly Konfiguration angeboten.

    Man kann aber sehr gut abseits der App, der WebUI und der Cloud per RPC Schedule Jobs anlegen und/oder ändern.

    Ich schaue mal in der Konfiguration nach ...

    TomyH

    1. Zum Hit URL: Wenn die Nachricht an deselben Shelly gelingen soll, musst du dafür localhost verwenden, also 127.0.0.1
    2. Hier die Anfangsversion für den Eventhandler zur Erfassung des digitalen Eingangs (input:100)

    Edit:

    Nun gibt es prinzipiell zwei Implementationen.

    1. Du verwendest den Eventhandler (s.o.) und speicherst immer den aktuellen Zustand von e.info.state in einer globalen Variablen.
      Wenn bedingt geschaltet werden soll, fragst du dafür den Wert dieser Variablen ab.
    2. Du fragst an passender Stelle den Status von input:100 ab und lässt bedingt schalten.

    Ich favorisiere eindeutig Variante 1. Code kann bei Bedarf folgen ...

    Edit 1:

    Variante 2 ist aufwändiger, weil hierfür ein RPC Aufruf erforderlich ist und diese Aufrufe asynchron ablaufen. D.h. dass dir der Status nicht unmittelbar zur Verfügung steht.

    TomyH

    Ich nutze einen Plus 1 mit AddOn, aber mit einem DHT22 Sensor und keinem digitalen Input.

    Meine Abfrage liefert ebenfalls

    Code
    {"id":0,"state":false}

    was nicht verwunderlich ist. Somit vermute ich, dass dein Anschluss nicht korrekt ist oder dein Schalter nicht arbeitet.

    Prüfe bitte mal mit einem Durchgangsprüfer (Ohmmeter), ob dein Schalter wirklich schaltet!

    Woll-E

    zwecks Entwirrung folgender Kommentar meinerseits:

    Deine Klemmenbezeichnungen 0 und 1 sind irreführend, sie sollten I (Input) und O (Output) lauten.

    Der TE besitzt afaik keinen separaten Druckschalter.

    DarkSoul

    Ich als "Skript Junkie" lege Wert auf hohe Funktionssicherheit. 8o