Beiträge von towiat

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.

    Ich lese gerade das "What you need to know" über die Änderungen, die offenbar mit Firmware 1.8 kommen.... da wird's wohl ein paar Anfragen im Forum geben - Beispiele:

    Zitat
    • Browsers and other clients may warn about certificate trust chain validation problem. The certificate is issued by Shelly private CA. Shelly will publish the chain of trust for importing into your client. Shelly application will have this chain of trust by default.
    • Account lockout after repeated failures within a time window, only established sessions are allowed.
    • Bluetooth channel is automatically disabled after setup; enabling it opens a 15-minute pairing window only.
    • You must complete initial configuration (admin password, Wi-Fi, etc.) within the guided 15-minute window after powering up/resetting the device.

    Siehe https://kb.shelly.cloud/knowledge-base…elly-and-eu-red

    HTTP Kommunikation (welche ich abfangen und ändern könnte)

    Du hast recht. Ich bin fälschlicherweise davon ausgegangen, dass der Shelly auch die Integrität der Nachricht verifiziert, aber die entsprechende Quality of Protection (auth-int) wird offensichtlich nicht unterstützt. Somit ist zwar das Passwort geschützt, aber der Inhalt der Nachricht ist manipulierbar. Asche auf mein Haupt...

    Es nützt genau das, was ich gesagt habe. Ein Eindringling kann durch Datenanalyse wahrscheinlich problemlos herausfinden, welcher Shelly dein Garagentor steuert - aber er kann es ohne Passwort nicht öffnen. Dass es besser ist, das Netzwerk von vornherein so abzusichern dass es ger nicht erst so weit kommt, halte ich für offensichtlich.

    Wie schon gesagt, bleibt es jedem selbst überlassen, ob er das machen will (ich tu's auch nicht).

    Die Shellys sprechen aktuell nur http - da ist das mit der Passwortsicherheit eh hinfällig.

    Da würde ich (ein bisschen) widersprechen. Die Grundidee der vom Shelly verwendeten Digest-Authentication ist es ja, dass das Passwort auch bei unverschlüsselten Verbindungen geheim bleibt (weil es nie im Klartext sondern nur als Teil eines Hashes übertragen wird, der für jede Abfrage neu berechnet wird).

    Ein potentieller Eindringling ins Netzwerk könnte zwar problemlos den (unverschlüsselten) Datenverkehr vom und zum Shelly mitlesen - ohne Kenntnis des Passwortes ist es ihm aber unmöglich, selbst Abfragen oder Befehle an den Shelly zu schicken.

    Ob die Absicherung gegen dieses Szenario den Aufwand für die Passworterstellung/-verwaltung rechtfertigt, ist wohl eine individuelle Entscheidung...

    Ich habe es bei meinem einfachen Test "zu simpel" versucht.

    Das ist eher eine Verkettung unglücklicher Umstände - der Shelly lehnt offenbar POST-Requests ohne Body ab und curl sendet keinen Body, wenn er nicht explizit angegeben wird. Deswegen geht curl http://ip/rpc/Shelly.GetStatus -X POST nicht durch, aber curl http://ip/rpc/Shelly.GetStatus -d "{}" oder curl http://ip/rpc/Shelly.GetStatus -d "xyz" sehr wohl - muss man auch einmal draufkommen...

    PHP ist nicht meine Baustelle, daher hier die Beispiele direkt in curl (die optionalen Parameter habe ich weggelassen). Es gibt zwei gleichwertige Methoden, um RPCs via POST zu schicken:

    1. Du schickst einen POST an den /rpc Endpunkt. Dann musst du einen vollständigen JSON_RPC Frame mit id, method und params verwenden:

    curl http://192.168.178.253/rpc -d '{"id": 0, "method": "Webhook.Create", "params": {"event": "switch.on", "cid": 0, "name": "Action-Name", "enable": true, "urls": ["https://meine-domain.de"]}}'

    2. Du schickst einen POST direkt an den /rpc/Webhook.Create Endpunkt. Dann reichen die Request-spezifischen Parameter im Body:

    curl http://192.168.178.253/rpc/Webhook.Create -d '{"event": "switch.on", "cid": 0, "name": "Action-Name", "enable": true, "urls": ["https://meine-domain.de"]}'

    Dokumentiert ist das alles hier...

    Ich habe Version 3.6 des Scriptes veröffentlicht - hier ist das Changelog:

    3.6 (2025-11-18)

    This release enhances the priceModifier function so that it can be used to calculate date- or time-dependent price variations (like variable grid fees which have become more widespread in many European countries).

    With this version, the script will pass both the price value and the date and time for each price into the priceModifier function. An example on how this can be used:

    A grid operator charges different grid fees depending on the time of day:

    • The fee is 10 ct/kWh during the peak hours from 7:00 to 9:00 and 18:00 to 20:00.
    • For the remainder of the day, the fee is 8 ct/kWh.

    The priceModifier can be modified like so to add these fees to the EPEX price:

    JavaScript
    function priceModifier(datetime, spotPrice) {
      let hour = datetime.getHours(); // extract hour from the datetime
      if (hour === 7 || hour === 8 || hour === 18 || hour === 19) {
        return spotPrice + 10; // peak hour - add 10 cent to the EPEX price
      }
      return spotPrice + 8; // normal hour - add 8 cent to the EPEX price
    }

    These modified prices are then used by the price analysis algorithm to determine the cheapest hours of the day.

    Note that the WebUI will display these modified prices (and not just the pure EPEX price) when this feature is used.

    Eine direkte Möglichkeit gibt es meines Wissens nach nicht, aber man kann sich mit der utc_offset Variable aus der sys-Komponente helfen. Die gibt den Abstand zur UTC in Sekunden an - in der mitteleuropäischen Zeitzone also 7200 bei Sommerzeit und 3600 bei Normalzeit.

    Die folgende Zeile legt eine Variable Sommerzeit an, die bei aktiver Sommerzeit auf true steht:

    JavaScript
    let Sommerzeit = Shelly.getComponentStatus("sys").utc_offset === 7200;

    Logischerweise würde ich annehmen, dass der Shelly die utc_offset Variable exakt zum Zeitpunkt der Zeitumstellung ändert, aber wirklich prüfen kann ich das nicht...

    Ich habe Version 3.5 des Scriptes veröffentlicht - hier ist das Changelog:

    3.5 (2025-10-18)

    This release contains two changes:

    • Changed: Price Retrieval
      As the price API sometimes delivers too many and/or erroneous price records especially for the Austrian market, the retrieval logic was slightly changed to try to compensate for that. This change should prevent the API from delivering more than 96 prices for a day (although I can not guarantee that since the API is not under my control).
    • New: Invert Switch
      A new configuration variable invertSwitch is available, which makes it possible to change the switching behavior of the script (useful for some electrical configurations):

      • When set to false (the default), the script turns the switch ON for the selected (cheapest) hours and OFF for the remaining hours.
      • When set to true, the script turns the switch OFF for the selected (cheapest) hours and ON for the remaining hours.

      Note: This change has no impact on the WebUI, which will always show ON for the selected (cheapest) and OFF for the remaining hours.

    Das Script ist wie immer auf GitHub zu finden: https://github.com/towiat/spotelly

    Ich habe Version 3.3 des Scriptes veröffentlicht. Hier ist das Changelog:

    3.3 (2025-10-06)

    Mit dieser Version werden nun 15-Minuten-Preise unterstützt. Da derzeit viele Verträge weiterhin mit Stundenpreisen arbeiten (die eigentlich nur der Durchschnitt der 15-Minuten-Preise für jede Stunde sind), unterstützt das Skript vorerst beide Modi: 60 Minuten und 15 Minuten.

    Die neue Konfigurationsvariable hourMode legt den zu verwendenden Modus fest:

    Wenn sie auf true gesetzt ist (die Grundeinstellung), berechnet und zeigt das Skript die Schaltzeiten für volle Stunden (basierend auf dem Durchschnittspreis für jede Stunde).

    Wenn sie auf false gesetzt ist, werden die Schaltzeiten basierend auf Viertelstunden berechnet und angezeigt. Alle Scriptfunktionen wie Zeitfenster, Blockmodus und Preislimits funktionieren wie erwartet und die Stundentabelle im WebUI ermöglicht die manuelle Anpassung der Ergebnisse. Es gibt jedoch einen Unterschied bei der Einrichtung des Scriptes:

    Im 15-Minuten-Modus definiert die Variable switchOnDuration die Dauer in Viertelstunden, nicht in Stunden. Wenn also z. B. eine Gesamteinschaltzeit von fünf Stunden konfiguriert werden soll, ist der korrekte Wert für diese Variable in diesem Modus 20.

    Das Script ist wie immer auf GitHub zu finden: https://github.com/towiat/spotelly

    Ein bisschen Senf von mir:

    Das JSON-RPC Protokoll definiert nur das Layout von Nachrichten, aber nicht den Transportmechanismus. Shellies können JSON-RPC Nachrichten offenbar über HTTP, UDP, MQTT, WebSocket und Bluetooth empfangen.

    Die Diskussion hat mich neugierig gemacht, weil ich mich bisher nie gefragt habe, wie mein HA eigentlich mit dem Shelly kommuniziert. Des Rätsels Lösung ist: WebSocket. Die Dokumentation sagt Folgendes:

    Zitat

    Websocket

    The connection is kept alive through the whole duration of the communication (not only for one request-response pair) as used by the local web interface and aioshelly. Each Shelly device has a websocket endpoint and a client can connect to it to communicate with the device. Protection through digest authentication is supported over this channel.

    The websocket channel is served on ws://<shelly.addr>/rpc. Clients must send at least one request frame with valid src to be able to receive notifications from the device.

    Das erwähnte aioshelly ist die Python Library, die für die HA-Shelly Kommunikation zuständig ist (und auch auf GitHub zu finden). Wenn ich via HA den Switch des Shelly betätige, erscheint im Shelly Log auch eine entsprechende Nachricht mit WS_in als Quelle:

    Code
    Switch.Set [17@aios-546907190912] via WS_in 192.168.178.254:42364

    HA hält also via WebSocket eine permanente Verbindung zum Shelly offen und ich würde annehmen, dass das wohl die effizienteste/performanteste Lösung ist...

    Hallo Coloschni ,

    wenn ich zwei Skripte auf einem Modul laufen lasse, schalten die sich gegenseitig weg

    Ja, das ist so. Beide Script-Instanzen versuchen zu jeder vollen Stunde, den Switch anhand ihrer internen Tabelle umzuschalten und letzten Endes ist es Zufall, welche der beiden Versionen gewinnt.

    Von der Programmierung her wäre es einfach, den Tag in Segmente zu unterteilen und für jedes Segment separat die günstigsten Stunden zu errechnen. Das Problem dabei ist, dass die Konfiguration des Scriptes damit wesentlich komplizierter werden würde (und mit der Umstellung auf Viertelstundenpreise gilt das umso mehr).

    Ich experimentiere gerade in dem Bereich, aber ich kann noch nicht sagen, ob ich dafür eine zufriedenstellende Lösung finden werde...

    NScale

    Okay, dann würde ich noch eine Änderung im Script machen, nämlich den Content-Type - statt

    JavaScript
    "Content-Type": "application/json",

    solte er

    JavaScript
    "Content-Type": "application/x-www-form-urlencoded",

    sein (weil der Inhalt des Body eigentlich kein JSON mehr ist).

    Mit dieser Änderung sieht der vom Shelly gesendete Request in meinen Tests dann 1:1 wie der von curl aus. Wenn das auch nicht reicht, bin ich dann am Ende meiner Weisheit...

    NScale

    Das ist komisch - wenn du diese Meldung bekommst, müsste OpenDTU das eigentlich akzeptiert haben. Bei genauerer Ansicht fällt mir noch auf, dass die Definition des Request body nicht der Dokumentation entspricht. Probiere noch, diese Zeile:

    JavaScript
    body: JSON.stringify({ data: payload }),

    durch diese zu ersetzen:

    JavaScript
    body: "data=" + JSON.stringify(payload),

    Und du könntest noch schaun, ob OpenDTU den folgenden curl-Request (natürlich mit deinen Daten) akzeptiert - der ist direkt aus der OpenDTU Dokumentation:

    Code
    curl -u "admin:password" http://192.168.10.10/api/limit/config -d 'data={"serial":"11418180xxxx", "limit_type":1, "limit_value":50}'

    Vorweg: Ich verwende OpenDTU nicht und kann daher nur nach Doku vorgehen.

    Laut der Konsole wird der Befehl ausgeführt und das Limit gesetzt. Allerdings kann ich in der openDTU keine Änderung verzeichnen. Kann mir jemand helfen?

    Die Meldung in der Konsole sagt nur, dass der Request erfolgreich abgeschickt wurde. Sie sagt NICHT, dass OpenDTU den Request auch akzeptiert hat. Mit hoher Wahrscheinlichkeit lehnt OpenDTU den Request ab, weil User und Passwort nicht korrekt gesendet wurden.

    Hier ist eine modifizierte Version deines Scriptes, in der ich drei Dinge geändert habe:

    1. Anstelle von HTTP.POST wird HTTP.Request mit der Methode POST verwendet (weil bei HTTP.POST kurioserweise keine eigenen Header mitgegeben werden können).
    2. Username und Passwort werden im Header so mitgegeben, wie es die Basic HTTP Authentication vorsieht.
    3. Zusätzlich ist eine Fehlerbehandlung implementiert, die genaue Auskunft über etwaige Probleme geben sollte.

    Wenn du jetzt die Funktion sendLimit() aufrufst, sollte in der Konsole eine von drei Meldungen erscheinen:

    • Shelly Fehler ... wenn der Request nicht abgeschickt werden konnte
    • OpenDTU Fehler ... wenn OpenDTU den Request nicht akzeptiert hat
    • Limit erfolgreich geändert wenn alles funktioniert hat

    Versuch es bitte mal und lass mich wissen, was die Konsole sagt...