I cant use join node in my project in Nodered

Reference Topic:
Exec command using function node in NodeRED - General - Node-RED Forum
This topic is not getting response so i have to create a new one and i have a issue mentioned in that topic which says that join node is giving me unwanted data due to After a number of message parts set to 24 this leads to a problem. So, I am explaining you my issue again i have 3 RTD HAT which have 8 ports each for temp sensors, so when i connect 3 RTD HAT i get 24 temp Sensors from this code which is given by @jbudd it works well till this.


[{"id":"246b29e8a1e83da8","type":"tab","label":"Flow 3","disabled":false,"info":"","env":[]},{"id":"d5ae235057454821","type":"group","z":"246b29e8a1e83da8","name":"24 Discrete Commands - No Need For Split!","style":{"label":true},"nodes":["f7c49f5d17e518bf","9207bd218eacab96","c7ca2dbd434c8ea8","69ec1362b364ab2c","02609ea7b4a2ab06","40688440afc0037c","3ce268ef3a5ec6fb","73750f83d4e0afd5","65717d848a8a7eaf"],"x":34,"y":219,"w":952,"h":162},{"id":"0781401244ccfb7c","type":"group","z":"246b29e8a1e83da8","name":"One Very Long Command With &&.  ","style":{"label":true},"nodes":["af25b8098c19c102","eff4574f0d6fb3b2","81d51c83bee6e104","86e3d79acaf2f4a3","95314a9b07d2c18a","07450de398d37621","abd0ed563e6e6fb7","b593b241aa9651f1","73b8a1762ff0f7b2"],"x":34,"y":39,"w":952,"h":149.5},{"id":"b593b241aa9651f1","type":"comment","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"One very long command","info":"","x":190,"y":80,"wires":[]},{"id":"af25b8098c19c102","type":"function","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"One command with &&","func":"var cmd = 'rtd 0 read 1';\nvar cmd1 = 'rtd 0 read 2';\nvar cmd2 = 'rtd 0 read 3';\nvar cmd3 = 'rtd 0 read 4';\nvar cmd4 = 'rtd 0 read 5';\nvar cmd5 = 'rtd 0 read 6';\nvar cmd6 = 'rtd 0 read 7';\nvar cmd7 = 'rtd 0 read 8';\nvar cmd8 = 'rtd 1 read 1';\nvar cmd9 = 'rtd 1 read 2';\nvar cmd10 = 'rtd 1 read 3';\nvar cmd11 = 'rtd 1 read 4';\nvar cmd12 = 'rtd 1 read 5';\nvar cmd13 = 'rtd 1 read 6';\nvar cmd14 = 'rtd 1 read 7';\nvar cmd15 = 'rtd 1 read 8';\nvar cmd16 = 'rtd 2 read 1';\nvar cmd17 = 'rtd 2 read 2';\nvar cmd18 = 'rtd 2 read 3';\nvar cmd19 = 'rtd 2 read 4';\nvar cmd20 = 'rtd 2 read 5';\nvar cmd21 = 'rtd 2 read 6';\nvar cmd22 = 'rtd 2 read 7';\nvar cmd23 = 'rtd 2 read 8';\n\nmsg.payload = cmd + '&&' + cmd1 + '&&' + cmd2 + '&&' + cmd3 + '&&' + cmd4 + '&&' + cmd5 + '&&' + cmd6 + '&&' + cmd7 + '&&' + cmd8 + '&&' + cmd9 + '&&' + cmd10 + '&&' + cmd11 + '&&' + cmd12 + '&&' + cmd13 + '&&' + cmd14 + '&&' + cmd15 + '&&' + cmd16 + '&&' + cmd17 + '&&' + cmd18 + '&&' + cmd19 + '&&' + cmd20 + '&&' + cmd21 + '&&' + cmd22 + '&&' + cmd23\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":140,"wires":[["86e3d79acaf2f4a3"]]},{"id":"eff4574f0d6fb3b2","type":"inject","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":140,"wires":[["af25b8098c19c102"]]},{"id":"81d51c83bee6e104","type":"debug","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"debug 230","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":80,"wires":[]},{"id":"86e3d79acaf2f4a3","type":"exec","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","command":"","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":650,"y":140,"wires":[["abd0ed563e6e6fb7"],["73b8a1762ff0f7b2"],[]]},{"id":"95314a9b07d2c18a","type":"split","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":610,"y":80,"wires":[["07450de398d37621"]]},{"id":"07450de398d37621","type":"join","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"1","count":"24","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":730,"y":80,"wires":[["81d51c83bee6e104"]]},{"id":"f7c49f5d17e518bf","type":"function","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"24 discrete commands","func":"for (let rtd = 0; rtd < 3; rtd++) {\n    for (let read = 1; read < 9; read++) {\n        node.send({ payload: `rtd ${rtd} read ${read}` })\n    }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":320,"wires":[["40688440afc0037c"]]},{"id":"9207bd218eacab96","type":"inject","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":320,"wires":[["f7c49f5d17e518bf"]]},{"id":"c7ca2dbd434c8ea8","type":"debug","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"debug 231","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":260,"wires":[]},{"id":"69ec1362b364ab2c","type":"exec","z":"246b29e8a1e83da8","g":"d5ae235057454821","command":"","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":650,"y":320,"wires":[["3ce268ef3a5ec6fb"],["65717d848a8a7eaf"],[]]},{"id":"02609ea7b4a2ab06","type":"join","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"1","count":"24","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":730,"y":260,"wires":[["c7ca2dbd434c8ea8"]]},{"id":"abd0ed563e6e6fb7","type":"function","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"Remove new lines from response","func":"msg.payload = msg.payload.trim()\nif (msg.payload)\n    return msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":80,"wires":[["95314a9b07d2c18a"]]},{"id":"40688440afc0037c","type":"delay","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"Rate limit","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"4","nbRateUnits":"0.1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":520,"y":320,"wires":[["69ec1362b364ab2c"]]},{"id":"3ce268ef3a5ec6fb","type":"function","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"Remove new lines from responses","func":"msg.payload = msg.payload.trim()\nif (msg.payload)\n    return msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":260,"wires":[["02609ea7b4a2ab06"]]},{"id":"73750f83d4e0afd5","type":"comment","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"Rate Limit may not be needed","info":"","x":840,"y":340,"wires":[]},{"id":"73b8a1762ff0f7b2","type":"debug","z":"246b29e8a1e83da8","g":"0781401244ccfb7c","name":"Errors?","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":860,"y":140,"wires":[]},{"id":"65717d848a8a7eaf","type":"debug","z":"246b29e8a1e83da8","g":"d5ae235057454821","name":"Errors?","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":860,"y":300,"wires":[]}]

but when i remove 1 RTD HAT and it get from 24 to 16 then it gives me some wrong information which is not valid because the join node sends message 24 i have to manual change every time if i remove the RTD HAT which is not a solution in this. is there any other solution to join msg without join node.

These sections of the Join node help might give you some ideas:

A timeout can be set to trigger sending the new message using whatever has been received so far. This timeout can be restarted by sending a message with the msg.restartTimeout property set.

If a message is received with the msg.complete property set, the output message is finalised and sent. This resets any part counts.

If a message is received with the msg.reset property set, the partly complete message is deleted and not sent. This resets any part counts.

but how to write it

Aye, there's the rub.

Probably depends if you can work out how many hats are connected to the Pi.

sometimes 3 or 2 Hat so i dont want to go to join node set less number of message and deploy and if 3 hat connect again go to join and do it, that not possible, if i am getting different msg which is joining properly but at some point it gets wrong then is there any other way to write in function node like if else

@jbudd i write this function in if else it give me proper sperate msg which is working fine but i just need to join it in array without using join node


[{"id":"69429f4b761ef0b0","type":"tab","label":"Flow 4","disabled":false,"info":"","env":[]},{"id":"e25fd6b450fe29fc","type":"function","z":"69429f4b761ef0b0","name":"24 discrete commands","func":"if (msg.payload === 2) {\n    for (let rtd = 0; rtd < 3; rtd++) {\n        for (let read = 1; read < 9; read++) {\n            node.send({ payload: `rtd ${rtd} read ${read}` })\n        }\n    }\n} else if (msg.payload === 1) {\n    for (let rtd = 0; rtd  < 2; rtd++) {\n        for (let read = 1; read < 9; read++) {\n            node.send({ payload: `rtd ${rtd} read ${read}` })\n        }\n    }\n}\nelse if (msg.payload === 0) {\n    for (let rtd = 0; rtd <1; rtd++) {\n        for (let read = 1; read < 9; read++) {\n            node.send({ payload: `rtd ${rtd} read ${read}` })\n        }\n    }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":220,"y":180,"wires":[["6b12bc55b2f1d9fd"]]},{"id":"0b01b654bacc138d","type":"inject","z":"69429f4b761ef0b0","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":210,"y":120,"wires":[["e25fd6b450fe29fc"]]},{"id":"4ed0f3ac5ad5d32b","type":"debug","z":"69429f4b761ef0b0","name":"debug 239","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":340,"wires":[]},{"id":"6b12bc55b2f1d9fd","type":"function","z":"69429f4b761ef0b0","name":"function 19","func":"var exec = childProcess.exec;\n\nvar command1 = msg.payload;\nvar child1 = exec(command1, function (error, stdout, stderr) {\n    var payload1 = { payload: stdout };\n    node.send(payload1);\n\n});\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"childProcess","module":"child_process"}],"x":390,"y":240,"wires":[["153a91755e55106f"]]},{"id":"153a91755e55106f","type":"function","z":"69429f4b761ef0b0","name":"F2","func":"msg.payload = msg.payload.trim()\n    return msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":280,"wires":[["4ed0f3ac5ad5d32b"]]}]

so check and tell me in this i use inject node to set 0, 1, 2 for RTD HAT its just example

Why do you need to join them?

to call it sperate in uibuilder for gauges

You don't have to have them all in one message to show them in gauges, unless I misunderstand something. You can feed them one at a time to the appropriate gauges.

How to show different msg in there gauges i am using uibuilder with canvas-gauge and i don't know how to do it

I don't know how to do that either, I don't use uibuilder, but provided each message is sent to uibuilder with an identifier to say which gauge it is to go to then I guarantee that it can be done.
Did you write the code for the uibuilder bit of your app?

There are so many different libraries - can you give a reference to this one? Are you using it with Vue or some other way?

uibuilder is a facilitator. In this case, it seems to me that you simply need to get the data over to the front-end. If the values for your gauges are linked, send them in 1 msg. If they are not, send them in multiple messages with an identifier (typically the msg.topic but it could be anything) so that your front-end code can detect which gauge it needs to update. (As I see Colin has also suggested).

In the front end, your 3 gauges also need their own identifiers - as does anything on a web page that needs to be dynamically updated. Though if you are using something like Vue, then you will simply want each gauge to be driven by a different responsive Vue data variable.

@TotallyInformation , the bellow is the HTML in uibuilder

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./gauge.min.js"></script>

    <style>
        .canvas-container {
            display: contents;
        }

        .canvas {
            width: 24% !important;
            /* adjust as needed */
            height: auto !important;
            /* adjust as needed */
        }

        @media (max-width: 600px) {
            .canvas {
                width: 50% !important;
                height: auto !important;

            }

            .bod {
                display: table-row;
            }
        }


        .sonnenMode {
            position: absolute;
            transform: translate(-50%, -50%);
            top: 50%;
            left: 50%;
        }
    </style>
</head>

<body class="bod">
    <div class="canvas-container" style=" align-items: center;">
        <canvas class="canvas" id="canvas" data-type="radial-gauge" data-width="300" data-height="300" data-units="°C"
            data-title="false" data-value= {{msg.payload}} data-min-value="0" data-max-value="320"
            data-major-ticks="0,40,80,120,160,200,240,280,320" data-minor-ticks="6" data-stroke-ticks="true"
            data-highlights='[
                    { "from": 0, "to": 60, "color": "rgba(0,255,0)" },
                    { "from": 60, "to": 80, "color": "rgba(255,255,0)" },
                    { "from": 80, "to": 100, "color": "rgba(255,0,0)" }
                ]' data-color-plate="#fff" data-border-shadow-width="0" data-borders="false" data-needle-type="arrow"
            data-needle-width="2" data-needle-circle-size="7" data-needle-circle-outer="true"
            data-needle-circle-inner="false" data-animation-duration="1500" data-animation-rule="linear"
            data-title={{msg.title}} data-value-Box="true" data-value-Int="2" data-value-Dec="2">
        </canvas>

        <canvas class="canvas" id="canvas" data-type="radial-gauge" data-width="300" data-height="300" data-units="°C"
            data-title="false" data-value={{msg.payload[0]}} data-min-value="0" data-max-value="320"
            data-major-ticks="0,40,80,120,160,200,240,280,320" data-minor-ticks="6" data-stroke-ticks="true"
            data-highlights='[
                    { "from": 0, "to": 60, "color": "rgba(0,255,0)" },
                    { "from": 60, "to": 80, "color": "rgba(255,255,0)" },
                    { "from": 80, "to": 100, "color": "rgba(255,0,0)" }
                ]' data-color-plate="#fff" data-border-shadow-width="0" data-borders="false" data-needle-type="arrow"
            data-needle-width="2" data-needle-circle-size="7" data-needle-circle-outer="true"
            data-needle-circle-inner="false" data-animation-duration="1500" data-animation-rule="linear"
            data-title={{msg.title}} data-value-Box="true" data-value-Int="2" data-value-Dec="2">
        </canvas>

        <canvas class="canvas" id="canvas" data-type="radial-gauge" data-width="300" data-height="300" data-units="°C"
            data-title="false" data-value={{msg.payload[0]}} data-min-value="0" data-max-value="320"
            data-major-ticks="0,40,80,120,160,200,240,280,320" data-minor-ticks="6" data-stroke-ticks="true"
            data-highlights='[
                    { "from": 0, "to": 60, "color": "rgba(0,255,0)" },
                    { "from": 60, "to": 80, "color": "rgba(255,255,0)" },
                    { "from": 80, "to": 100, "color": "rgba(255,0,0)" }
                ]' data-color-plate="#fff" data-border-shadow-width="0" data-borders="false" data-needle-type="arrow"
            data-needle-width="2" data-needle-circle-size="7" data-needle-circle-outer="true"
            data-needle-circle-inner="false" data-animation-duration="1500" data-animation-rule="linear"
            data-title={{msg.title}} data-value-Box="true" data-value-Int="2" data-value-Dec="2">
        </canvas>


        <canvas class="canvas" id="canvas" data-type="radial-gauge" data-width="300" data-height="300" data-units="°C"
            data-title="false" data-value={{msg.payload[0]}} data-min-value="0" data-max-value="320"
            data-major-ticks="0,40,80,120,160,200,240,280,320" data-minor-ticks="6" data-stroke-ticks="true"
            data-highlights='[
                    { "from": 0, "to": 60, "color": "rgba(0,255,0)" },
                    { "from": 60, "to": 80, "color": "rgba(255,255,0)" },
                    { "from": 80, "to": 100, "color": "rgba(255,0,0)" }
                ]' data-color-plate="#fff" data-border-shadow-width="0" data-borders="false" data-needle-type="arrow"
            data-needle-width="2" data-needle-circle-size="7" data-needle-circle-outer="true"
            data-needle-circle-inner="false" data-animation-duration="1500" data-animation-rule="linear"
            data-title={{msg.title}} data-value-Box="true" data-value-Int="2" data-value-Dec="2">
        </canvas>
    </div>

