Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. Node-Red
    5. NodeRed - SendTo Proxy mit JS

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    NodeRed - SendTo Proxy mit JS

    This topic has been deleted. Only users with topic management privileges can see it.
    • mickym
      mickym Most Active last edited by

      Neuer Thread - um die fehlende Funktion der sendTo Funktionalität an diverse Adapter auszugleichen, habe ich ein kleines Javascript verfasst.

      https://github.com/ioBroker/ioBroker.node-red/issues/291

      Dazu legt man einen Datenpunkt unter 0_userdata.0 an und bekommt das Ergebnis entweder in dem gleichen Datenpunkt oder in unterschiedlichen Datenpunkten.

      So kann man für verschiedene Abfragen immer den gleichen Eingangs (Query) Datenpunkt nehmen, aber auch unterschiedliche Ausgangspunkte.

      Apollon77 created this issue in ioBroker/ioBroker.node-red

      closed Add "sendTo" Node to send messages to adapters #291

      1 Reply Last reply Reply Quote 1
      • mickym
        mickym Most Active last edited by mickym

        So nun im Detail - hier das Javascript, dass man importieren muss und das stellvertretend für NodeRed - die Nachricht an den entsprechenden Adapter schickt:

        EDIT - so noch ein paar kleine Nacharbeiten notwendig - da man ja nur Strings durch die Gegend schicken darf und keine Objekte:

        Manche Adapter liefern ja auch gar nichts zurück.

        So hier nun das Javascript - was natürlich immer aktiv bleiben muss. 😉

        /**
        * Zweck:      Setzt für einen NodeRed Flow - SendTo Kommandos an verschiedene Adapter ab
        * Datum:      17.08.2022
        * 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:
         *  {
            "adapter": <Adapterinstanz oder Adapter z.Bsp mqtt.0, sql.0>,
            "command": <Kommando - hängt vom jeweilige Adapter ab - bei sql zum Beispiel query, bei manchen Adaptern auch nicht erforderlich>,
            "message": <Nachricht, die an den Adapter geschickt wird>,
            "result": <optional: Pfad zum Datenpunkt, wo das Ergebnis als String abgespeichert wird, ansonsten wird der Trigger als Ausgabepunkt verwendet>
            }
         * 
         * 
        */
        var exchangeWithNodeRed = "0_userdata.0.NodeRed.sendTo";
        
        on({id: exchangeWithNodeRed, change: 'any', ack: false},function (obj) {
        
            // console.log(obj.state.val);
            var val = JSON.parse(obj.state.val);
           
            var returnResult;
        
            // console.log("adapter: " + val.adapter);
            // console.log("command: " + val.command);
            // console.log("message: " + val.message);
            // console.log("result: " + val.result); 
        
            if (val.result === undefined) returnResult = exchangeWithNodeRed; else returnResult =val.result;
         
            if (val.command === undefined){
                // console.log("no command");
                sendTo(val.adapter,val.message,function (result) {
                    if (result.error) setState(returnResult,result.error,true); else setState(returnResult,JSON.stringify(result.result),true);
                    })
            } else {
                // console.log("command: " + val.command);
                sendTo(val.adapter, val.command, val.message, function (result) {
                    if (result.error) setState(returnResult,result.error,true); else setState(returnResult,JSON.stringify(result.result),true);
                });
        
            }
          
        });
        

        Wie gesagt ich habe immer den gleichen Datenpunkt für die sendTo Funktion verwendet und ggf. unterschiedliche Rückgabe Punkte muss aber nicht sein.

        Schauen wir uns mal an, wie man so über den MQTT-Adapter Nachrichten published:

        d954535f-f627-4f71-8126-c89a2d4dc9a3-image.png

        Herzstück für alle Abfragen zu einem Adapter ist die Change-Node, daraus wird dann das Objekt gemacht, dass als JSON zu dem Austauschdatenpunkt geschickt wird.:
        3ca0ad5c-4dec-49cf-a63b-a339c8a7c194-image.png

        Hier nun eine Beispiel mit Rückgabe anhand des SQL-Adapters:

        Hier die SQL Abfrage:
        2a6c3ee2-67f2-4e78-beff-abbb446f2b9a-image.png

        und hier die Change-Node:
        ec5cfc60-2365-480b-879a-5cd2e60b4da1-image.png

        einmal direkt das Ergebnis geholt oder einen neuen Flow triggern lassen:

        10bb24fb-1849-4c07-8251-97196c332a38-image.png

        Hier mal alles zum Import:

        [
           {
               "id": "7ae04fc8f05dccd4",
               "type": "inject",
               "z": "30f50cdc81f34302",
               "name": "SQL Query",
               "props": [
                   {
                       "p": "payload"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "",
               "payload": "SELECT  id,name FROM iobroker.sources",
               "payloadType": "str",
               "x": 120,
               "y": 140,
               "wires": [
                   [
                       "905eccb6718c33b1"
                   ]
               ]
           },
           {
               "id": "fd62cf142cca7aec",
               "type": "ioBroker out",
               "z": "30f50cdc81f34302",
               "name": "sendTo",
               "topic": "0_userdata.0.NodeRed.sendTo",
               "ack": "false",
               "autoCreate": "false",
               "stateName": "",
               "role": "",
               "payloadType": "",
               "readonly": "",
               "stateUnit": "",
               "stateMin": "",
               "stateMax": "",
               "x": 680,
               "y": 100,
               "wires": []
           },
           {
               "id": "905eccb6718c33b1",
               "type": "change",
               "z": "30f50cdc81f34302",
               "name": "send to SQL Adapter",
               "rules": [
                   {
                       "t": "set",
                       "p": "sendTo",
                       "pt": "msg",
                       "to": "{\"adapter\":\"sql.0\",\"command\":\"query\",\"message\":\"\",\"result\":\"0_userdata.0.mwhelper.result\"}",
                       "tot": "json"
                   },
                   {
                       "t": "move",
                       "p": "payload",
                       "pt": "msg",
                       "to": "sendTo.message",
                       "tot": "msg"
                   },
                   {
                       "t": "move",
                       "p": "sendTo",
                       "pt": "msg",
                       "to": "payload",
                       "tot": "msg"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 320,
               "y": 140,
               "wires": [
                   [
                       "7d4d17c1c3e3505e",
                       "d57ea069d151e7b0",
                       "40233502982b276a"
                   ]
               ]
           },
           {
               "id": "e43c264b5f15ecb0",
               "type": "debug",
               "z": "30f50cdc81f34302",
               "name": "SQL result",
               "active": true,
               "tosidebar": true,
               "console": false,
               "tostatus": false,
               "complete": "payload",
               "targetType": "msg",
               "statusVal": "",
               "statusType": "auto",
               "x": 1070,
               "y": 160,
               "wires": []
           },
           {
               "id": "d57ea069d151e7b0",
               "type": "delay",
               "z": "30f50cdc81f34302",
               "name": "",
               "pauseType": "delay",
               "timeout": "250",
               "timeoutUnits": "milliseconds",
               "rate": "1",
               "nbRateUnits": "1",
               "rateUnits": "second",
               "randomFirst": "1",
               "randomLast": "5",
               "randomUnits": "seconds",
               "drop": false,
               "allowrate": false,
               "outputs": 1,
               "x": 580,
               "y": 160,
               "wires": [
                   [
                       "b811d795d4530384"
                   ]
               ]
           },
           {
               "id": "b811d795d4530384",
               "type": "ioBroker get",
               "z": "30f50cdc81f34302",
               "name": "result",
               "topic": "0_userdata.0.mwhelper.result",
               "attrname": "payload",
               "payloadType": "value",
               "errOnInvalidState": "nothing",
               "x": 770,
               "y": 160,
               "wires": [
                   [
                       "c39ef769f6c3a5ce"
                   ]
               ]
           },
           {
               "id": "c39ef769f6c3a5ce",
               "type": "json",
               "z": "30f50cdc81f34302",
               "name": "",
               "property": "payload",
               "action": "",
               "pretty": false,
               "x": 910,
               "y": 160,
               "wires": [
                   [
                       "e43c264b5f15ecb0"
                   ]
               ]
           },
           {
               "id": "89d24fa9dae59aa1",
               "type": "change",
               "z": "30f50cdc81f34302",
               "name": "send to MQTT Adapter",
               "rules": [
                   {
                       "t": "set",
                       "p": "sendTo",
                       "pt": "msg",
                       "to": "{\"adapter\":\"mqtt.1\",\"command\":\"sendMessage2Client\"}",
                       "tot": "json"
                   },
                   {
                       "t": "move",
                       "p": "payload",
                       "pt": "msg",
                       "to": "sendTo.message",
                       "tot": "msg"
                   },
                   {
                       "t": "move",
                       "p": "sendTo",
                       "pt": "msg",
                       "to": "payload",
                       "tot": "msg"
                   }
               ],
               "action": "",
               "property": "",
               "from": "",
               "to": "",
               "reg": false,
               "x": 380,
               "y": 440,
               "wires": [
                   [
                       "c869e86385c28208",
                       "eefe9b5106617c53"
                   ]
               ]
           },
           {
               "id": "64b709dff7660a6f",
               "type": "ioBroker out",
               "z": "30f50cdc81f34302",
               "name": "sendTo",
               "topic": "0_userdata.0.NodeRed.sendTo",
               "ack": "false",
               "autoCreate": "false",
               "stateName": "",
               "role": "",
               "payloadType": "",
               "readonly": "",
               "stateUnit": "",
               "stateMin": "",
               "stateMax": "",
               "x": 740,
               "y": 440,
               "wires": []
           },
           {
               "id": "66308db5f4cf558c",
               "type": "inject",
               "z": "30f50cdc81f34302",
               "name": "Publish mqtt topic",
               "props": [
                   {
                       "p": "payload"
                   }
               ],
               "repeat": "",
               "crontab": "",
               "once": false,
               "onceDelay": 0.1,
               "topic": "",
               "payload": "{\"topic\":\"your/topic/here2\",\"message\":\"Testnachricht\"}",
               "payloadType": "json",
               "x": 150,
               "y": 440,
               "wires": [
                   [
                       "89d24fa9dae59aa1"
                   ]
               ]
           },
           {
               "id": "165dc0884f716439",
               "type": "debug",
               "z": "30f50cdc81f34302",
               "name": "MQTT topic",
               "active": true,
               "tosidebar": true,
               "console": false,
               "tostatus": false,
               "complete": "payload",
               "targetType": "msg",
               "statusVal": "",
               "statusType": "auto",
               "x": 370,
               "y": 480,
               "wires": []
           },
           {
               "id": "7d4d17c1c3e3505e",
               "type": "json",
               "z": "30f50cdc81f34302",
               "name": "",
               "property": "payload",
               "action": "",
               "pretty": false,
               "x": 530,
               "y": 100,
               "wires": [
                   [
                       "fd62cf142cca7aec"
                   ]
               ]
           },
           {
               "id": "c869e86385c28208",
               "type": "json",
               "z": "30f50cdc81f34302",
               "name": "",
               "property": "payload",
               "action": "",
               "pretty": false,
               "x": 590,
               "y": 440,
               "wires": [
                   [
                       "64b709dff7660a6f"
                   ]
               ]
           },
           {
               "id": "c610499ae23a8d3d",
               "type": "comment",
               "z": "30f50cdc81f34302",
               "name": "Abfrage über den iobroker SQL Adapter",
               "info": "",
               "x": 210,
               "y": 40,
               "wires": []
           },
           {
               "id": "e33198f610486456",
               "type": "comment",
               "z": "30f50cdc81f34302",
               "name": "Abfrage über den iobroker MQTT Adapter",
               "info": "",
               "x": 220,
               "y": 380,
               "wires": []
           },
           {
               "id": "eefe9b5106617c53",
               "type": "debug",
               "z": "30f50cdc81f34302",
               "name": "sendTo",
               "active": true,
               "tosidebar": true,
               "console": false,
               "tostatus": false,
               "complete": "payload",
               "targetType": "msg",
               "statusVal": "",
               "statusType": "auto",
               "x": 600,
               "y": 400,
               "wires": []
           },
           {
               "id": "a53a3929530a7a45",
               "type": "ioBroker in",
               "z": "30f50cdc81f34302",
               "name": "",
               "topic": "0_userdata.0.mwhelper.result",
               "payloadType": "value",
               "onlyack": "update",
               "func": "all",
               "gap": "",
               "fireOnStart": "false",
               "outFormat": "MQTT",
               "x": 180,
               "y": 260,
               "wires": [
                   [
                       "50cc942afbf9b4b6"
                   ]
               ]
           },
           {
               "id": "d10d14fa1999d81c",
               "type": "debug",
               "z": "30f50cdc81f34302",
               "name": "SQL Ergebnis, wenn fertig",
               "active": true,
               "tosidebar": true,
               "console": false,
               "tostatus": false,
               "complete": "payload",
               "targetType": "msg",
               "statusVal": "",
               "statusType": "auto",
               "x": 590,
               "y": 260,
               "wires": []
           },
           {
               "id": "50cc942afbf9b4b6",
               "type": "json",
               "z": "30f50cdc81f34302",
               "name": "",
               "property": "payload",
               "action": "",
               "pretty": false,
               "x": 390,
               "y": 260,
               "wires": [
                   [
                       "d10d14fa1999d81c"
                   ]
               ]
           },
           {
               "id": "40233502982b276a",
               "type": "debug",
               "z": "30f50cdc81f34302",
               "name": "sendTo",
               "active": true,
               "tosidebar": true,
               "console": false,
               "tostatus": false,
               "complete": "payload",
               "targetType": "msg",
               "statusVal": "",
               "statusType": "auto",
               "x": 540,
               "y": 60,
               "wires": []
           }
        ]
        

        1 Reply Last reply Reply Quote 2
        • mickym
          mickym Most Active last edited by

          Es empfiehlt sich im Übrigen den Datenpunkt zum Austausch als Typ JSON zu definieren:

          8061764e-d3c0-4e80-aa17-070b22b56ee1-image.png

          Damit kann man das Script natürlich dann ohne NodeRed schon mal vortesten. 😉

          S 1 Reply Last reply Reply Quote 1
          • S
            Sineos @mickym last edited by Sineos

            @mickym Sehr elegante Lösung 👍

            Ich habe Beispiele wo auch message leer sein kann. Dann rennt das Script auf Fehler. Habs mal so gelöst (Zeile 43):

            
            /**
            * Zweck:      Setzt für einen NodeRed Flow - SendTo Kommandos an verschiedene Adapter ab
            * Datum:      17.08.2022
            * 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:
             *  {
                "adapter": <Adapterinstanz oder Adapter z.Bsp mqtt.0, sql.0>,
                "command": <Kommando - hängt vom jeweilige Adapter ab - bei sql zum Beispiel query, bei manchen Adaptern auch nicht erforderlich>,
                "message": <Nachricht, die an den Adapter geschickt wird>,
                "result": <optional: Pfad zum Datenpunkt, wo das Ergebnis als String abgespeichert wird, ansonsten wird der Trigger als Ausgabepunkt verwendet>
                }
             *
             *
            */
            
            const exchangeWithNodeRed = '0_userdata.0.NodeRed.sendTo';
            
            on({id: exchangeWithNodeRed, change: 'any', ack: false}, function(obj) {
              console.log(obj.state.val);
              const val = JSON.parse(obj.state.val);
              let returnResult;
              //console.log('adapter: ' + val.adapter);
              //console.log('command: ' + val.command);
              //console.log('message: ' + val.message);
              //console.log('result: ' + val.result);
            
              if (!val.result) returnResult = exchangeWithNodeRed;
              else returnResult = val.result;
              if (!val.command){
                //console.log('no command');
                sendTo(val.adapter, val.message, function(result) {
                  if (result.error) setState(returnResult, result.error, true); 
                  else setState(returnResult, JSON.stringify(result.result), true);
                });
              } else {
                //console.log('command: ' + val.command);
                sendTo(val.adapter, val.command, val.message? val.message : {}, function(result) {
                  if (result.error) setState(returnResult, result.error, true);
                  else setState(returnResult, JSON.stringify(result.result), true);
                });
              }
            });
            
            
            mickym 1 Reply Last reply Reply Quote 0
            • mickym
              mickym Most Active @Sineos last edited by

              @sineos Aha 😉 - Muss dass dann ein leeres Objekt sein oder kann es auch ein leerer String sein? - nur halt nicht undefined nehme ich mal an.

              S 1 Reply Last reply Reply Quote 0
              • S
                Sineos @mickym last edited by

                @mickym Das ist wohl ein bisschen abhängig davon, was der Adapter erwartet. Die homematic rssiInfo Methode erwartet ein Objekt.

                mickym 1 Reply Last reply Reply Quote 0
                • mickym
                  mickym Most Active @Sineos last edited by

                  @sineos Dann würde ich aber nicht den JS Code ändern, sondern belassen und aus NodeRed ein leeres Objekt als message mitgeben.

                  S 1 Reply Last reply Reply Quote 0
                  • S
                    Sineos @mickym last edited by

                    @mickym Stimmt, auch ne Möglichkeit. Sogar die flexiblere. 👍

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post

                    Support us

                    ioBroker
                    Community Adapters
                    Donate

                    994
                    Online

                    31.7k
                    Users

                    79.8k
                    Topics

                    1.3m
                    Posts

                    2
                    8
                    641
                    Loading More Posts
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes
                    Reply
                    • Reply as topic
                    Log in to reply
                    Community
                    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                    The ioBroker Community 2014-2023
                    logo