NEWS
Shelly Dimmer via MQTT in NodeRed
-
Hallo zusammen.
Ich habe wiedermal eine Frage.
Und zwar möchte ich via NodeRed einen Shelly Dimmer 2 ansteuern und natürlich auch dimmen.
Das Einschalten klappt wunderbar..
Das Change node sieht so aus:
Wenn man bei "brightness" einen Wert von 1-100 dahinter schreibt, schaltet der Shelly mit dem entsprechenden Dimmwert ein. 100 wäre also demnach Dimmwert 100.
Momentan steht da X weil ich nicht weiss wie ich das angehen soll, damit ich via Slider auf dem Dashboard dimmen kann.
Der Slider sieht so aus:
Danke für eure Hilfe.
-
@faithlux Du schreibst nicht x dahinter, sondern payload (ohne Gänsefüsschen) und nutzt JSONATA und nicht JSON in Deiner Change Node.
-
ich habe dasselbe gemacht, einfach in json. ich habe nachgelesen was jsonata ist und das macht durchaus sinn, ergo es funktioniert danke @mickym
Dimmen hört auf den Befehl
shellies/shellydimmer-<deviceid>/light/0/set
Schalten hört auf den Befehlshellies/shellydimmer-<deviceid>/light/0/command
Ich möchte nun, dass wenn ich zB auf 50% gedimmt habe (natürlich sollte das mit jedem anderen Dimmwert zwischen 0-100 auch genauso gehen) und ausschalte, beim nächsten Mal genau auf der selben Dimmstufe eingeschaltet wird.
Ich dimme auf 50% runter, schalte aus.
Schalte ein, Licht ist auf 50% gedimmt.Ich kann das gewünschte mit zwei MQTT Ausgängen bereitstellen. dass das gewollte so funktioniert:
Aber das ist eher so eine semi gute Lösung.
Am Besten wäre es, wenn man in NodeRed, das Dimmen so gestalten könnte, wie wenn man einen Push-Taster hat.
Kurzes Tippen =
on
oderoff
Langes Tippe =hochdimmen
oder mit Pause dazwischenrunterdimmen
(und umgekehrt) -
@faithlux ich hab den shelly Dimmer gen1 und da funktioniert es so, wie du es beschreibst. Das macht aber die Hardware du muss ich gar nichts mit Node-red machen. Um einen Taster softwareseitig zu simulieren, arbeitest du im Dashboard nicht mit einem slider, sondern musst dir selbst was basteln. Das ist alles andere als trivial- ich habesowas ähnliches mal gemacht- muss aber nochmal schauen.
Die Frage ist in dem Fall wirklich, wieviel Aufwand möchtest Du in dein Dashboard stecken. Wie gesagt hardwareseitig habe ich ein Taster am Shelly und funktioniert genau so.
Hier habe ich mal sowas mit einem Node-Red Flow für ein vis Widget gebastelt- das kann ich nochmal raussuchen, da müsstest du dann einen eigenen Button-Typ im Dashboard definieren.
Hier: https://forum.iobroker.net/post/939067 gibts ein kleines mp4, wenn es das ist was du meinst - ist aber viel Aufwand.Du musst halt aufpassen ob du soviel Aufwand in ein Dashboard stecken willst, oder ob dir das mit slider und switch langt. Ansonsten musst du dir einen eigenen Button erstellen.
Du müsstest im übrigen auch ohne brightness mit dem Objekt schalten können, also ohne brightness, also mit
{"turn":"off"}
-
@mickym Danke für diesen Input.
Das wäre genau das was ich suche. Jedoch absolut keinen Plan wie ich das angehen soll.Hast du nicht per Zufall irgendwo diesen Code, den ich dann mit meinen Werten etc befüllen kann?
-
@faithlux Ja ich habe diesen Flow gefunden - aber nichts mit einfach Werte befüllen. Da musst Du schon tiefer einsteigen und zwar viel tiefer.
Wie gesagt im Normalfall nutzt man im Dashboard einfach den Slider und einen Switch getrennt - habe ich auch bei meinen Lampen so:
Das was Du in meinem Beitrag über das mp4 und dem vis widget gesehen hast, funktioniert für einen Softwaretaster nicht, da dieser einfach nur ein true oder eine beliebige payload schickt beim betätigen. Aber das nur einmal.
Als erste Vorraussetzung brauchst Du also einen Button, der meldet wenn er gedrückt wird (also Maus down) und meldet wenn er wieder losgelassen wird (also Maus up). Das ist im Standard nie der Fall, deswegen kannst Du da auch kein Long und Short unterscheiden.Um so einen Taster im NodeRed Dashboard zu erzeigen, musst Du den also selbst programmieren und halt auch das Aussehen anpassen. Ich nutze sogenannte momentary Buttons zum Beispiel im NodeRed Dashboard, dass ich als Fernbedienung nutze für die Lautstärketasten.
Wie gesagt anpassen musst Du die dann vom Aussehen her selbst. Ich hab Dir diese Taste mal herausgelöst und in ein eigene Dashboardgruppe übernommen. Ich habe mal das Lautstärkesymbol ausgetauscht mit den Awesome-Icons
Dieser Button hat nun die Eigenschaft, dass er true beim Drücken und false bei Loslassen sendet und deshalb sich von allen Standardbuttons unterscheidet.
Hier die Node als Einzelstück:
Die Node besteht aus einer template Node mit folgendem Code:
<style> .nr-dashboard-template { padding: 0px; } </style> <div class="momentary_1"> <md-button style="width:100%; height:48px; margin: 0px; background-color: var(--nr-dashboard-widgetBackgroundColor); padding-top: 10px;" ><i class="fa fa-lightbulb-o fa-2x"> </i></md-button> </div> <script> (function($scope) { $('.momentary_1').on('touchstart mousedown', function(e) { // e.preventDefault(); //prevent default behavior $scope.send({"payload": true}); }); $('.momentary_1').on('touchend mouseup', function(e) { // e.preventDefault(); //prevent default behavior $scope.send({"payload": false}); }); })(scope); </script>
Man sieht es wird eine eigene CSS Klasse definiert, die auf Mauseregnisse reagiert. Wenn Du mehrere solcher Nodes auf einer Dashboard-Seite verwendest musst Du darauf achten, dass Du jeder Node eine eigene ID gibst.
ggf kannst Du das auch über die ID der Node machen:<div id="{{'my_'+$id}}" - aber ich habe den Code nicht ausprobiert.
So hier mal der gesamte Tasterflow:
Der ist schon etwas älter deswegen wurde hier noch ohne JSONATA gearbeitet - um zum Beispiel zu dimmen:
Das ist wie gesagt noch umständlicher gemacht - aber das kannst Du ggf. ja anpassen, aber es kommen die gleichen Objekte raus.
Wichtig ist dass Du das Herzstück des Flows begreifst. Bevor ich den richtigen momentary Switch einbinde hier noch mit 2 getrennten Triggern:
Der obere Trigger entspricht dem Taster gedrückt, dem unteren Trigger entspricht Taster losgelassen. Solange der Taster gedrückt ist wird also alle 250 Millisekunden eine Nachricht erzeugt und zwar true. Falls false kommt wird der Trigger zurückgesetzt und es werden kein Nachrichten mehr erzeugt. Ich binde Dir später den momentary button noch ein.
Also die trigger Node sendet solange true alle 250 ms bis false kommt.
Nun kommen wir (eine der seltenen Fälle) sinnvoll ohne Programmieren nicht aus - deswegen folgende function Node:
Hier als Code:
var count = context.get('count') || 0; var longpress = context.get('longpress') || false; if (msg.payload){ count += 1; context.set('count',count); if (count > 5) { // Wert erhöhen wenn Longpress zu früh erkannt wird longpress = true; context.set('longpress',longpress); return [null,msg]; } } else { msg.payload=true; count = 0; context.set('count',count); if (!longpress) return [msg,null]; longpress = false; context.set('longpress',longpress); }
Wie Du an den ersten beiden Zeilen siehst, wird der Node Kontext für 2 Variablen verwendet. Zum einen ob die Node im Status Longpress ist und wieviele Nachrichten eingegangen sind, bevor eine false Nachricht kommt.
Wenn die false Nachricht kommt, dann wird der else-Ast ausgeführt und falls die Node nicht im Status Longpress ist, wird eine true Nachricht an den oberen Ausgang geschickt. Ausserdem wird der Zähler zurückgesetzt und der Longpress Zustand auf false.
Solange True Nachrichten kommen werden diese gezählt und ab 5 Nachrichten an den unteren Ausgang weitergeleitet.
Diese Zahl kannst Du natürlich anpassen, so wie Du es willst. Da alle 250 ms eine Nachricht von der Trigger Node erzeugt wird und erst ab mehr als 5 Nachrichten ein Longpress erkannt wird, wird am 1,5 Sekunden ein Longpress erkannt.Wenn Du was nicht verstehst musst halt nachfragen.
So ich habe mal den momentary button eingebunden:
Wird der button nur kurz gedrückt siehst Du dass die Nachricht am oberen Ausgang rauskommt - habe den shortpress debug aktiviert (hellblau) , drückst Du länger werden alle Nachrichten nach 1,5 Sekunden nach unten geleitet (lila).
So damit Du weiter den Flow verstehst, habe ich hier mal als Trockenübung über eine Inject Node mal die Flowvariablen initialisiert. (Test Inject Node)
Im Flowkontext wird also folgendes gespeichert:
Das aktuelle Dimmlevel, in welche Richtung gedimmt wird und ob die Lampe an ist.
Bei kurzem Drücken, schaltet also das commando (toggelt) zwischen "on" und "off".
Das Dimmen siehst Du nicht als Trockenübung - da hier der tatsächliche Status der Lampe triggert. Das ist auch wichtig, da Du ja weiterhin über den physischen Taster schalten kannst.
Zum Schluss noch eine Erklärung dieses Flow teils beim Dimmen:
Wenn keine neuen Dimmkommandos mehr kommen, dann wird die flow.down variable umgeschaltet.
Das ist im Prinzip die Dimmrichtung. Über die Flowvariable wird also entschieden ob bei erneutem Longpress auf- oder abgedimmt wird.
So hier nochmal der Flow in letzter Form:
Die iobroker Nodes musst halt ggf. gegen entsprechenden mqtt Nodes ersetzen.
Du siehst also - entweder Standard - der Rest ist machbar und auch eine gute Übung, aber halt alles andere als trivial.
-
@mickym Ach du heilige.. Danke für deine Arbeit.
Ich studiere das heute Abend mal und probiere meine Sache zum laufen zu bringenSieht in der Tat sehr komplex aus - aber ja ist sicher eine gute Übung.
-
@faithlux Ja manches würde ich heute mit JSONATA machen - aber das ist halt noch ein Flow aus meinen früheren Tagen und ich wollte ihn jetzt nicht ewig überarbeiten.
-
@m-gans you can try to use this. It is not working over mqtt so you can leave shell cloud turned on.
[ { "id": "c4e589e09355c27d", "type": "shelly-cloud", "z": "d724ef4f9c579ce1", "server": "33eca59cc5addf74", "description": "", "outputs": 1, "x": 690, "y": 700, "wires": [ [ "42afdd0863c670c9", "28bd90bf0488a3bc" ] ] }, { "id": "28bd90bf0488a3bc", "type": "shelly-gen1", "z": "d724ef4f9c579ce1", "hostname": "10.0.1.34", "description": "", "mode": "polling", "server": "033a6e9acf499057", "outputmode": "event", "uploadretryinterval": 5000, "pollinginterval": 5000, "pollstatus": false, "getstatusoncommand": true, "devicetype": "Dimmer", "devicetypemustmatchexactly": true, "outputs": 1, "x": 900, "y": 640, "wires": [ [] ] }, { "id": "42afdd0863c670c9", "type": "debug", "z": "d724ef4f9c579ce1", "name": "debug 1", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 900, "y": 760, "wires": [] }, { "id": "aeb4c2cae80da838", "type": "function", "z": "d724ef4f9c579ce1", "name": "on", "func": "msg.payload = {\n on:true\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 270, "y": 500, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "cb63debaf7f8cc7a", "type": "function", "z": "d724ef4f9c579ce1", "name": "off", "func": "msg.payload = {\n on:false\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 270, "y": 540, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "a2c586bfef493ba4", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Turn On", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 500, "wires": [ [ "aeb4c2cae80da838" ] ] }, { "id": "aa0ecc89becb52b6", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Turn Off", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 540, "wires": [ [ "cb63debaf7f8cc7a" ] ] }, { "id": "2cf86b714691d6aa", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Poll Status", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "str", "x": 120, "y": 440, "wires": [ [] ] }, { "id": "3340ffcb8fc86c54", "type": "function", "z": "d724ef4f9c579ce1", "name": "toggle", "func": "msg.payload = {\n turn:\"toggle\"\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 270, "y": 580, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "0ea0fceb5bc1b8f8", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Toggle", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 580, "wires": [ [ "3340ffcb8fc86c54" ] ] }, { "id": "e2e90ad3b39f30fb", "type": "function", "z": "d724ef4f9c579ce1", "name": "brightness 100%", "func": "msg.payload = {\nbrightness: 100\n}\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 310, "y": 620, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "5cd3246ee54df257", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Brightness", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 620, "wires": [ [ "e2e90ad3b39f30fb" ] ] }, { "id": "bbfe7de807db8d9d", "type": "function", "z": "d724ef4f9c579ce1", "name": "brightness 25%", "func": "msg.payload = {\nbrightness: 25\n}\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 300, "y": 660, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "c3dabccd82633861", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Brightness", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 660, "wires": [ [ "bbfe7de807db8d9d" ] ] }, { "id": "784a23f5f04fe49d", "type": "function", "z": "d724ef4f9c579ce1", "name": "turn on & set brightness 60%", "func": "msg.payload = {\n on : true,\n brightness: 60\n}\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 340, "y": 700, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "84b0058013cd5e99", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Combined", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 700, "wires": [ [ "784a23f5f04fe49d" ] ] }, { "id": "cde543a45872eba4", "type": "function", "z": "d724ef4f9c579ce1", "name": "on 2s", "func": "msg.payload = {\n on:true,\n brightness: 100,\n transition: 1000, // optional 0..5000ms\n timer: 2\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 270, "y": 740, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "21765d5065807b6a", "type": "function", "z": "d724ef4f9c579ce1", "name": "up 10%", "func": "msg.payload = {\n dim : 'up',\n step : 10, // %\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 280, "y": 780, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "f23c3049caf67f07", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Turn On", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 740, "wires": [ [ "cde543a45872eba4" ] ] }, { "id": "70d0d15752323197", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Dim Up", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 110, "y": 780, "wires": [ [ "21765d5065807b6a" ] ] }, { "id": "dcd652864f8a15d5", "type": "function", "z": "d724ef4f9c579ce1", "name": "down 10%", "func": "msg.payload = {\n dim : 'down',\n step : 10, // %\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 290, "y": 820, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "828232e21c455142", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Dim Down", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 820, "wires": [ [ "dcd652864f8a15d5" ] ] }, { "id": "4d828a1702a46719", "type": "function", "z": "d724ef4f9c579ce1", "name": "stop", "func": "msg.payload = {\n dim : 'stop',\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 270, "y": 860, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "a8a4fae7ed7cb40c", "type": "inject", "z": "d724ef4f9c579ce1", "name": "Dim Stop", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 120, "y": 860, "wires": [ [ "4d828a1702a46719" ] ] }, { "id": "775474fc432399fe", "type": "ui_slider", "z": "d724ef4f9c579ce1", "name": "", "label": "Svijetlo boravak", "tooltip": "", "group": "d5e8a876913ae91e", "order": 0, "width": 0, "height": 0, "passthru": false, "outs": "end", "topic": "payload", "topicType": "msg", "min": "1", "max": "100", "step": "1", "className": "", "x": 120, "y": 360, "wires": [ [ "be8c892c4ecbe444" ] ] }, { "id": "be8c892c4ecbe444", "type": "function", "z": "d724ef4f9c579ce1", "name": "set brightness and turn on", "func": "msg.payload = {\n on : true,\n brightness: msg.payload\n}\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 370, "y": 360, "wires": [ [ "c4e589e09355c27d" ] ] }, { "id": "611ce15e1152fcb8", "type": "ui_button", "z": "d724ef4f9c579ce1", "name": "", "group": "d5e8a876913ae91e", "order": 2, "width": "3", "height": "1", "passthru": false, "label": "Upali", "tooltip": "", "color": "", "bgcolor": "", "className": "", "icon": "", "payload": "", "payloadType": "date", "topic": "topic", "topicType": "msg", "x": 90, "y": 220, "wires": [ [ "aeb4c2cae80da838" ] ] }, { "id": "dda55d360731af0b", "type": "ui_button", "z": "d724ef4f9c579ce1", "name": "", "group": "d5e8a876913ae91e", "order": 2, "width": "3", "height": "1", "passthru": false, "label": "Ugasi", "tooltip": "", "color": "", "bgcolor": "", "className": "", "icon": "", "payload": "", "payloadType": "date", "topic": "topic", "topicType": "msg", "x": 90, "y": 260, "wires": [ [ "cb63debaf7f8cc7a" ] ] }, { "id": "33eca59cc5addf74", "type": "shelly-cloud-server", "description": "" }, { "id": "033a6e9acf499057", "type": "shelly-gen1-server", "port": "20001", "hostname": "aaa", "hostip": "" }, { "id": "d5e8a876913ae91e", "type": "ui_group", "name": "Svjetlo boravak", "tab": "35399c96328c3aa8", "order": 1, "disp": true, "width": "6", "collapse": false, "className": "" }, { "id": "35399c96328c3aa8", "type": "ui_tab", "name": "Home", "icon": "dashboard", "disabled": false, "hidden": false } ]