</body>
<script>
    uibuilder.onChange('msg', function(msg) {
        if (msg.topic === 'gauge') console.log(msg);
    });
</script>

</html>

And JS of the canvas-gauge here

<script src="//cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js"></script>

Nice - raw HTML, I like that. I'll have a closer look

Where are all the other dependencies? You've not loaded the uibuilder client and you appear to be using VueJS {{.....}} and haven't loaded that either.

Right, that didn't take long. You should note that the examples page does not seem to have fully working code.

html:

<!doctype html>
<html lang="en"><head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Canvas Gauges Example - Node-RED uibuilder</title>
    <meta name="description" content="Node-RED uibuilder - Canvas Gauges Example">
    <link rel="icon" href="./images/node-blue.ico">

    <!-- Your own CSS (defaults to loading uibuilders css)-->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all">

    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / - socket.io no longer needed  -->
    <script defer src="../uibuilder/uibuilder.iife.min.js"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/canvas-gauges@2.1.7/gauge.min.js"></script>
    <script defer src="./index.js">/* OPTIONAL: Put your custom code in that */</script>
    <!-- #endregion -->

</head><body class="uib">
    
    <h1>uibuilder Canvas Gauges Example</h1>

    <div id="more"><!-- '#more' is used as a parent for dynamic HTML content in examples --></div>

    <canvas id="gauge-radial-1"></canvas>

    <pre id="msg" class="syntax-highlight">Waiting for a message from Node-RED</pre>

</body></html>

index.js

// @ts-nocheck

'use strict'

var gauge = new RadialGauge({
    renderTo: 'gauge-radial-1'
}).draw()

// Listen for incoming messages from Node-RED
uibuilder.onChange('msg', function(msg) {
    // Dump the msg as text to the "msg" html element
    const eMsg = $('#msg')
    if (eMsg) eMsg.innerHTML = uibuilder.syntaxHighlight(msg)

    gauge.value = msg.payload
})

And the input is simply an inject node with the payload set to

$formatInteger($random() * 100, "0")

Using JSONata to give a random number between 0 and 100.

To extend to multiple gauges, each gauge should have its own id and you create a new gauge variable in js that points to it.

VERY simple to use with uibuilder and very nice. Certainly going in my toolkit.

PS: I used the gauges from the jsDelivr CDN but they are in an npm package so you can install using the uibuilder library manager and then reference as:

<script defer src="../uibuilder/vendor/canvas-gauges/gauge.min.js"></script>

i tried your code but its not giving the data to msg

Sorry, I don't understand. You mean that your inject node isn't producing what you think? Or something else?

inject is sending msg but uibuilder is not receiving it

You have used exactly the code I shared with you?

What version of uibuilder are you using?