Exec command using function node in NodeRED

hi there,

var exec = childProcess.exec;
var cmd = 'rtd 0 read 1';
var cmd1 = 'rtd 0 read 2';
var cmd2 = 'rtd 0 read 3';
var cmd3 = 'rtd 0 read 4';
var cmd4 = 'rtd 0 read 5';
var cmd5 = 'rtd 0 read 6';
var cmd6 = 'rtd 0 read 7';
var cmd7 = 'rtd 0 read 8';
var cmd8 = 'rtd 1 read 1';
var cmd9 = 'rtd 1 read 2';
var cmd10 = 'rtd 1 read 3';
var cmd11 = 'rtd 1 read 4';
var cmd12 = 'rtd 1 read 5';
var cmd13 = 'rtd 1 read 6';
var cmd14 = 'rtd 1 read 7';
var cmd15 = 'rtd 1 read 8';
var cmd16 = 'rtd 2 read 1';
var cmd17 = 'rtd 2 read 2';
var cmd18 = 'rtd 2 read 3';
var cmd19 = 'rtd 2 read 4';
var cmd20 = 'rtd 2 read 5';
var cmd21 = 'rtd 2 read 6';
var cmd22 = 'rtd 2 read 7';
var cmd23 = 'rtd 2 read 8';

if(msg.payload === 2){
    exec(cmd + '&&' + cmd1 + '&&' + cmd2 + '&&' + cmd3 + '&&' + cmd4 + '&&' + cmd5 + '&&' + cmd6 + '&&' + cmd7 + '&&' + cmd8 + '&&' + cmd9 + '&&' + cmd10 + '&&' + cmd11 +'&&'+ cmd12 + '&&' + cmd13 + '&&' + cmd14 + '&&' + cmd15 + '&&' + cmd16 + '&&' + cmd17 + '&&' + cmd18 + '&&' + cmd19 + '&&' + cmd20 + '&&' + cmd21 + '&&' + cmd22 + '&&' + cmd23, function (error, stdout, stderr) {
    if (error) {
        node.error(error);
    } else {
        var payload1 = stdout;
        msg.payload = payload1;
        node.send(msg);    }
});
}

This is my function code which is working well but the problem is how to define payload to payload1, payload2, payload3, etc. As i got output in this form
"690.909058↵23.228514↵690.909058↵-1210.389648↵690.909058↵690.909058↵635.344055↵-262.242004↵-1210.389648↵-1210.389648↵690.909058↵690.909058↵690.909058↵690.909058↵690.909058↵690.909058↵690.909058↵690.909058↵690.909058↵690.909058↵-300.958191↵690.909058↵690.909058↵690.909058↵"

and if i spit it then it sends multiple payload, but the issue is still there i need it specify multiple gauge to payload1, payload2, payload3, payload4 so gauge can read it.
please help me.
thank you

Hi @Jayeshpitale1. I'm not familiar with the use of childprocess.exec() in a Node-red function, indeed it does not work in my standard Node-red setup.

  1. Does your dashboard have 24 gauges?

  2. Why are you running these rtd commands in this way rather than via the exec node?

  3. Why don't you run the commands in a shell script via a single exec node?
    Your output data is unwieldy as a single multi-line string. If you used a shell script (or python) you would have more control over the output format.

  4. The string you posted above is more manageable if you split it then join as an array, giving you payload[0] .. payload[23].
    Why do you need payload1 .. payload24 rather than the above array elements?

If you build the array as suggested by @jbudd then in each gauge node you can select what you want to show, using the Value Format field. In there put payload[0] in the first node, payload[1] in the next and so on.

You are missing spaces - that might work in most cases but it might not in some cases.

It is also a very fragile way to try to run a bunch of commands since any one of them can simply make the whole thing fail. Would you even be able to tell which command failed? Is it important whether you can run the commands again? Perhaps at least consider splitting into smaller batches.

And yes, as mentioned by the others - you are doing a lot of work manually that you could have asked the computer to do for you by use of loops.

@jbudd

  1. Does your dashboard have 24 gauges?

1). Yes, I have 24 gauges which are in ui_template also they act as payload1..... Payload24. Means from payload1 to payload 24 they get the data.

  1. Why are you running these rtd commands in this way rather than via the exec node?

2). i have condition if else so i have to run it as this.

  1. Why don't you run the commands in a shell script via a single exec node?
    Your output data is unwieldy as a single multi-line string. If you used a shell script (or python) you would have more control over the output format.

