Shelly Plus Plug S - LED Farbe und Brightness wechslen über REST

Es wird besser, aber leider noch nicht richtig:

ok, dann folgendes:

msg.payload = 'config={"leds":{"mode":"switch","colors":{"switch:0":{"on":{"brightness":10},"off":{"brightness":100}}}}}';
return msg;

Okay, das war es für die “function”-node! :grinning:

Leider geht es jetzt mit der http-request-node weiter:

Natürlich teste ich mit der “richtigen” IP!
“GET” habe ich auch mit allen 3 Varianten (für Nutzdaten(payload)) durch, funktioniert auch nicht.

Oh man, so langsam bin ich mit meinem Latein auch am Ende :upside_down_face::see_no_evil: wenn du das am Browser machst, brauchst du davor mal die Anmeldedaten vom Shelly?

Nein, meine Shelly’s haben auch keinen Passwortschutz.
Ich kopiere das hier:

http://<Shelly-IP>/rpc/PLUGS_UI.SetConfig?config={"leds":{"mode":"switch","colors":{"switch:0":{"on":{"brightness":10},"off":{"brightness":100}}}}}

in die Adressleiste des Browsers und bekomme diese Rückmeldung:
image

Shelly vorher:
image
Shelly nachher:
image

Strange… Vielleicht mal noch sowas anlog dieser Lösung:
https://flows.nodered.org/flow/f0a1a4d30712a5e8b37a9287a8cdb3d4
Das würde die Seite direkt öffnen…

Du wirst es nicht glauben, aber es geht viiiiiiiiiel einfacher:


und in der http-request-Node steht der komplette Befehl unter URL drin:

Eine Besonderheit gilt es noch zu beachten, wenn man die HTTP-Request-Node in einen Flow einbindet und damit triggert:
Es darf kein payload mit Inhalt geschickt werden, auch bei einer Inject-Node vorher alle Ausgänge löschen. Im Flow habe ich mir damit beholfen, dass ich eine “trigger”-Node mit 1ms davor gesetzt habe, die als Nachricht boolean “true” sendet.

Trotzdem Danke für Deine Bemühungen!

2 „Gefällt mir“

:joy::joy::joy: Ok, dachte das hattest du schon probiert :see_no_evil::see_no_evil::see_no_evil: aber cool, dass es jetzt doch noch so easy geht :+1:

Hatte ich auch, aber mit dem “String” als Payload der “Inject”-node :woozy_face:
In der HTTP-Request-Node hatte ich URL nur die IP (hatte mich von diversen Suchergebnissen im www blenden lassen, die alle mit “Change”- und “function”-Nodes gearbeitet hatten. :face_with_diagonal_mouth:

Vielen herzlichen Dank an @harryp für die Lösung! Ich habe mich aufgrund deiner Beiträge dazu entschieden, Node Red als Addon zu HA zu installieren und konnte meine Problemstellung damit zufriedenstellend lösen.

Gruß

Werner

1 „Gefällt mir“

Gerne!
Du wirst bestimmt nach und nach alle Deine Automatisierungen von HA auf Node-Red umstellen. Wetten? :grinning:

1 „Gefällt mir“

Ich muss da noch viel lernen. Da der Node “events: state” keine Werte von - bis kennt, habe ich mir mit einem Helfer “Schwellenwert Sensor” beholfen, da ich ja nicht nur für min/max eine Farbe darstellen möchte, sondern auch für ein oder zwei Zwischenstufen. Man muss schon kreativ sein, um an eine Lösung zu kommen. Nicht immer wird einem alles am Silbertablett präsentiert. Ich mag das. :wink:

1 „Gefällt mir“

Du konntest auch hinter der “event-state”-node eine “switch”-node einbauen und darin die verschiedenen Zustände Deines “payload” abfragen und entsprechend Aktionen auslösen.

Bei mir funktioniert es so:

in der configuration.yaml:

rest_command:
  set_color:
    url: "{{ url }}"

ein Script erstellen mit folgendem Inhalt (unter Automatisationen → scripts und dann die drei Punkte als yaml bearbeiten)

Scriptname: change_shelly_color

description: Changes the color of the Shelly Plug
fields:
  ip:
    description: IP address of the Shelly Plug
    example: 192.168.11.73
    required: true
  red:
    description: Red value (0-255)
    example: 100
    required: true
  green:
    description: Green value (0-255)
    example: 100
    required: true
  blue:
    description: Blue value (0-255)
    example: 100
    required: true
sequence:
  - service: rest_command.set_color
    data:
      url: >
        {% set config = {
          "leds": {
            "mode": "switch",
            "colors": {
              "switch:0": {
                "on": {"rgb": [red, green, blue], "brightness": 100},
                "off": {"rgb": [red, green, blue], "brightness": 100}
              }
            },
            "power": {"brightness": 100}
          }
        } %} http://{{ ip }}/rpc/PLUGS_UI.SetConfig?config={{ config | tojson |
        urlencode }}

