- Home
- Deutsch
- Skripten / Logik
- Node-Red
- ProxyScript für NodeRed und JS-Selektor
ProxyScript für NodeRed und JS-Selektor
-
In Anlehnung an die Defizite des NodeRed Adapters (ähnlich der fehlenden SendTo Funktionalität) habe ich nun ein Javascript geschrieben, dass die Möglichkeiten des $-Selectors im Blockly und im JS abbildet.
Dies zielt vor allem darauf IDs für die Räume und Funktionen definiert sind, über den $-Selektor auszuwählen.
Folgendes JS muss importiert werden und immer laufen:
// @ts-nocheck /** * Zweck: Nutzt die Möglichkeiten des selectors für Node-Red * Datum: 26.09.2023 * Autor: @mickym */ // In die Variable exchangeWithNodeRed den Pfad des Datenpunktes auswählen, der als Trigger verwendet wird /********************************************************************************************************* * In den Datenpunkt muss ein Objekt von Node Red mit folgenden Eigenschaften übergeben werden: * { "topic": Selector Kommando, "payload": true = sends triggered events, false oder undefined = liefert nur Array mit ids und unsubscribed ids, "events" : Datenpunkt bei dem getriggerte Objekte zurückgeliefert werden. } * * */ var exchangeWithNodeRed = "0_userdata.0.NodeRed.selector"; on({id: exchangeWithNodeRed, change: 'any', ack: false},function (obj) { var val = JSON.parse(obj.state.val); var mySubscription = val.topic; if (!val.payload){ // if no payload or paylod = false, all ids will be returned as array and all ids will be unsubscribed var arr = []; $(val.topic).each(function (id) { arr.push(id); unsubscribe(id); }); // console.log(arr); Arrays mit Selectoren setState(exchangeWithNodeRed,JSON.stringify(arr),true); } if (val.payload) { // console.log("Events selected"); // Subscription of selector (val.topic) existsObject(val.events, function (err, isExists) { if (isExists){ $(val.topic).on(function(obj){ setState(val.events,JSON.stringify(obj),obj.state.ack); }); } }); } });
Folgende Anleitung.
Minimum - muss man als erstes einen Datenpunkt erstellen über den mit dem Javascript kommuniziert wird.
Den Pfad zu diesem Datenpunkt legt man am Anfang in dem Javascript fest:
var exchangeWithNodeRed = "0_userdata.0.NodeRed.selector";
In diesen Datenpunkt muss man mit Node-Red immer ein Objekt schreiben. Minimal wird ein topic mit dem Selector festgelegt:
In das topic trägt man den Selector ein, der die entsprechenden IDs als Array ausgibt.{ "topic": "(functions=light) [state.id=alias.0.schalter.*.on]" }
Es werden dann alle IDs als Array ausgegeben:
Das Array kann man dann aufsplitten und die entsprechenden Werte über die get-Node herausholen.
================================================================================
Um den Selector als Subscription zu benutzen - muss man folgendes Objekt in den Datenpunkt schreiben:
{ "topic": "(functions=light) [state.id=alias.0.schalter.*.on]", "payload": true, "events": "0_userdata.0.mwhelper.events" }
Wichtig ist hier die payload. Ist diese true, wird der Selector in topic abonniert (subscribed) - ist diese false dann werden die IDs nicht mehr abonniert (unsubscribed).
Unter events - muss ein Datenpunkt angegeben werden, über den die getriggerten Objekte ausgetauscht werden.
WICHTIG: Der Datenpunkt darf nicht derselbe sein, der zum Empfang der Kommandos verwendet wird also nicht der Datenpunkt, der unter exchangeWithNodeRed spezifiziert wurde.
Hat man Subscribed, dann werden über die vollständigen Objekte in diesen Datenpunkt geschrieben:
damit hat man auch die Möglichkeit auf die vorherigen Werte zuzugreifen, die die Standard iobroker-IN Node nicht liefert.
Über eine Change-Node kann man dann die gleiche Ausgabe wie bei der iobroker-IN Node ausgeben.
Wenn man die Datenpunkte selbst wählen will, dann hier den gesamte Flow zum Import:
[ { "id": "44d25d1b10b4fdc7", "type": "group", "z": "7e6af0015415146d", "name": "Only IDs", "style": { "label": true }, "nodes": [ "750e461453f800f9", "f6fd573ff1603ead", "29cb8341265af84f", "0fa964dcba3accf5", "6e680242a1f6e19e", "7ac2b919939c4d42", "9311df4790cdbe04", "80b7ca2866737936", "0c8bec3d3be48173", "b976bef4126c177a" ], "x": 54, "y": 2439, "w": 952, "h": 262 }, { "id": "750e461453f800f9", "type": "inject", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "Nur topic als Selector", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{\"topic\":\"(functions=light) [state.id=alias.0.schalter.*.on]\"}", "payloadType": "json", "x": 240, "y": 2480, "wires": [ [ "f6fd573ff1603ead" ] ] }, { "id": "f6fd573ff1603ead", "type": "json", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "", "property": "payload", "action": "", "pretty": false, "x": 430, "y": 2480, "wires": [ [ "29cb8341265af84f" ] ] }, { "id": "29cb8341265af84f", "type": "ioBroker out", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "", "topic": "0_userdata.0.NodeRed.selector", "ack": "false", "autoCreate": "false", "stateName": "", "role": "", "payloadType": "", "readonly": "", "stateUnit": "", "stateMin": "", "stateMax": "", "x": 650, "y": 2480, "wires": [] }, { "id": "0fa964dcba3accf5", "type": "ioBroker in", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "", "topic": "0_userdata.0.NodeRed.selector", "payloadType": "value", "onlyack": "update", "func": "all", "gap": "", "fireOnStart": "false", "outFormat": "MQTT", "x": 210, "y": 2540, "wires": [ [ "6e680242a1f6e19e" ] ] }, { "id": "6e680242a1f6e19e", "type": "json", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "", "property": "payload", "action": "", "pretty": false, "x": 430, "y": 2540, "wires": [ [ "7ac2b919939c4d42", "9311df4790cdbe04" ] ] }, { "id": "7ac2b919939c4d42", "type": "debug", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "IDs von Selector", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 600, "y": 2540, "wires": [] }, { "id": "9311df4790cdbe04", "type": "split", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "", "x": 590, "y": 2600, "wires": [ [ "0c8bec3d3be48173" ] ] }, { "id": "80b7ca2866737936", "type": "ioBroker get", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "", "topic": "", "attrname": "payload", "payloadType": "value", "errOnInvalidState": "nothing", "x": 580, "y": 2660, "wires": [ [ "b976bef4126c177a" ] ] }, { "id": "0c8bec3d3be48173", "type": "change", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "", "rules": [ { "t": "move", "p": "payload", "pt": "msg", "to": "topic", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 780, "y": 2600, "wires": [ [ "80b7ca2866737936" ] ] }, { "id": "b976bef4126c177a", "type": "debug", "z": "7e6af0015415146d", "g": "44d25d1b10b4fdc7", "name": "Gelesene Werte vom Selektor", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 830, "y": 2660, "wires": [] }, { "id": "66cd713bd728bf0b", "type": "group", "z": "7e6af0015415146d", "name": "Subscribe Selector", "style": { "label": true }, "nodes": [ "ce94710ba9138d5f", "b42a36143bf213d8", "9715126f03f7caba", "139ada8b966f92f4", "349a1def489caede", "832e54742b28340b", "98ee845ca189c433", "0b6c8da8ee75d1a4", "0fc809759e3593a2" ], "x": 54, "y": 2739, "w": 952, "h": 242 }, { "id": "ce94710ba9138d5f", "type": "inject", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "Subscribe Selector", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{\"topic\":\"(functions=light) [state.id=alias.0.schalter.*.on]\",\"payload\":true,\"events\":\"0_userdata.0.mwhelper.events\"}", "payloadType": "json", "x": 250, "y": 2820, "wires": [ [ "b42a36143bf213d8" ] ] }, { "id": "b42a36143bf213d8", "type": "json", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "", "property": "payload", "action": "", "pretty": false, "x": 510, "y": 2800, "wires": [ [ "9715126f03f7caba" ] ] }, { "id": "9715126f03f7caba", "type": "ioBroker out", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "", "topic": "0_userdata.0.NodeRed.selector", "ack": "false", "autoCreate": "false", "stateName": "", "role": "", "payloadType": "", "readonly": "", "stateUnit": "", "stateMin": "", "stateMax": "", "x": 750, "y": 2800, "wires": [] }, { "id": "139ada8b966f92f4", "type": "ioBroker in", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "", "topic": "0_userdata.0.mwhelper.events", "payloadType": "value", "onlyack": "", "func": "all", "gap": "", "fireOnStart": "false", "outFormat": "MQTT", "x": 210, "y": 2880, "wires": [ [ "349a1def489caede" ] ] }, { "id": "349a1def489caede", "type": "json", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "", "property": "payload", "action": "", "pretty": false, "x": 450, "y": 2880, "wires": [ [ "832e54742b28340b", "98ee845ca189c433" ] ] }, { "id": "832e54742b28340b", "type": "debug", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "Geändertes Objekt", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 630, "y": 2880, "wires": [] }, { "id": "98ee845ca189c433", "type": "change", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "iobroker IN", "rules": [ { "t": "set", "p": "topic", "pt": "msg", "to": "payload.id", "tot": "msg" }, { "t": "set", "p": "payload", "pt": "msg", "to": "payload.state.val", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 610, "y": 2940, "wires": [ [ "0b6c8da8ee75d1a4" ] ] }, { "id": "0b6c8da8ee75d1a4", "type": "debug", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "triggered nach Selector", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 850, "y": 2940, "wires": [] }, { "id": "0fc809759e3593a2", "type": "inject", "z": "7e6af0015415146d", "g": "66cd713bd728bf0b", "name": "Unubscribe Selector", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{\"topic\":\"(functions=light) [state.id=alias.0.schalter.*.on]\",\"payload\":false}", "payloadType": "json", "x": 250, "y": 2780, "wires": [ [ "b42a36143bf213d8" ] ] } ]
Wenn man die Datenpunkte FIX in einen Subflow einträgt:
Hier habe ich folgende Datenpunkte gewählt:
0_userdata.0.NodeRed.selector 0_userdata.0.NodeRed.events
Den Subflow habe ich mal unter die iobroker-Nodes eingeordnet:
Triggert man diese Node mit
true: Dann verhält sich die Node- wie eine iobroker-IN Node mit dem Selector
false: Dann verhält sich die Node- wie eine iobroker-GET NodeDen Selector legt man in der Node fest:
Wie gesagt die Datenpunkte müssen hier fix im Subflow festgelegt werden.
Wer die Subflow- Node haben will kann diesen Flow importieren:
[ { "id": "6dc2a3eda2d93cdf", "type": "subflow", "name": "iobroker-in($)", "info": "", "category": "ioBroker", "in": [ { "x": 60, "y": 140, "wires": [ { "id": "d52d92d58461e38a" } ] } ], "out": [ { "x": 1320, "y": 220, "wires": [ { "id": "631e0e97cba8b845", "port": 0 }, { "id": "8496ffc343effdba", "port": 0 } ] } ], "env": [ { "name": "selector", "type": "str", "value": "(functions=light) [state.id=alias.0.schalter.*.on]" } ], "meta": {}, "color": "#A6BBCF", "icon": "node-red/arrow-in.svg" }, { "id": "d52d92d58461e38a", "type": "change", "z": "6dc2a3eda2d93cdf", "name": "", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "{\t \"topic\":$env(\"selector\"),\t \"payload\":payload,\t \"events\": \"0_userdata.0.NodeRed.events\"\t}", "tot": "jsonata" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 210, "y": 140, "wires": [ [ "d1a362cccfb80f62" ] ] }, { "id": "84dc903929a49984", "type": "ioBroker out", "z": "6dc2a3eda2d93cdf", "name": "", "topic": "0_userdata.0.NodeRed.selector", "ack": "false", "autoCreate": "false", "stateName": "", "role": "", "payloadType": "", "readonly": "", "stateUnit": "", "stateMin": "", "stateMax": "", "x": 630, "y": 140, "wires": [] }, { "id": "d1a362cccfb80f62", "type": "json", "z": "6dc2a3eda2d93cdf", "name": "", "property": "payload", "action": "", "pretty": false, "x": 410, "y": 140, "wires": [ [ "84dc903929a49984" ] ] }, { "id": "479b9273744c9deb", "type": "ioBroker in", "z": "6dc2a3eda2d93cdf", "name": "", "topic": "0_userdata.0.NodeRed.selector", "payloadType": "value", "onlyack": "update", "func": "all", "gap": "", "fireOnStart": "false", "outFormat": "MQTT", "x": 210, "y": 240, "wires": [ [ "ac63e3d0e5bc122e" ] ] }, { "id": "fd4cf4c227103e8f", "type": "ioBroker in", "z": "6dc2a3eda2d93cdf", "name": "", "topic": "0_userdata.0.NodeRed.events", "payloadType": "value", "onlyack": "update", "func": "all", "gap": "", "fireOnStart": "false", "outFormat": "MQTT", "x": 220, "y": 300, "wires": [ [ "ac63e3d0e5bc122e" ] ] }, { "id": "ac63e3d0e5bc122e", "type": "json", "z": "6dc2a3eda2d93cdf", "name": "", "property": "payload", "action": "", "pretty": false, "x": 450, "y": 260, "wires": [ [ "bc6e58ac8e2aac04" ] ] }, { "id": "bc6e58ac8e2aac04", "type": "switch", "z": "6dc2a3eda2d93cdf", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "istype", "v": "object", "vt": "object" }, { "t": "istype", "v": "array", "vt": "array" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 610, "y": 260, "wires": [ [ "8496ffc343effdba" ], [ "93218c9289da2a66" ] ] }, { "id": "93218c9289da2a66", "type": "split", "z": "6dc2a3eda2d93cdf", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "", "x": 750, "y": 300, "wires": [ [ "db73f767b00490d9" ] ] }, { "id": "db73f767b00490d9", "type": "change", "z": "6dc2a3eda2d93cdf", "name": "", "rules": [ { "t": "move", "p": "payload", "pt": "msg", "to": "topic", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 940, "y": 300, "wires": [ [ "631e0e97cba8b845" ] ] }, { "id": "631e0e97cba8b845", "type": "ioBroker get", "z": "6dc2a3eda2d93cdf", "name": "", "topic": "", "attrname": "payload", "payloadType": "value", "errOnInvalidState": "nothing", "x": 1160, "y": 300, "wires": [ [] ] }, { "id": "8496ffc343effdba", "type": "change", "z": "6dc2a3eda2d93cdf", "name": "iobroker IN", "rules": [ { "t": "set", "p": "topic", "pt": "msg", "to": "payload.id", "tot": "msg" }, { "t": "set", "p": "payload", "pt": "msg", "to": "payload.state.val", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 770, "y": 220, "wires": [ [] ] }, { "id": "1f8b194868f1a7e6", "type": "subflow:6dc2a3eda2d93cdf", "z": "7e6af0015415146d", "name": "", "x": 770, "y": 3140, "wires": [ [ "f6169149b3bf40b5" ] ] }, { "id": "d0d9a9a29907ce64", "type": "inject", "z": "7e6af0015415146d", "name": "", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "true", "payloadType": "bool", "x": 570, "y": 3120, "wires": [ [ "1f8b194868f1a7e6" ] ] }, { "id": "a7600adda853d7a6", "type": "inject", "z": "7e6af0015415146d", "name": "", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "false", "payloadType": "bool", "x": 570, "y": 3160, "wires": [ [ "1f8b194868f1a7e6" ] ] }, { "id": "f6169149b3bf40b5", "type": "debug", "z": "7e6af0015415146d", "name": "Ausgabe", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 940, "y": 3140, "wires": [] } ]