3). I dont have experience with this, and i am still learning new thing in NodeRED.

  1. The string you posted above is more manageable if you split it then join as an array, giving you payload[0] .. payload[23].
    Why do you need payload1 .. payload24 rather than the above array elements?

4). i tried to split and join but it not working well.

Show us how you did it and what did not work well.

Can you expand on this? Show us your code. I think you may be making life unnecessarily difficult for yourself.

I see that there is a node to interact with Sequent Microsystems RTD card. node-red-contrib-sm-rtd Is this the card you have?

In function node you could use this instead:

const cmds = []
for (let rtd = 0; rtd < 3; rtd++) {
    for (let read = 0; read < 9; read++) {
        cmds.push(`rtd ${rtd} read ${read}`)
    }
}

msg.payload = cmds.join(" && ")

return msg;

Connect it to an exec node.

2). i have condition if else so i have to run it as this.

The exec node has 3 outputs. The 2nd output is the error output, use it.

image

Hi There, @bakman2
I have used your code but the issue is that
"rtd 1 read 0&&rtd 1 read 1&&rtd 1 read 2&&rtd 1 read 3&&rtd 1 read 4&&rtd 1 read 5&&rtd 1 read 6&&rtd 1 read 7&&rtd 1 read 8&&rtd 2 read 0&&rtd 2 read 1&&rtd 2 read 2&&rtd 2 read 3&&rtd 2 read 4&&rtd 2 read 5&&rtd 2 read 6&&rtd 2 read 7&&rtd 2 read 8"
this making exec in error mode which says this
/bin/bash: 1: command not found
Because it is giving all command in one string which is going wrong.

If you had accurately copied @bakman2's function node I would expect that your combined command would be

rtd 0 read 0 && rtd 0 read 1 && rtd 0 read 2 && rtd 0 read 3 && rtd 0 read 4 && rtd 0 read 5 && rtd 0 read 6 && rtd 0 read 7 && rtd 0 read 8 && rtd 1 read 0 && rtd 1 read 1 && rtd 1 read 2 && rtd 1 read 3 && rtd 1 read 4 && rtd 1 read 5 && rtd 1 read 6 && rtd 1 read 7 && rtd 1 read 8 && rtd 2 read 0 && rtd 2 read 1 && rtd 2 read 2 && rtd 2 read 3 && rtd 2 read 4 && rtd 2 read 5 && rtd 2 read 6 && rtd 2 read 7 && rtd 2 read 8

not

rtd 1 read 0&&rtd 1 read 1&&rtd 1 read 2&&rtd 1 read 3&&rtd 1 read 4&&rtd 1 read 5&&rtd 1 read 6&&rtd 1 read 7&&rtd 1 read 8&&rtd 2 read 0&&rtd 2 read 1&&rtd 2 read 2&&rtd 2 read 3&&rtd 2 read 4&&rtd 2 read 5&&rtd 2 read 6&&rtd 2 read 7&&rtd 2 read 8

However, the missing spaces around && should not make a difference when it's executed, and anyway /bin/bash: 1: command not found cannot come from this combined command.

So there is something odd going on.
Here is a simple flow

[{"id":"15aa69a805c52c76","type":"function","z":"246b29e8a1e83da8","name":"Create command","func":"const cmds = []\nfor (let rtd = 0; rtd < 3; rtd++) {\n    for (let read = 0; read < 9; read++) {\n        cmds.push(`rtd ${rtd} read ${read}`)\n    }\n}\n\nmsg.payload = cmds.join(\" && \")\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":180,"wires":[["27061fc6f82fdb5b"]]},{"id":"cac4f00477686190","type":"inject","z":"246b29e8a1e83da8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":180,"wires":[["15aa69a805c52c76"]]},{"id":"b86e1285fc0bf92d","type":"debug","z":"246b29e8a1e83da8","name":"Show result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":750,"y":160,"wires":[]},{"id":"27061fc6f82fdb5b","type":"exec","z":"246b29e8a1e83da8","command":"","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":570,"y":180,"wires":[["b86e1285fc0bf92d"],["4f90080647090a41"],[]]},{"id":"4f90080647090a41","type":"debug","z":"246b29e8a1e83da8","name":"Show errors","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":750,"y":200,"wires":[]}]

Can you copy the code above and import it to your Node-red (CTRL i, paste, Import), deploy and run it? Show us the output of the two debug nodes.