und dann den Dienst so aufrufen:

service: script.change_shelly_color
data:
  ip: '192.168.11.104'
  red: 100
  green: 1
  blue: 1

Die Farben gehen dabei nur von 0-100

Neustart nicht vergessen!

Viel Spaß damit :slight_smile:

PS.: Das Script habe ich mit Chat GPT4o erstellt - hat mir sehr viel geholfen - solltet ihr auch probieren

2 „Gefällt mir“

Genial. Ich konnte es sofort nachvollziehen und umsetzen. :+1: :+1: :+1:

Vielen lieben Dank - auch mir hat das Script geholfen.

Ich habe es noch etwas erweitert, um einen Unterschied bei den Farben für ON und OFF, sowie auch die Helligkeit bestimmen zu können.

Ich habe an dem Shelly Plug SG3 eine Siebträgermaschine.
Wenn die Steckdose einschaltet leuchtet sie grün und wenn die Heizung angeht, die Leistung über 200W geht, schalte ich die LED rot.
Somit sehe ich wann die Maschine heizt.
Wenn gewünscht, stelle ich das geänderte Script hier rein.
Grüße
ULi

Ich habe dafür auch einen Node-RED Subflow erstellt, mit dem sich die RGB-LED eines Shelly Plug (Gen3) über die RPC-API steuern lässt.

:puzzle_piece: Funktionen

  • Übergabe von RGB-Farbwerten, Helligkeit und Modus (on, off, both)
  • Verwendung von Subflow-Umgebungsvariablen als Fallback
  • POST-Request mit JSON-Body an /rpc/PLUGS_UI.SetConfig
  • Statusausgabe über Subflow-Status-Port (z. B. für Logging)
  • Validierung der Eingaben (z. B. IP-Adresse, Wertebereiche)

:test_tube: Beispiel-Nutzung

msg.payload:

{
  "ip": "10.0.11.63",
  "red": 0,
  "green": 255,
  "blue": 0,
  "brightness": 100,
  "mode": "both"
}

:paperclip: Subflow-JSON

