Reset dashboard values

Hey node heads, i had a quick question. if i've got a dash readout like this:

and i wanted to (on press of a reset button on the dash) empty the value fields of all those message nodes... does anyone know of how to organise the function to do it? i tried having the reset button feed into a for loop, but i couldn't get it to work. it only ever wiped the timestamp.

i cant upload the flow as it is too big. but here is a SS of the flow:

it's not a game breaking thing, i just thought it would be neat for the user to have between tests to start from an empty dashboard

i will add. that i am able to successfully do it by linking the reset function which forces the msg.payload = "";, to the message nodes at the end. but then i end up with 21 wires which gets messy. just curious if you guys with more experience and knowledge know of a more elegant functional way

If you want a message to flow from one place to another you need wires.

But maybe you could use the existing wires by adding some code to your message parser function node. Something like this might work, depending on what your change nodes do.

if (msg.payload === "reset") {
    msg = {"payload": ""}
    return[msg, msg, msg, msg, ...]  // as many as the function has outputs
}
// normal node processing here

ps Would you end up with less wiring if your function only had one output?
Do you actually need all those change nodes?
Remember the dashboard nodes are not limited to displaying msg.payload, they can also be set to display eg msg.payload.B1

hi Jbudd, there are most certainly wires in the flow lol... but i do use out > in nodules to make the wires less messy (invisible).

the change nodes are just there to do some conversion from string to number to allow for range calculation of the value and thus changing the text colour (as in first image) the reason for the string to number conversion is because after some arbitrary point, the colour change node wasn't listening / outputting the correct response to the message node any more because it wasn't able to actually read the number in the string (it was a whole thing, but don't worry it doesn't affect the need for a function to delete all the values currently shown on dash).

as for the number of outputs, that function takes 20 readings coming in from a single serial string and parses them out into the grid / timestamp you see in dash

So you could get rid of them and use the Javascript Number() function in the message parser function. :slightly_smiling_face:

i tried that but i ran into a bugger where if any of the boards aren't connected, the message displays a string error. and then node-red throws a tizzy about not being able to conver "error" to a number. i could just do what i do in the change node where i declare the error to have a value of 1000000 and then convert that to number. then on the other side of the node i read the number 1000000 and declare it as "ERROR".

here's what those changes do to the message in order from left to right:
1)
change 1
2)

i'm aware it's a roundabout way of doing it, but it works lol (constraints upon constraints).

to avoid going off topic

is there any way to write a function in JS / node-red that effectively tells all message nodes to become a clean slate? without a simple re-declare and 21 wires anyway

what do you mean by this exactly?

I thought I answered that question, perhaps I misunderstood?

hmmm unfortunately i tried that too and all it does it deletes only the first output, none of the others. i then tried to make it output an array, but then it just replaced the timestamp with the word reset.

I was thinking if your function emits an object something like this

{
"B1":1500,
"B2":1000000,
"B3":900
}

then your ui-texts can display {{msg.payload.B1}}, {{msg.payload.B2}} or {{msg.payload.B3}} (etc)

Which implies a single output and should get rid of some of the change node processing.

However I can't immediately think of a simple way to combine this with colouring the output depending on the value, so probably not worth the effort.

Impossible to comment without seeing the function code and it's input data.

I agree with @jbudd, it would be simpler to process this in the message parser node.

Can you share just the function node and a sample of the data it receives ?

ah, no the data is coming in just as numbers:
image

so the message payload is each reading separated by a tab but only the value of the reading as i use the dashboard and csv node to format headings etc.

i assume you mean the message parser function code?:

var display = [];
var values = msg.payload.split("\t");
for(var v in values){
    display.push({payload:values[v]});
}

return display;

@smcgann99

i've taken a picture of how the message parser receives data (one msg.payload with multiple values in a single message separated by tabs)

and copied in the parser code.

i wonder if using a for statement could work in some fashion combined with the IF == reset example jbudd suggested. so:

if (msg.payload == reset){
for iterations{
msg.payload = ""}
}

or perhaps a change node that has an if statement on the input of the message parser function?

just another update, this is what i've attempted following jbudds suggestion:

var output = [];
var values = msg.payload.trim().split("\t");

if (msg.payload === "reset") {
    msg.payload = " " + "\t" + " " + "\t" + " " + "\t"

}
for(var v in values){
    output.push({payload:values[v]});
}

return output;

this is what is does to the dashboard:

even if i get rid of the tabs in the new msg.payload and just have ""+""+""+""+... etc, it does same thing... weird.