the rtd command is probably not available from the node red user path, most likely it requires the full path to the command

Don't think that's it. The OP has already been running rtd from his function.

Hi there @jbudd
i got this from result debug
RTD channel number value out of range!
Actually I figured out the problem and solved it using split node But the issue is that i need to make a array so i can call it as payload1, payload2, payload3, payload4 till payload24 for gauges

You said before that "split and join not working well". @Colin asked you to show us what you did and the problem you have.
We cannot provide support unless you answer questions.
Export and post here your split and join nodes.

Yes, you need an array.
payload1, payload2, ... payload24 is not an array.
If msg.payload is an array then the elements will be msg.payload[0] to msg.payload[23].
The square brackets are important and note that the first element of an array is payload[0] not payload[1]

Is there a reason that you not do it as a sequence of separate commands rather than all in one go?

@jbudd , @Colin
I have added my JSON File
[{"id":"cfb92dc5a11cbc66","type":"tab","label":"Flow 3","disabled":false,"info":"","env":[]},{"id":"4784c5753c5a41f9","type":"function","z":"cfb92dc5a11cbc66","name":"Create command","func":"const cmds = []\nfor (let rtd = 0; rtd < 3; rtd++) {\n for (let read = 0; read < 9; read++) {\n cmds.push(rtd ${rtd} read ${read})\n }\n}\n\nmsg.payload = cmds.join(\" && \")\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":270,"y":220,"wires":[["dd62afa5cd8fecea"]]},{"id":"590d999591a443f3","type":"inject","z":"cfb92dc5a11cbc66","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":140,"wires":[["4784c5753c5a41f9"]]},{"id":"b4437d1a5f7e9518","type":"debug","z":"cfb92dc5a11cbc66","name":"Show result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":80,"wires":[]},{"id":"9bd5e2afb7838e99","type":"exec","z":"cfb92dc5a11cbc66","command":"","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":530,"y":140,"wires":[["b4437d1a5f7e9518"],["d5e5387afee0b754"],[]]},{"id":"d5e5387afee0b754","type":"debug","z":"cfb92dc5a11cbc66","name":"Show errors","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":160,"wires":[]},{"id":"dd62afa5cd8fecea","type":"split","z":"cfb92dc5a11cbc66","name":"","splt":"&&","spltType":"str","arraySplt":"1","arraySpltType":"len","stream":false,"addname":"topic","x":390,"y":160,"wires":[["9bd5e2afb7838e99"]]}]

And i have the output like this

"690.909058↵"

"690.909058↵"

"690.909058↵"

"690.909058↵"

"-1210.389648↵"

"690.909058↵"

"-1210.389648↵"

"690.909058↵"

"RTD channel number value out of range!↵"

"690.909058↵"

So Now i got this reading from the upper code which is working like this but there is still issue if i use the exec node as compare to my first code which is working well but the issue is still same where i cant convert to array and therefore i cant get the reading as expected payload1,payload2 till payload24.

This is all kind of messy isn't it.

Just run the command 24 times without concatenation.

for (let rtd = 0; rtd < 3; rtd++) {
    for (let read = 0; read < 9; read++) {
       node.send({payload:`rtd ${rtd} read ${read}`})
    }
}

connect it to an exec node.
connect a join node to the exec node, set it to 24 messages and you will get an array with 24 elements in the output.

In the gauge nodes use: {{ payload[0] }}, {{ payload[1] }} etc as value.

Here are two possible approaches. One uses your original single long command, the other uses 24 short commands. Try them and see if they give you the same result.

[{"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":[]}]

I don't have the rtd command so I had to simulate it.
I found that with the second version I needed to limit the rate of spawning OS commands to get the output order constant. You may not need this.
I also included a function to remove new lines from the response. Again, you may not need this, but I think you probably do. I'm actually surprised my first version Split still works with this function.

For @bakman2 : I think your snippet of code should be

for (let rtd = 0; rtd < 3; rtd++) {
    for (let read = 1; read < 9; read++) {
        node.send({ payload: `rtd ${rtd} read ${read}` })
    }
}

(read = 0 is invalid)

Thanks for your help as you all guide me well @Colin @jbudd @TotallyInformation @bakman2

@jbudd @bakman2 ,
After Few Days I Got this issue that this function is sending unwanted data which is not valid
image
in this image the top msg.payload array 24 is wrong because i only connected one Hat which have only 8 rtd which i have received after 13 payload msg and therefore i think it working but giving unwanted payload which does not exist