[{"id":"8cd8a702eebbe29a","type":"subflow","name":"Shelly Plug RGB Color","info":"Setzt die RGB-Farbe der LED eines Shelly Plug über das PLUGS_UI.SetConfig RPC-Interface.\r\n\r\n⚙️ Parameter (via msg.payload):\r\n- IP (string, optional): IP-Adresse des Geräts. Falls leer, wird default_ip verwendet.\r\n- Red, Green, Blue (0-255): Farbwerte\r\n- Brightness (0-100, optional): Helligkeit (Standard: 100)\r\n- Mode (string, optional): \"on\", \"off\" oder \"both\" → bestimmt, ob die Farbe im Zustand Ein, Aus oder beidem geändert wird.\r\n\r\n🌐 Beispiel:\r\n{\r\n  \"ip\": \"192.168.11.73\",\r\n  \"red\": 255,\r\n  \"green\": 120,\r\n  \"blue\": 60,\r\n  \"brightness\": 80,\r\n  \"mode\": \"on\"\r\n}","category":"","in":[{"x":180,"y":140,"wires":[{"id":"8c5e9c60882bb559"}]}],"out":[{"x":680,"y":140,"wires":[{"id":"401ea8ee19743b5a","port":0}]}],"env":[{"name":"IP","type":"str","value":""},{"name":"Red","type":"num","value":""},{"name":"Green","type":"num","value":""},{"name":"Blue","type":"num","value":""},{"name":"Brightness","type":"num","value":""},{"name":"Mode","type":"str","value":""}],"meta":{"desc":""},"color":"#ff9900","icon":"node-red/light.svg","status":{"x":680,"y":200,"wires":[{"id":"a8b81368418d4893","port":0}]}},{"id":"8c5e9c60882bb559","type":"function","z":"8cd8a702eebbe29a","name":"RPC-Configuration","func":"// Umgebungsvariablen als Fallbacks\nconst ip = msg.payload.ip ?? env.get(\"IP\");\nconst red = msg.payload.red ?? env.get(\"Red\");\nconst green = msg.payload.green ?? env.get(\"Green\");\nconst blue = msg.payload.blue ?? env.get(\"Blue\");\nconst brightness = msg.payload.brightness ?? env.get(\"Brightness\") ?? 100;\nconst mode = (msg.payload.mode ?? env.get(\"Mode\") ?? \"both\").toLowerCase();\n\n// ---------- Validierungen ----------\n// IP-Prüfung\nconst ipRegex = /^(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)){3}$/;\nif (!ip || !ipRegex.test(ip)) {\n    node.status({ fill: \"red\", shape: \"dot\", text: \"Ungültige IP-Adresse\" });\n    node.error(\"Invalid IP address\", msg);\n    return null;\n}\n\n// Farbwerte prüfen\nconst isValidByte = (v) => Number.isInteger(v) && v >= 0 && v <= 100;\nif (!isValidByte(red) || !isValidByte(green) || !isValidByte(blue)) {\n    node.status({ fill: \"red\", shape: \"dot\", text: \"RGB-Werte ungültig\" });\n    node.error(\"RGB values must be integers from 0 to 255\", msg);\n    return null;\n}\n\n// Helligkeit prüfen\nif (!Number.isInteger(brightness) || brightness < 0 || brightness > 100) {\n    node.status({ fill: \"red\", shape: \"dot\", text: \"Brightness ungültig\" });\n    node.error(\"Brightness must be an integer from 0 to 100\", msg);\n    return null;\n}\n\n// Modus prüfen\nif (![\"on\", \"off\", \"both\"].includes(mode)) {\n    node.status({ fill: \"red\", shape: \"dot\", text: \"Ungültiger Modus\" });\n    node.error(\"Mode must be 'on', 'off' or 'both'\", msg);\n    return null;\n}\n\n// ---------- Konfiguration erstellen ----------\nlet on_config = {};\nlet off_config = {};\n\nif (mode === \"on\" || mode === \"both\") {\n    on_config = { \"on\": { \"rgb\": [red, green, blue], \"brightness\": brightness } };\n}\nif (mode === \"off\" || mode === \"both\") {\n    off_config = { \"off\": { \"rgb\": [red, green, blue], \"brightness\": brightness } };\n}\n\nlet config = {\n    leds: {\n        mode: \"switch\",\n        colors: {\n            \"switch:0\": {\n                ...on_config,\n                ...off_config\n            }\n        }\n    }\n};\n\n// ---------- RPC vorbereiten ----------\nconst query = JSON.stringify(config);\nmsg.method = \"POST\";\nmsg.url = `http://${ip}/rpc/PLUGS_UI.SetConfig`;\nmsg.payload = {\n  config: config\n};\n\n// Status anzeigen\nnode.status({ fill: \"blue\", shape: \"dot\", text: `Sending RGB (${red},${green},${blue})` });\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":140,"wires":[["401ea8ee19743b5a"]]},{"id":"401ea8ee19743b5a","type":"http request","z":"8cd8a702eebbe29a","name":"","method":"use","ret":"txt","paytoqs":"body","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":530,"y":140,"wires":[["a8b81368418d4893"]]},{"id":"a8b81368418d4893","type":"function","z":"8cd8a702eebbe29a","name":"Set Status","func":"let statusObject = {};\n\nif (msg.statusCode === 200) {\n    node.status({ fill: \"green\", shape: \"dot\", text: \"Success\" });\n\n    statusObject = {\n        fill: \"green\",\n        shape: \"dot\",\n        text: \"Success\"\n    };\n} else {\n    node.status({ fill: \"red\", shape: \"ring\", text: \"Error \" + msg.statusCode });\n\n    statusObject = {\n        fill: \"red\",\n        shape: \"ring\",\n        text: \"Error \" + msg.statusCode\n    };\n}\n\nmsg.payload = statusObject;\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":200,"wires":[[]]},{"id":"c48a65e626c7722b","type":"subflow:8cd8a702eebbe29a","z":"84a284212330aadd","name":"","x":600,"y":3540,"wires":[[]]}]

Hallo Feichtl,
falls das für dich oder die anderen noch relevant ist, hier hab ich eine nette Lösung für die Signalisierung mit Shelly Plugs LEDs:

**
**

Hi, Danke für deine Bemühungen! Ich habe mir den Beitrag durchgelesen und entschieden, bei meiner Lösung mit Node Red zu bleiben. Da ich (aktuell) damit nur drei Shellys ansteuere und es problemlos läuft, belasse ich es dabei.

LG Werner

Hi uli536,

würde mich sehr für dein Skript interessieren. Vor allem das Thema Helligkeit ist nicht uninteressant für mich.

Hat jemand noch eine Idee wie ich die LED blinken lassen kann, ohne mit einem „Einschalt-Befehl“, einem „Ausschalt-Befehl“ und einer Wiederholung dieser Schleife arbeiten zu müssen?

Und wie stellt ihr hier andere Farben (z.B. Orange {RGB:255;165;0} ) mit den Werten von 0-100 ein?

Vielen Dank im Voraus!

1 „Gefällt mir“