Beiträge von eiche

VPN/Proxy erkannt

Es scheint, dass Sie einen VPN- oder Proxy-Dienst verwenden. Bitte beachten Sie, dass die Nutzung eines solchen Dienstes die Funktionalität dieser Webseite einschränken kann.

    Uhrsteuerung per Shelly 2. Generation mit Schedule Jobs und Skript

    Auf ausdrücklichen Wunsch von thgoebel habe ich mich um eine nutzbare Implementation bemüht. horkatz könnte sie auch interessieren.

    Die erste auslieferbare Testfassung ist fertig.

    Ich habe sie getestet mit einem Shelly Plus 1, MQTT Nachrichten, Node-RED zwecks Speicherung in einer Influx Zeitreihendatenbank und Grafana zur Visualisierung.

    Zusätzlich habe ich per Node-RED einen Zähler für die Schaltpulse eingerichtet. Per Inject Node wird der Zählerstand auf 0 gesetzt und der Zeitstempel zu diesem Zeitpunkt gespeichert.

    So kann jederzeit die zur vergangenen Zeit gezählten Pulse erfasst und ausgewertet werden.

    Mein letzter Test zeigte, dass auch nach einem (simulierten) Stromausfall schließlich alle ausgefallenen Pulse nachträglich erzeugt wurden.

    Ich kann nicht ganz ausschließen, dass nach einem Stromausfall evtl. ein Puls zu wenig erzeugt wird, um die Uhr auf die richtige Zeit zu bringen.

    Dies sollte mit einer Uhr, die ich nicht habe, getestet werden.

    Für den praktischen Einsatz ist eine Funktion pulse(duration) so anzupassen, dass die physikalisch geeigneten Pulse erzeugt werden, bspw. mit zwei Ausgängen.

    Das erforderliche Timing der Pulse ist relativ leicht per zwei anzulegender Schedule Jobs einzustellen.

    Die von mir angelegten Schedule Jobs für Testzwecke sind folgende:

    Code
    {"jobs":[
    {"id":1,"enable":true,"timespec":"0 * * * * *","calls":[{"method":"Script.Eval","params":{"id":1,"code":"pulse(5000)"}}]},
    {"id":2,"enable":false,"timespec":"*/5 * * * * *","calls":[{"method":"Script.Eval","params":{"id":1,"code":"pulse(1000)"}}]}
    ]}

    Die beiden Jobs unterscheiden sich im wesentlichen in der Frequenz.

    Job 1 ruft minütlich die Funktion pulse(5000) auf. Es wird somit alle 60 s ein Puls mit einer Dauer von 5000 ms = 5 s erzeugt.

    Job 2 ruft alle 5 s die Funktion pulse(1000) auf, wodurch alle 5 s ein Puls mit einer Dauer von 1000 ms = 1 s erzeugt wird.

    Job 1 ist für den regulären Betrieb zuständig, Job 2 für die Nachlieferung von per Stromausfall nicht gesendeten Pulse, um die Uhr auf die richtige Zeit zu stellen.

    Das Skript aktiviert immer nur einen dieser beiden Jobs, sie sind also nie zugleich aktiv.

    Nun das Skript:

    Es enthält neben debug Ausgaben (print), welche per debug=true aktiviert bzw. debug=false deaktiviert werden, noch zusätzliche Ausgaben, die später entfernt werden können.

    Sie dienen der Beobachtung insbesondere der Pulserzeugung nach Stromausfall.

    Um einen Stromausfall zu simulieren, genügt es, das Skript anzuhalten und es nach der simulierten Ausfalldauer zu starten.

    Selbstverständlich lässt sich der Code auch ein Stück weit objektorientiert verfassen.

    Da ich zu diesem Projekt keine einschlägige Vorerfahrung hatte, habe ich schlicht Wert auf dessen Funktionalität und Funktionssicherheit gelegt.

    Eine Grafana Zeitgrafik zur Pulserzeugung:

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

    Links sind die in dichter Folge erzeugten nach einem Stromausfall gelieferten Uhrstell-Pulse zu sehen, rechts die regulären minütlichen Pulse.

    Bei konkreten Fragen zum Skript und den Schedule Jobs gebe ich gerne Auskunft. Ob ich die Muße finden werde, zum Einsatz eine Anleitung zu verfassen, weiß ich noch nicht.

    Das wird auch vom Kreis der Interessenten abhängen.

    Nun hoffe ich, dass diese Implementation irgendwo ihre Anwendung findet.

    Gruß aus Rheinland-Pfalz

    Es ist spannend.

    Der Shelly schickt derzeit alle 5s missing pulses raus. Es waren 89, da ich zwischenzeitlich am nicht laufenden Skript arbeitete.

    Nun werde ich sehen, ob er irgendwann in den regulären Betrieb übergeht.

    Nach meinen Überlegungen sollten dann erneut Pulse fehlen, aber erheblich weniger - und wieder missing pulses ausgeben.

    Irgendwann sollte dann die Synchronisation in den regulären Betrieb übergehen.

    Ich bleibe "am Ball". Ich bin auch gespannt, ob meine Entwicklung jemand einsetzen wird.

    Ich habe ja keine entsprechende Uhr.

    Ok, solche hardwarenahen Einzelheiten wären ohnehin später noch zu implementieren.

    Dazu muss dann nur noch eine Funktion angepasst werden, welche die Ausgänge steuert.

    Dazu kann ich mir später Gedanken machen.

    Zunächst geht es mir darum, festzustellen, wie viele Pulse fehlen, um die Uhr erneut die aktuelle Zeit anzeigen zu lassen.

    Das ist bereits fertig. Nun fehlt aber noch das Senden der fehlenden Pulse, und dies, ohne von den regulären Minutenpulse dabei gestört zu werden - nicht ganz trivial.

    Und schließlich muss danach wieder der reguläre Betrieb laufen.

    Werter thgoebel ;)

    Das kann ich gerne tun.

    Momentan bin ich noch damit beschäftigt, "missing pulses" zu implementieren. Dies sind zusätzliche Pulse, welche beim zwischenzeitlichen Stromausfall zum stellen der Uhr nachzuliefern sind.

    Mein erster Versuch mit einem Timer, der sich selbst beendet, gelang fast, aber leider nur fast.

    Grund: Das Timer Handle liegt offenbar erst dann vor, wenn der Timer.set Aufruf "durch" ist. Intern wird aber zum beenden des Timers dieses Handle benötigt.

    Hier kommt die sprichwörtliche Katze zu spät, um sich in den Schwanz zu beißen - bzw. den Schwanz abzubeißen.

    Nun will ich statt des Timers, mal wieder, einen zusätzlichen schedule job einsetzen. Ich arbeite gerade daran - bin selbst gespannt.

    Cu later

    Kurze Rückmeldung zur bisherigen Problemlösung

    Ich habe das Skript umgeschrieben und bin damit zufrieden.

    Auch nehme ich die Vermutung (vorläufig) zurück, dass die Firmware ursächlich für das Problem ist.

    Jedenfalls lag die Stelle des Auftretens irgendwo im event handling.

    Mein Skript nutzt nun den ursprünglichen schedule job und zwecks Erfassung des Schaltens das event handling.

    Ich danke Devil und Seven of Nine für ihre Beteiligungen an diesem Thread.

    Bei Interesse an diesem kleinen Projekt stelle ich meine Lösung gerne zur Verfügung.

    Es soll dem Steuern von älteren elektrischen Nebenuhren dienen können.

    Mir stellt sich die Firmware 0.14.1 als instabil dar.

    Warum?

    Folgende Konstellation:

    Schedule Jobs:

    Code
    {"jobs":[
    {"id":1,"enable":false,"timespec":"0 * * * * *","calls":[{"method":"Script.Eval","params":{"id":1,"code":"clockTrigger(5000)"}}]},
    {"id":2,"enable":true,"timespec":"0 * * * * *","calls":[{"method":"Switch.Set","params":{"id":0,"on":true}}]}
    ], "rev":6}

    Ohne ein gestartetes Skript tut der Shelly seinen Job gemäß seines Schedule Job 2. Auch das konfigurierte automatische Abschalten nach 5s funktioniert.

    Dann sperre ich wieder das automatische Abschalten und starte das folgende Skript:

    Nun ereignen sich in kürzeren Abständen, also deutlich unter 1 Minute Ein- und Ausschaltvorgänge - mehrmals hintereinander.

    Ein und sofort danach wieder aus.

    Die Ausgaben per print habe ich zur Sicherheit auskommentiert.

    Zuvor zeigten sie die eintreffenden zu erwartenden Schaltereignisse.

    Ich werde erneut andere typgleiche Shellies testen - mit unterschiedlichen Firmware Versionen.

    Edit:

    Das obige Skript ist nicht gut zusammengestellt. Der Timer sollte Event selektiv gestartet werden.

    Allerdings sah ich ausschließlich die Schaltevents ...

    Ich arbeite weiter daran.

    So, ich habe soeben einen zweiten Schedule Job angelegt mit:

    Code
    http://<ip-address>/rpc/Schedule.Create?enable=true&timespec="0 * * * * *"&calls=[{"method":"Switch.Set","params":{"id":0,"on":true}}]

    Und prompt ereignet sich beim Einschalten der bereits geschilderte Skriptabbruch mit derselben Fehlermeldung.

    Ein Eventhandling zum Einschalten habe ich noch nicht eingebaut.

    Da bleibt mir nur noch der Schluss, dass hier ein Fehler in der Firmware vorliegt.

    Mich würde nun noch interessieren, welche Konstellation dazu führt.

    Ich habe ein anderes Projekt vorläufig erfolgreich abgeschlossen, welches einen Shelly Plus 1 mit Sensor Addon und einem Ventilantrieb als autarken Thermostat betreibt - ohne irgendeinen Skriptabbruch.

    Und jenes Projekt ist deutlich komplexer als dieses hier mit dem von mir oben beschriebenen Skript.

    Inzwischen habe ich den ersten Schedule Job disabled. Trotzdem derselbe Fehler.

    Ich werde nun sukzessive und kleinschrittig ein neues Skript aufbauen, um zu sehen, wann sich dieser Fehler einstellt.

    Ich hatte übrigens auch mal den Shelly gewechselt, also einen typgleichen eingesetzt.

    Ich werde den Schedule Job so ändern, dass er die Methode Switch.Set mit {"id":0, "on":true} aufruft und im Eventhandler die Rückmeldung des Schaltens nutzen, um den Puls zu stoppen.

    Meine bisherige Lösung gefällt mir aber besser, weil man so die Pulsdauer parametrieren kann, ohne das Skript zu manipulieren.

    Wenn dies gelingt, kann ich ja noch Kommunikation einbauen, damit der Anwender die Pulsdauer darüber konfigurieren kann.

    Das hatte ich zunächst so. Ich neige durchaus auch zu anonymen Funktionen.

    Dann las ich während meiner Fehlersuche in den Dokus, dass es in der Tiefe von anonymen Funktionen Beschränkungen gibt und lagerte sie in benannte Funktionen aus.

    Leider half auch das nicht.

    Außerdem lasse ich das Skript laufen, ohne zu schalten. So läuft es seit Stunden ohne Unterbrechung durch, wie ich in den Datenbankaufzeichnungen sehen kann.

    Mit den Callbacks von Shelly.call hatte ich dasselbe Problem.

    Ja, mit großen Anfangsbuchstaben hatte ich begonnen.

    Meiner Erfahrung nach sind die Methodennamen case unsensitiv.

    In anderen Projekten funktioniert das Schalten fehlerfrei auch mit Kleinschreibung.

    Btw, der Shelly schaltet mitunter (oder immer?) noch, bevor das Skript abbricht.

    Somit ist es kaum möglich, dass der Methodenaufruf fehlerhaft ist.

    Tja ...

    Danke für die Reaktionen.

    Devil

    Das große S hat leider keine Besserung gebracht.

    Seven of Nine

    Oh ja, klar - mit http:// - ich war zu diesem Zeitpunkt schon etwas abgearbeitet.

    Nun, mit Switch.toggle hatte ich bereits gearbeitet - leider das selbe Problem wie mit Switch.set.

    Merkwürdig ist auch, dass beide Schaltaufrufe in einem anderen Projekt keinerlei Probleme bereiten. So etwas gehört ja auch zu den absoluten basics.

    Ich versuchte es soeben mit http.get und komplettem URL. Leider genau dasselbe Problem, Skriptabbruch mit obiger Fehlermeldung.

    Es sieht so aus, als ob der RPC-Methodenaufruf ein Problem darstellt, unabhängig vom Weg dorthin.

    Hallo,

    Ich entwickle eine Anwendung für Shellies der zweiten Generation mit per Scheduling ausgelöstem Schalten.

    device: shelly plus 1

    firmware: 0.14.1, alternativ getestet mit 0.13.0

    Mein schedule job:

    Code
    {"id":1,"enable":true,"timespec":"0 * * * * *","calls":[{"method":"Script.Eval","params":{"id":1,"code":"clockTrigger(5000)"}}]}

    Dieser bewirkt zu jeder vollen Minute den Aufruf der Funktion clockTrigger mit 5000 (ms) als Parameter, welche das unten stehenden Skript enthält.

    Und hier mein bisheriges Skript:

    Der Abbruch des Skript ereignet sich in der Funktion pulseOut, wenn geschaltet wird - Zeilen 31 und Zeilen 37.

    Das Skript arbeitet einwandfrei, wenn die Schaltmethodenaufrufe auskommentiert sind.

    Die Methoden http.get habe ich nur zwecks Fehlersuche eingesetzt. Sie sind also nur alternativ zu switch.set bzw. switch.toggle zu verstehen.

    Wenn ich die Schaltmethoden einbaue, bspw. per switch.set, gibt es den Skriptabbruch mit der Fehlermeldung:

    "onEvent callback error: type error"

    Ich kann keinen Typfehler finden. Dieser müsste sich in den Shelly.call Aufrufen zum schalten befinden, da ohne diese Aufrufe das Skript fehlerfrei abgearbeitet wird.

    Manchmal erscheint diese Meldung beim Einschalten, spätestens nach dem Ausschalten - verlässlich reproduzierbar.

    Mir fällt nichts mehr ein, was ich noch tun kann, um diesen Fehler zu beseitigen oder mich der Ursache zu nähern.

    horkatz

    Wenn ich es richtig verstand, dann werden die Nebenuhren ohne eigenes "Zeitgerät" von der Masteruhr gesteuert.

    Hier eine SPS einzusetzen, halte ich für sehr übertrieben - um es vorsichtig auszudrücken. ;)

    Mit jeweils einem Shelly könnten die Nebenuhren auch relativ autonom betrieben werden.

    Ein Shelly kann leicht, auch ohne Programmierung (s.a. Projekt von Th. Goebel) sehr präzise jede Minute - oder auch bspw. jede Sekunde - einen Schaltvorgang auslösen/durchführen.

    Zur Umstellung zwischen "Sommerzeit" und physikalischer Zeit kann ein Skript erstellt werden - von wem auch immer. ;)

    Dieses Skript kann zu bekannten Umstellzeiten die Nebenuhr vorstellen oder für eine Stunde anhalten.

    Ob diese Umstellzeiten gleich bleiben, weiß ich derzeit nicht, vermute es aber.

    Wie du die Zeitsynchronisation per Zeitserver realisierst, bleibt dir überlassen.

    Prinzipiell wäre es auch möglich, hierfür die Impulse der Masteruhr einzusetzen, was jedoch ziemlich retrospektiv wäre.

    Um die Dauer eines Stromausfalls zu erfassen - und die Nebenuhr nachzustellen, wäre in den Shellies immer der letzte Unix-Zeitstempel zu einem Nebenuhr-Schaltimpuls im nichtflüchtigen Speicher (nvs = non volatile storage) abzulegen. Auch dies wäre prinzipiell noch ohne Skriptprogrammierung möglich. Hierfür sind aber Kenntnisse zu den RPC (remote procedure calls) erforderlich, welche von der Firmware bereitgestellt sind.

    In der Firmware von Allterco wird statt nvs die Bezeichnung KVS verwendet - key value storage. key value bezeichnet allerdings eine Datenstruktur, auf deren Elemente (Werte) per key zugegriffen wird.

    Nachteil: Der nvs verträgt deutlich weniger Schreibzugriffe als der flüchtige Speicher, auch als RAM geläufig.

    Dieser kleine Nachteil ist aber vermutlich nicht entscheidend.

    Jedenfalls kann der Shelly per Skript zu jedem erfassten Unix-Zeitstempel die ausgefallenen Minutentakte an die Nebenuhr ermitteln und diese quasi nachreichen.

    Versuch eines relativ simplen Lösungsentwurfs:

    Lichtschranke, durch welche das Pendel "läuft" oder Reflektionslichtschranke.

    Die Impulse (von Lichtschranke) werden im Shelly (oder anderem Mikrocontroller) gezählt.

    Der Zählerstand wird mit der vergangenen Zeit verglichen und gelegentlich bzw. bei zu großer Abweichung das Pendel temporär angehalten.

    Für diesen Zweck sollte die Uhr also ein klein wenig schneller laufen.

    Ich möchte das Prinzip "inkrementale Regelung" nennen - ohne Kenntnis davon, ob es so etwas im Sprachgebrauch gibt. ;)

    @dekat win

    Vielen Dank für deine Reaktion. Stimmt, ich könnte versuchen, das selbst zu ermitteln. Allerdings könnte ich so nur die Phänomene erkennen und müsste interpretieren.

    Ok, das ist wohl ein etwas ungewöhnliches Thema.

    Mein Projekt:

    Nutzen eines Shelly Plus 1 mit Addon und DHT 22 zwecks autarker, lokaler Temperaturregelung (Heizkörper/Raum).

    Hierfür werde ich KVS und insbesondere den Scheduler nutzen. Letzterer kann ja mehr als nur Wochenpläne, auch wenn die für Anwender genügen.

    Ich entwickle daran, bis schon soweit fertig - außer Komfortfunktionen.

    Der wichtige Nebeneffekt daran ist, dass ich während der Implementation und Verbesserungen die Firmware genauer kennenlernen muss(te). ;)

    Mir gefällt sie immer besser. Ich möchte selbstverständlich auch eine sehr hohe Funktionssicherheit erreichen.

    Dann können solche Shellies locker die TRV ablösen.

    Meine Projektlösung wird stabiler arbeiten, immer erreichbar sein, zügig reagieren und erweiterbar sein.

    Ok, ein angepasstes Webinterface fehlt. Hierfür habe ich ein Node-RED Dashboard erstellt.

    Ob es möglich ist, per Skript ein solches Webinterface zu implementieren, weiß ich derzeit nicht.

    Btw, ich nutze teilweise noch Shellies der 1. Gen. mit Addon. Die Regelung findet per Node-RED Flows statt. Das ist nicht ganz gut, weil die Autarkie der Shellies fehlt.