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.

    Du kannst selbstverständlich anwendungsorientiert protokollieren lassen.

    Ich setze mal voraus, dass kein übergeordnetes System zum Zuge kommt und evtl. das Protokoll viele Zeilen umfassen können soll.

    Dann bietet sich das Speichern in einer Datei an, ich nenne sie mal "log". log wird wie ein Skript genutzt, obwohl sie kein Skript ist.

    Dort passen aber relativ viele Zeilen hinein.

    Ich habe etwas ähnliches für einen Freund erstellt.

    Wenn es dich interessiert, ich habe die Beschreibung veröffentlicht, allerdings (noch) ohne das Skript selbst.

    Du wirst vermutlich an die Ausgangsklemmen herankommen. Bei 12V Versorgung kannst du zumindest alle Klemmen und angelötete, nach außen führende Leitungen testen.

    Mit einem Multimeter könntest du bei Änderung der Sensorbefeuchtung die verschiedenen Spannungen messen. Falls sich dabei eine Spannung verändert, hast du zumindest eine Ausgangsklemme erwischt. Dann ist noch zu prüfen, wie sich diese Spannung verändert.

    Ändert sie sich sprunghaft von niedrig zu hoch, handelt es sich höchstwahrscheinlich um ein binäres Signal.

    Zusätzlich kannst du mit der Sensorbefeuchtung in möglichst kleinen Schritten experimentieren. Nimmt dann diese Spannung zwischenwerte ein, ist sie analog.

    Mir gefällt dein Skript. Wegen des gut strukturierten Codes will ich nicht meckern. :thumbup:

    Trotzdem folgende Dinge, falls es dich interessiert. Wenn nicht, ignoriere meine Hinweise einfach! ;)

    1. user defined parameter ist rein optional. An solchen null zu übergeben und ud nicht zu nutzen, ist absolut überflüssig.
    2. In JavaScript gibt es den Vergleichsoperator, der auf Wert und Typ prüft (===). Im Zweifelsfall könnte dies zielführend sein.
      Der entsprechende ungleich Operator ist !==.
      Dies kann eine Rolle spielen, da diese Sprache nicht typenstreng ist.
    3. Zum schalten muss nicht vorher geprüft werden, ob der Ausgang bereits den angestrebten Zustand hat. Du erreichts damit allenfalls, dass laufzeitabhängig ein ggf. überflüssiger Methodenaufruf nicht stattfindet.

    status = isTurnedOn();

    // print ("turnOff called, status=" + status);

    if (true == status) {

    Hier genügt bspw.

    if(isTurnedOn()) {

    allerdings nur ohne die Ausgabe zwecks Test/Prüfung.

    Mit status genügt

    if(status) { // status beinhaltet bereits einen Wahrheitswert, der muss nicht noch mit true, oder an anderer Stelle mit false, verglichen werden.

    Ich weiß, dass dies sehr, sehr oft zu finden ist. Das erscheint mir aber sehr stereotyp. Und Häufigkeit hat nichts mit Qualität zu tun. :S

    Berry Programm? Meinst du auf einem Raspberry? das ist schon zu "gross".

    Nein, kein Raspberry Pi.

    Wenn man Tasmota32 (nur für ESP32 Boards) nutzt, steht auch die Programmierumgebung, ein online Editor, zum Erstellen von Programmen zur Verfügung, die in der Programmiersprache Berry erstellt werden. Diese ist C affin und bietet so einiges, was es in Shelly Script nicht gibt. Ich mag Shelly Script insbesondere wegen des gut strukturierten API und der mächtigen Schedule Jobs.

    Ich habe seit langem kein Berry Programm mehr erstellt, weiß aber noch folgendes.

    Es gibt eine Berry Konsole, in welcher man Berry Kommandos eingeben und damit testen sowie experimentieren kann.

    Bei laufendem Berry Programm kann man bspw. Variableninhalte ausgeben lassen und auch Funktionen aufrufen.

    Es steht ein einfaches Dateisystem zur Verfügung, in welchem man seine Berry Programme ablegen kann.

    Berry ist eine Hybridsprache, Quellcode wird in Dateien mit Suffix .be abgelegt. Ein Compilat erhält das Suffix .bec. Der kleine Interpreter arbeitet solche .bec Dateien ab, die geladen wurden.

    In eine Datei autoexec,be trägt man am besten per load <Dateiname> die Dateien ein, die mit dem Booten geladen und ausgeführt werden sollen. .be Dateien werden mit dem Laden automatisch compiliert, das Compilat in einer .bec Datei abgelegt und ausgeführt.

    Berry ist sehr interessant und man kann von Rules Berry Funktionen aufrufen lassen - mit Parameterübergabe.

    Per Berry kann man auf die flüchtigen (Varx) und die nichtflüchtigen (Memx) Rules-Variablen zugreifen.

    Die Rules sind Ereignis gesteuert und somit die Berry Funktionen auch.

    Es ist sogar möglich, per Berry externe Hardware (Sensoren, Aktoren) direkt anzusprechen (Gerätetreiber), was ich aber nie ernsthaft tat.

    Inzwischen soll es weitere Möglichkeiten geben, die ich (noch) nicht kenne.

    Ich habe ein wenig dazu dokumentiert.

    Ich versuche genauer zu erfassen, was du derzeit einsetzt und was du erreichen willst.

    Das Prinzip gefällt mir. Das zyklische Wechseln per Modulo ist interessant.

    Von einem sog. "Volkszähler" hatte ich vor Jahren mal etwas gelesen - und verworfen.

    Läuft irgendetwas dbzgl. bei dir bzw. dem Kumpel auf einem ESP32 Board, vielleicht sogar mit Tasmota32?

    Wenn ja, hast du mal ein Berry-Programm versucht?

    Mir gefällt Berry für solche Einsatzzwecke sehr gut und das Konzept überzeugt mich.

    Bin selbst Software Engineer.

    Dann solltest du nicht wirklich überfordert sein. Und entschuldige, falls ich dir etwas versucht habe zu erklären, was für dich selbstverständlich ist. ;)

    Dann könnte dich meine Skripteinführung (siehe Signatur) unterfordern, aber vielleicht auch interessieren.

    Echtes "komplettes" JavaScript ist ja nicht zu machen. Von daher musste ich mich mit dem zufrieden geben.

    Der aktuelle JavaScript Interpreter ist recht brauchbar und es gibt ein gutes API, was relativ ausführlich und gut beschrieben ist.

    Ich vermisse derzeit nichts.

    Und was du hier und anderswo finden kannst, ist nicht selten zu sehr stereotyp. Ich kann dir nur empfehlen, manches kritisch zu betrachten.

    Für den Fall, dass die Abbrüche bleiben, habe ich noch zwei Hinweise.

    Du kannst eine Ausnahmebehandlung einbauen. Dies ist so etwas wie ein Sicherheitsnetz für den Fall eines Laufzeitfehlers.

    Eine Ausnahmebehandlung ist eine Kombination aus einem try-Block und einem unmittelbar darauf folgenden catch-Block.

    Hier mit einem Code-Ausschnitt von #3:

    Ich habe zwei Ausnahmebehandlungen eingefügt, die sich in den Parametern ein wenig unterscheiden, um deutlich zu machen, dass nur die Struktur und nicht der Parametername wesentlich ist.

    Dies ist eine relativ grobe Methode, um einen Skriptabbruch zu verhindern. Sie kann und soll nicht die von mir weiter oben aufgeführten Sicherheitsabfragen ersetzen.

    Falls auch dies nicht helfen sollte, kannst du noch eine Notmaßnehme einsetzen, welche wenigstens für eine, wenn auch nicht technisch saubere, Fortsetzung der Funktionalität sorgt.

    Dazu setze einen Schedule Job ein, der bspw. jede Minute das Skript startet.

    http://<IP Adresse des Skript-Shelly>/rpc/schedule.create?timespec="0 * * * * *"&calls=[{"method":"script.start","params":{"id":<Skript Id>}}]

    Einen solchen Schedule Job kannst du nicht per Web UI anlegen, aber dessen Zeitmuster (timespec) später per Web UI ändern.

    Wenn das Skript läuft, bleibt das so. Ist das Skript gestoppt, wird es zu jeder vollen Minute gestartet.

    Zu Schedule Jobs habe ich einen kurzen Artikel verfasst.

    Grässlicher Code, sorry.

    Das Wichtigste zuerst:

    Immer wenn auf eine Objekt-Komponente zugegriffen wird, könnte sich ein Fehler ereignen, der zum Skriptabbruch führt.

    Beispiel:

    let x = a.b.c; // a sei ein Objekt mit erwartungsgemäß vorhandener Komponente b, die erwartungsgemäß Komponente c enthält.

    Wenn a oder a.b nicht existiert (undefined), kommt es zum Skriptabbruch.

    Gegenmaßnahme:

    let x;

    if(a.b.c!==undefined) x = a.b.c;

    oder

    if(a.b.c===undefined) return;

    x = a.b.c;

    Baue bei jedem lesenden Zugriff diese Sicherheitsabfrage ein!

    Btw, wenn a.b.c undefined ist, kommt es an dieser Stelle nicht zum Skriptabbruch, aber bei einer Weiterverarbeitung kann es dazu kommen

    Bin mir nicht ganz sicher. Evtl. ist eine noch aufwändigere Abfrage zielführend.

    if(a===undefined | | a.b===undefined | | a.b.c===undefined) return; // | | ist das logische ODER, das Leerzeichen dazwischen ist zwecks Vermeidung eines Smileys erforderlich.

    ...

    Logische Verknüpfungen werden i.d.R., hier immer, per Kurzschluss gewertet, d.h. sobald das Resultat der Verknüpfung feststeht, wird nicht weiter gewertet.

    Hier: Wenn a.b undefined ist, wird a.b.c nicht mehr auf undefined geprüft.

    Wenn du verstanden hast, wirst du den Code selbst verbessern können.

    Unwichtig, aber zum verschlanken des Codes geeignet:

    Du brauchst beim Verketten mit einem String einen numerischen Wert nicht per JSON.stringify in einen String zu verwandeln. Das tut der Interpreter alleine, weil der Operator + bei bereits einem String-Operanden als Verkettungsoperator interpretiert wird.

    Unsinnig, auch wenn oft zu finden:

    Als user defined parameter ein null zu übergeben ist stereotypischer Bullshit. Nimm solchen Quatsch heraus!

    Wozu soll die Variable alertTimer gut sein?

    Diese wäre erforderlich, wenn im Skript irgendwo der Timer gelöscht (Timer.clear(alertTimer)) werden soll. Auch das ist stereotypischer Unsinn, weil überflüssig.

    myunixdayint = result.unixtime / 86400 | 0;

    Mir erschließt sich nicht, was die bitweise ODER Verknüpfung mit 0 bewirken soll. x | 0 ergibt immer x.

    Vielleicht ist das ein tricky Ausdruck zur Umwandlung in einen Integer-Wert?

    Dazu sind Math.round(), Math.ceil() und Math.floor() vorgesehen.

    Es gibt noch mehr, ich will es hier aber mal so belassen.

    Ein kürzeres Skript ist übersichtlicher und leichter zu pflegen. ;)

    Da gibt es einen semantischen Widerspruch im Skript.

    Zeile 14:

    // Do not change code below this line!

    Zeile 90:

    Wozu gehört diese IP Adresse?

    %20 ist der Code eines Leerzeichens. ?

    Hab's gelesen - Volkszähler.

    Vielleicht, aber nicht wahrscheinlich, bringt die Antwort des Zählers das Skript irgendwie "aus dem Takt".

    Ich schaue mir das Skript weiter an ...

    Dann sollte das richtige Erkennen des Schalterzustandes wenigstens zumeist gelingen. Falls dbzgl. gelegentlich Aussetzer festzustellen sind, sind insbesondere die Kenntnisse von thgoebel gefragt.

    Meine Fragen:

    1. Hast du auf dem Shelly schon mal den Cloud-Zugriff deaktiviert?
    2. Wie ist die Zeitsteuerung implementiert?

    Yes, of course.

    Question: Does it have to be exactly 5 minutes or can it be up to about 6 minutes?

    An event handler receives the values and when power is 0 for the first time, it saves the timestamp.

    If power > 0, the timestamp is deleted.

    If 5 minutes later (current timestamp - saved timestamp) the power is still 0, the output is turned off.

    This is the simple algorithm.