Beiträge von towiat

    Spotelly 2.0: Tester gesucht

    Nachdem das Script offensichtlich einen kleinen, aber feinen Nutzerkreis gefunden hat, habe ich nun eine neue Version mit einigen zusätzlichen Features erstellt. Aufgrund einiger Limitationen in der Ursprungsversion musste ich dazu im Code kräftig umrühren und einige strukturelle Änderungen vornehmen.

    Die neue Version läuft in meinen Tests klaglos, aber angesichts der doch signifikanten Änderungen wäre es schön, wenn sich ein paar Mutige finden würden, die das Script vor der "offiziellen" Freigabe installieren und mir Feedback über eventuelle Probleme geben.

    Wie man an die Vorabversion kommt, beschreibe ich am Ende - vorher noch eine Übersicht über die Änderungen zwischen Version 1.2 und 2.0:

    Geändert: API

    Anstelle des Awatter APIs wird nun das API von http://energy-charts.info verwendet. Dieses API wird vom Fraunhofer-Institut für Solare Energiesysteme (ISE) bereitgestellt und hat den Vorteil, dass es Preisdaten für das gesamte Marktgebiet der Strombörse EPEX anbietet (und das Script somit nicht mehr nur in Deutschland und Österreich verwendbar ist).

    Die Konfigurationsvariable awattarCountry wurde durch epexBZN (für Bidding Zone) ersetzt. Die EPEX unterteilt ihr Marktgebiet in Marktzonen, die nicht unbedingt mit den Landesgrenzen übereinstimmen müssen. Jede Zone wird durch einen Code identifiziert, der der in der Dokumentation verlinkten Tabelle entnommen werden kann.

    Deutsche Benutzer müssen in diese Variable den Wert DE-LU eintragen (weil Deutschland und Luxemburg eine gemeinsame Marktzone betreiben). Für österreichische Benutzer lautet der Code AT (Großschreibung ist in beiden Fällen wichtig!).

    Geändert: Abruflogik und Fehlertoleranz

    In der Vorversion war es notwendig, den Abrufzeitpunkt für die Preisdaten in einer Variable festzulegen. Diese Variable existiert nun nicht mehr - das Script führt den Preisabruf selbsttätig ab ca. 15:00 Uhr durch (der genaue Zeitpunkt ist leicht zufallsgesteuert, um die Last für den API-Server etwas zu verteilen).

    Sollte der API-Aufruf scheitern (weil die Tagespreise noch nicht im API-Server eingepflegt wurden oder auch aufgrund von Netzwerkproblemen etc.), startet das Script in Abständen von 20 Minuten so lange neue Versuche, bis die Daten erfolgreich abgerufen werden konnten. Normalerweise stehen die Preise irgendwann zwischen 15:00 und 17:00 zur Verfügung.

    Neu: nonBlockMode

    Über die neue Konfigurationsvariable blockMode kann nun zwischen zwei Betriebsmodi gewählt werden:

    Steht blockMode auf true (die Grundeinstellung), bleibt alles wie bisher - das Script identifiziert innerhalb des vorgegebenen Zeitfensters den zusammenhängenden Block von x Stunden mit dem niedrigsten Durchschnittspreis und aktiviert die Stromzufuhr für diesen Block.

    Wenn blockMode auf false gestellt wird, werden die x günstigsten Stunden im definierten Zeitfenster aktiviert - unabhängig davon, ob diese Stunden aufeinander folgen oder nicht.

    In beiden Modi wird für jede einzelne Stunde ein Check gegen das (optionale) Preislimit ausgeführt - sollte der Preis das Limit überschreiten, unterbleibt der Einschaltvorgang für die jeweilige Stunde.

    Entfernt: KVS-Eintrag

    Bisher hat das Script die berechneten Schaltzeiten über einen KVS-Eintrag kommuniziert. Für den neuen nonBlockMode ist das aufgrund der größeren Anzahl von Schaltaktionen nicht mehr praktikabel - ich habe daher die KVS-Logik entfernt und an dessen Stelle über einen HTTP-Endpunkt eine Infoseite implementiert - siehe den nächsten Punkt.

    Neu: HTTP-Endpunkt

    Das Script bietet nun einen HTTP-Endpunkt, der mit mit der URL http://<ipDesShelly>/script/<script_id>/spotelly aufgerufen werden kann. Gibt man obige URL im Browser ein, erhält man eine tabellarische Übersicht der berechneten Schaltzeiten samt den zugehörigen Preisen:

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

    Neu: priceModifier

    In der Grundeinstellung zeigt das Script die EPEX-Großhandelspreise an. Das sind aber üblicherweise nicht die Preise, die an den Stromlieferanten zu bezahlen sind - viele Anbieter verrechnen einen Aufschlag auf den Marktpreis und dazu kommt natürlich noch die Umsatzsteuer und vielleicht noch andere Abgaben oder Gebühren.

    In der Funktion priceModifier kann eine Formel hinterlegt werden, mit der der Marktpreis auf den tatsächlich zu bezahlenden Preis umgerechnet wird (und der so modifizierte Preis wird dann auch im HTTP-Endpunkt angezeigt).

    Beispiel: Ein österreichischer Anbieter verrechnet den EPEX-Spotpreis zuzüglich eines Aufschlages von netto 1.3 cent/kWh und auf diesen Betrag kommt dann noch die landesübliche Umsatzsteuer von 20 %. Diese Kalkulation würde man in der priceModifier Funktion so abbilden:

    JavaScript
    function priceModifier(spotPrice) {
      return (spotPrice + 1.3) * 1.2;
    }

    Neu: switchID

    Über die Konfigurationsvariable switchID kann bei Multi-Switch Geräten festgelegt werden, welcher Switch vom Script gesteuert werden soll. Jede Script-Instanz kann nur einen einzigen Switch verwalten.


    Das waren die Änderungen - um auf die neue Version zuzugreifen, muss im Github-Repository auf die dev Branch umgestellt werden:

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

    Nach Bestätigung dieser Auswahl sieht man die neue Version inklusive der überarbeiteten Dokumentation (es schadet wahrscheinlich nicht, diese Dokumentation einmal komplett durchzulesen ;)).

    Und hier ist noch einmal der Link auf das Repository:

    https://github.com/towiat/spotelly

    Für Fragen, Probleme, Wünsche und auch sonst alles stehe ich wie immer zur Verfügung ;).

    Der folgende Code tut, was du willst:

    JavaScript
    Shelly.call(
     "HTTP.GET",    // führe einen http GET request aus...
     {
       url: "http://192.168.2.60/rpc/Shelly.GetStatus", // ... und zwar auf diese URL
     },
     function (result, error) {
       print(result);
       print(error);
     },
    );

    Es reicht nicht, bei Shelly.call einfach eine URL reinzustecken - du musst sagen, welchen RPC du ausführen willst (in diesem Fall ist das ein HTTP GET Request) und gegebenenfalls die Parameter mitgeben, die dieser RPC verlangt (in diesem Fall ist der Parameter die URL die du aufrufen willst).

    Das Script ist in der vorliegenden Form tatsächlich nicht lauffähig, weil die Definition der Variablen SCAN_DURATION und ACTIVE_SCAN fehlt.

    Die Änderungshistorie zeigt, dass es am 5. Dezember 2024 eine Überarbeitung der Beispielscripte gab und in diesem Zuge sind die entsprechenden Programmzeilen (wohl unabsichtlich) gelöscht worden. Eine komplette Übersicht aller am 5. Dezember vorgenommen Änderungen zeigt der entsprechende Commit:

    https://github.com/ALLTERCO/shell…aa051540a4b907a

    Das bedeutet auch, dass die überarbeitete Version nie getestet wurde, weil dieser Fehler dann sofort aufgefallen wäre.

    Die einfachste Lösung ist vermutlich, die Version vor diesen Änderungen zu verwenden - die kann man sich aus der Git-Historie herausziehen. Hier ist der entsprechende Link:

    https://raw.githubusercontent.com/ALLTERCO/shell…le-shelly-dw.js

    Hallo familieschaal ,

    Ich habe mir das durch den Kopf gehen lassen und ich sehe keinen Sinn darin, das in diesem Script zu integrieren. Abgesehen von den Konsequenzen für die Programmierung (das Script müsste, abhängig von der Präsenz des Temperatursensors, unterschiedlich agieren) und für die Benutzerfreundlichkeit (die Konfiguration wäre ebenfalls unterschiedlich und komplexer) ist eine temperaturbezogene Steuerung auch einfach nicht der Zweck dieses Scriptes.

    Das Script soll sich ausschließlich um die preisbasierte Steuerung kümmern - und die Wärmepumpe muss ja in irgendeiner Form sowieso temperaturbezogen agieren (und den Energiebedarf selbsttätig reduzieren, wenn kein Heizbedarf besteht).

    Natürlich besteht immer die Möglichkeit das Script selbst anzupassen, aber in die von mir gepflegte "Standardversion" werde ich das nicht aufnehmen.

    In der Diskussion im Thread FritzBox reconnect über Script hat ostfriese erwähnt, dass bereits öfters nach einem Script gefragt wurde, das eine FRITZ!Box rebooten kann. Nachdem ich gerade in der Materie drin war, habe ich noch ein bisschen recherchiert und in den folgenden Links Vorlagen gefunden, die ich für den Shelly adaptieren konnte:

    https://www.media-techport.de/2023/08/fritzb…ipt-neustarten/

    https://forum.heimnetz.de/threads/repeat…en-tr-064.1061/

    Das folgende Script kann zumindest eine 6490 Cable erfolgreich rebooten:

    Da der Reboot offenbar zwingend eine Autorisierung erfordert, müssen Benutzer und Passwort im Klartext im Script eingetragen werden - ob das klug ist, muss jeder selber wissen ;-).

    Ich bitte um Feedback, falls das Ding auf anderen Modellen nicht funktionieren sollte - ich bin kein großer Fritzbox-Experte, aber ich werde mein Bestes tun ;).

    Ich kann das bei mir nicht testen, aber vielleicht gibt die Response einen Hinweis:

    Ich verstehe nicht, warum das nicht gehen sollte - das ist doch nur ein POST-Request mit ein paar Headern und einem String als Payload?

    Das müsste in dieser Richtung funktionieren (komplett ungetestet und ohne jegliche Haftung ;)):

    Die charCodeAt() Methode gibt direkt den Wert eines Zeichens als Integer zurück. Kombiniert mit einer for...of Loop könnte man das dann z. B. so formulieren:

    JavaScript
    let testString="\x00190aZ\xFF";
    
    for (let char of testString) { 
      print("Character: ", char, "Number: ", char.charCodeAt(0)); 
    };

    Das produziert den gleichen Output wie deine Version und ist etwas kürzer...

    Hallo E-Mix142 ,

    Es gibt derzeit keine Konfigurationsmöglichkeit für den anzusteuernden Switch, aber du kannst das gewünschte Resultat erzielen, indem du die Zeile 48 im Script von

      Shelly.call("Switch.Set", { id: 0, on: value }, function (result, error_code) {

    auf

      Shelly.call("Switch.Set", { id: 1, on: value }, function (result, error_code) {

    änderst.

    Ich werde in einer der nächsten Versionen eine entsprechende Konfigurationsvariable einbauen.

    Viel Erfolg!

    markus.guertler

    Sehr mysteriös - nur zur Sicherheit zwei Grundsatzfragen:

    1. Ist die Firmware des Shelly aktuell (sollte 1.4.4. sein)?
    2. Ist die Systemzeit des Shelly korrekt?

    Beides wird in der letzten Zeile des WebUI angezeigt. Wenn die Antwort auf beide Fragen ja ist, bräuchte ich die Logeinträge des Shelly zum Abfragezeitpunkt. Die findest du unterhalb des Scriptes (bitte die Checkbox "ONLY SCRIPT LOGS" deaktivieren):

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

    Die Einträge werden bei der planmäßigen Abfage um 15:00 geschrieben und nachdem das Log eine begrenzte Kapazität hat wäre es am besten, wenn du es genau zu diesem Zeitpunkt abfragst.

    akreienbring

    Nachdem sich mein Script ausführlich mit Datums- und Zeitproblemen beschäftigt und ich hier zufällig reingestolpert bin:

    Eigentlich sollte es reichen, wenn du die Zeile

    const nCurrentDateTime = (Shelly.getComponentStatus("sys").unixtime + 2 * 3600) * 1000;

    durch die Zeile

    const nCurrentDateTime = Date.now();

    ersetzt.

    Date.now() liefert den UNIX-Zeitstempel der Systemzeit. Über den Konstruktor new Date() kann ein Zeitstempel direkt in ein Datumsobjekt in der lokalen Zeitzone umgewandelt werden. Und von diesem Datumsobjekt kann man über den Aufruf der getTime() Methode wiederum den UNIX-Zeitstempel extrahieren. Als Beispiel:

    JavaScript
    let nowTimestamp = Date.now();                    // UNIX-Timestamp der Systemzeit
    let nowDatetime = new Date(nowTimestamp);         // Datum in der lokalen Zeitzone
    let nowDatetimeTimestamp = nowDatetime.getTime(); // UNIX-Timestamp des Datums
    print(nowTimestamp === nowDatetimeTimestamp);     // true

    Stromopa

    Danke für das Feedback - freut mich, dass es nützlich ist.

    Ich werke gerade an einer neuen Version und das von dir gewünschte Feature ist dabei im Plan. Es wird einen alternativen Berechnungsmodus geben, bei dem das Script die Stromzufuhr zu den günstigsten x Stunden des Zeitfensters einschaltet (auch wenn sie nicht zusammenhängen), womit dann automatisch die teuersten Stunden ignoriert werden.

    Ich kann noch nicht sagen, wann die neue Version herauskommt - wenn es so weit ist, werde ich das natürlich hier bekannt geben.

    beeMitch - danke für das Feedback!

    Ich würde das verwendete API tatsächlich gerne auf energy-charts.info umstellen, weil das Script dann europaweit verwendbar wäre und nicht nur in Deutschland und Österreich. Rein von der Programmierung her wäre der API-Wechsel in zehn Minuten erledigt - leider gibt es dabei ein praktisches Problem:

    Laut meinen Tests ist das energy-charts API sehr unzuverlässig. API-Aufrufe enden immer wieder in Timeouts und auch der Zeitpunkt, an dem die Preise für den nächsten Tag verfügbar sind, ändert sich jeden Tag - im Gegensatz zum Awattar-API, das offenbar steinstabil läuft und verlässlich um 15:00 die Preisdaten hat.

    Das Script in seiner derzeitigen Form kann mit dieser Unsicherheit aus strukturellen und technischen Gründen nicht umgehen - die praktische Konsequenz eines einfachen API-Wechsels wäre, dass es an einer signifikanten Anzahl von Tagen einfach nicht funktionieren würde.

    Ich arbeite an einer neuen Version, die konzeptionell völlig anders aufgezogen und in vielen Belangen resilienter ist (und es mir auch erlaubt, ein paar neue Features einzubauen). Ich kann aber derzeit nicht sagen, wann diese Version das Licht der Welt erblickt...

    HighFive

    Was spricht dagegen, wenn beispielhaft kein KVS vorhanden d.h. beim ersten Start einmal diesen Aufruf automatisch auszuführen?

    Zwei Dinge sprechen dagegen:

    Zum einen könnte das dazu führen, dass das Shelly-Limit von 5 Timern pro Script gerissen wird:

    • der Aufruf von calculate() analysiert das nächste Zeitfenster und setzt zwei Timer
    • dann kommt der planmäßige Aufruf via Schedule, der (abhängig vom Installationszeitpunkt) noch einmal dasselbe Zeitfenster beackert und nochmals zwei Timer (für dieselben Zeitpunkte) setzt
    • und diese vier Timer können (abhängig von den Berechnungsergebnissen) noch immer aktiv sein, wenn am Folgetag der nächste planmäßige Aufruf zwei weitere Timer hinzufügt

    Das derzeitige Design des Scriptes stellt implizit sicher, dass maximal vier Timer gleichzeitig aktiv sein können.

    Das zweite Problem ist, dass beim Aufruf von calculate() die Preisdaten für das nächste Zeitfenster möglicherweise noch gar nicht existieren. Wenn du das Script vor 14:00 installierst, gibt es die Preise für den nächsten Tag noch nicht und dementsprechend würde die Preisanalyse dann scheitern (und die Benutzer wären erst recht verwirrt).

    Ich habe versucht, das Verhalten nach der Installation in der Doku zu erklären - mehr wird es wohl nicht werden, weil es ein ziemlicher Aufwand wäre, die obigen Spezialkonstellationen algorithmisch abzufangen und den Benutzern verständlich zu machen.

    Aber das Problem von TomPu31 ist ja, dass das Script mysteriöserweise stoppt und das ist ja eine andere Baustelle...

    TomPu31

    Ein sofortiger Abbruch des Scriptes passiert normalerweise, wenn ein schwerer und offensichtlicher Programmierfehler im Script vorliegt. Das würde dann aber bei jedem Start des Scriptes bei allen Anwendern passieren - also auch bei meinen Tests (wo das natürlich nicht aufgetreten ist).

    Eine mögliche Ursache wäre, dass beim Kopieren des Scriptes auf deinen Shelly etwas schiefgegangen ist - hast du den alten Code komplett entfernt, bevor du die neue Version reinkopiert hast? Bzw. könntest du das noch einmal versuchen?

    Falls das Problem weiter auftreten sollte, könntest du direkt nach dem Start auf den Diagnostics Tab gehen und schauen, ob du da einen Fehler siehst? Der könnte z. B. so ausschauen:

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