So i managed to get it to work, however the message changing nodes to allow for ERROR vs number to be properly displayed didn't like that the message wasn't a number anymore (can't convert " " to a number after all.

i think i'll have to just link a forced message change function directly to the dashboard nodes :frowning:

There are always multiple ways to achieve the same ends.
I don't think this is a better solution than yours, just that it handles a RESET injection.

Considering that your input data is an array of numbers (though you have hinted it might sometimes contain numbers as strings and perhaps "ERROR BOARD NOT FOUND"), I might approach it like this.

Use a split node to break the input into messages each with a single value.
A function to process these messages.
A switch node to route the output to the dashboard widgets based on msg.parts.index.

To achieve the reset function inject an array of 21 empty strings and topic "RESET"

The function node would be something like this


[{"id":"356c4f0ce5e69212","type":"inject","z":"845828586139eeb4","name":"Sample data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[1,\"2\",\"ERROR\"]","payloadType":"jsonata","x":110,"y":260,"wires":[["6ff80d1b39744e05"]]},{"id":"6ff80d1b39744e05","type":"split","z":"845828586139eeb4","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":370,"y":260,"wires":[["c1456f65f632c1c5"]]},{"id":"c1456f65f632c1c5","type":"function","z":"845828586139eeb4","name":"function 1","func":"if (msg.payload === \"ERROR\") {  // Handle ERROR\n    msg.payload = \"-1\"\n}\nif (msg.topic === \"RESET\") {     // Send \" \" for RESET topic\n    msg.payload = \" \"\n}\nelse {\n    msg.payload = Number(msg.payload)\n    msg.colour = \"green\"\n    if (msg.payload > 1200 || msg.payload < 10) {\n        msg.colour = \"red\"\n    }\n}\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":260,"wires":[["6dd4c24e0413fd1c"]]},{"id":"6dd4c24e0413fd1c","type":"switch","z":"845828586139eeb4","name":"","property":"parts.index","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"2","vt":"num"},{"t":"eq","v":"3","vt":"num"},{"t":"eq","v":"4","vt":"num"},{"t":"eq","v":"5","vt":"num"},{"t":"eq","v":"6","vt":"num"},{"t":"eq","v":"7","vt":"num"},{"t":"eq","v":"8","vt":"num"},{"t":"eq","v":"9","vt":"num"},{"t":"eq","v":"10","vt":"num"},{"t":"eq","v":"11","vt":"num"},{"t":"eq","v":"12","vt":"num"},{"t":"eq","v":"13","vt":"num"},{"t":"eq","v":"14","vt":"num"},{"t":"eq","v":"15","vt":"num"},{"t":"eq","v":"16","vt":"num"},{"t":"eq","v":"17","vt":"num"},{"t":"eq","v":"18","vt":"num"},{"t":"eq","v":"19","vt":"num"},{"t":"eq","v":"20","vt":"num"}],"checkall":"true","repair":false,"outputs":21,"x":630,"y":260,"wires":[["1292dfe446098937"],["4ae09484e4d3130a"],["c57cfc0b45de138d"],["fedb633e6e0d2891"],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],["0538a0270a693b3d"]]},{"id":"1292dfe446098937","type":"debug","z":"845828586139eeb4","name":"0","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":100,"wires":[]},{"id":"4ae09484e4d3130a","type":"debug","z":"845828586139eeb4","name":"1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":140,"wires":[]},{"id":"c57cfc0b45de138d","type":"debug","z":"845828586139eeb4","name":"2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":180,"wires":[]},{"id":"fedb633e6e0d2891","type":"debug","z":"845828586139eeb4","name":"3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":220,"wires":[]},{"id":"4ff544b6599472a2","type":"inject","z":"845828586139eeb4","name":"Reset - array of empty strings","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"RESET","payload":"[\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \"]","payloadType":"json","x":160,"y":300,"wires":[["6ff80d1b39744e05"]]},{"id":"0538a0270a693b3d","type":"debug","z":"845828586139eeb4","name":"etc","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":400,"wires":[]}]

I agree it's a bit of a pain to handle an input which might be a string, might be a number and might contain "ERROR".
That is why my function has if(msg.payload === "ERROR) and not if (msg.payload.includes("ERROR))

hmmmm i've copied your flow in and it looks at a glance that it should replicate what my change nodes need to do... if i get some free time today i'll have a look at integrating it. thank you for your help :slight_smile:

i have just realised about your error = -1 solution, i do want the dashboard to display error board not found, so i assume i would have to convert -1 back to error after the colour change statement in your function?

also i just tested it, doesn't allow my timestamp to output... maybe if i inject the timestamp manually past the function it might work?

There is nothing special about the "-1".

I will take a look at this later today, and see if I can come up with a neat solution for you :wink:

Can you confirm the payload to the parse function always contains 20 values in the correct order ?