Use Variable in JSON

Hello All, New to Node Red. I have spent too much time looking for this and decided it would be best to ask here. Please point me in the right direction to learn about this topic as well if possible.

I want to have my dashboard send a float value to Node Red, then use that value in JSON, Then send it via MQTT to another device. I am sure this is very easy, I simply cannot wrap my head around it.

The Message I want to send is similar to {"Temp": 70} The part I am having difficulty with is how to change the hard coded value of 70 to variable that can come from say a dashboard.

I really appreciate your time in helping me with this. Thank you!

I think I would need a function block. Here is an example flow I am currently playing with.

[{"id":"5ab031e0.fed01","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"b90ab3e2.0eefd","type":"debug","z":"5ab031e0.fed01","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":742,"y":149,"wires":[]},{"id":"c016e447.981878","type":"inject","z":"5ab031e0.fed01","name":"","topic":"","payload":"80","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":271,"y":256,"wires":[["ddd09b49.bc1008"]]},{"id":"ddd09b49.bc1008","type":"function","z":"5ab031e0.fed01","name":"","func":"var payload=msg.payload;\nvar Temp={\"Temp\":payload};\nmsg= Temp;\nreturn msg;","outputs":1,"noerr":0,"x":555,"y":160,"wires":[["b90ab3e2.0eefd"]]}]

Hi @pascone10

that's the right idea, but can be simplified with:

msg.payload = {"Temp": msg.payload};
return msg;
2 Likes

Thank you so much @knolleary. I could not get my head there!

@knolleary Is there a way to force the output to have precision? I need msg.payload to have 1 precision. I was experimenting with .toFixed(1) but it kept returning a string.

The main issue is if I put a value in the dashboard as 0 or 1 my other device will not recognize that number as it is expecting a float.

Thank you very much in advance.

You can use parseFloat

v = msg.payload
msg.payload = {"Temp": parseFloat(Number(v).toFixed(1));};
return msg;

If you need (rounding) accuracy, there are many theories about the best solution.

2 Likes

Thank you for your time. Is it possible that .toFixed will only limit the precision and not add to it?

I am still getting values like this
msg.payload : Object

object

WrmClr: 1

Where I need values like
msg.payload : Object

object

WrmClr: 1.0

To force the precision you need to convert it to a String.

In JavaScript, there is no such thing as a number with fixed precision. It does not separate ints and floats like you do in Java - you only have the Number type. If you have the number value 1.0, JavaScript will always present that as 1, unless you convert it to a String in exactly the format you want to display it.

Hey Guys, I really appreciate your help. I have been using the S*** out of NodeRed and loving it!! Thank you @knolleary for your work on this awesome platform!

I am finally circling back to this. I have tried on my own off and on and cannot get this to work. The device that is receiving the data does not read a string so I need to convert it back to a Float.

If I return "v" I get the precision i need but the device wont read it. Once I change it to a float (return pointNum) I loose the .00 at the end.

Keep in mind I am using the Dashboard numeric node to feed the message.payload. I have a feeling that may be part of my problem as that is sending a value of "70". When I send "70.25" from the numeric node, all is well. So I believe the problem may start with the integer (i believe its a int) from the Dashboard Node.

Thank you all in advance.

i = msg.payload;
v = i.toFixed(2);
//var pointNum = parseFloat(v);
msg.payload = {"ZNTSP": v};
return msg;
1 Like

I am sorry, but I cannot quite understand what problem you are having, if you are still having a problem. You show the code for a function node, is that not working as you intend? If not then please show us what is going into the node, what is coming out, and what you want out.

Absolutely Colin. Thank you for your reply. Sorry I was not more clear. Basically I want to send Via MQTT a Json Object similar to this {"WrmClr": 72.00}

Doing my best I could only get the 72.00 from the Node Red Dashboard as a string like {"WrmClr": "72.00"}.

The issue is the device I am sending that Json Object to does not accept it as a string. So basically what I think i need is a float object in Json with a precision on it.

When using the Node Red Dashboard it works fine with .25 increments as there would be a value like {"WrmClr": 72.25}. The problem is ONLY when the Dashboard is set to a whole number like 72. There is no decimal and I'm guessing it is not a float, so the receiving controller does not accept that value.

If we can figure out how to make it {"WrmClr": 72.0} and {"WrmClr": 73.0} etc. I would be in business!!

In the attached flow I tried converting to string and converting back, to no avail. I hope there is a way to accomplish this.

[{"id":"946e02f4.047b7","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"1102ae7c.d77af2","type":"function","z":"946e02f4.047b7","name":"WrmClr","func":"v = msg.payload;\nmsg.payload = {\"WrmClr\": v};\nreturn msg;","outputs":1,"noerr":0,"x":786,"y":261,"wires":[["97b3b1e.4493d5"]]},{"id":"83840a54.b965c8","type":"ui_numeric","z":"946e02f4.047b7","name":"","label":"Warmer Cooler Setpoint","tooltip":"","group":"929435b0.ae4148","order":6,"width":4,"height":1,"wrap":false,"passthru":true,"topic":"","format":"{{value.toFixed(2)}}","min":"-2.0","max":"2.0","step":"0.25","x":570,"y":260,"wires":[["1102ae7c.d77af2"]]},{"id":"458752e.b8d84ac","type":"ui_numeric","z":"946e02f4.047b7","name":"","label":"OccHeatSP","tooltip":"","group":"929435b0.ae4148","order":7,"width":4,"height":1,"wrap":false,"passthru":true,"topic":"","format":"{{msg.payload}}","min":"60","max":"80","step":"0.25","x":530,"y":400,"wires":[["97f481d0.103fe"]]},{"id":"97b3b1e.4493d5","type":"debug","z":"946e02f4.047b7","name":"MQTT PUB","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1010,"y":280,"wires":[]},{"id":"795b98e9.7844f8","type":"inject","z":"946e02f4.047b7","name":"","topic":"","payload":"79.500","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":270,"y":320,"wires":[["97f481d0.103fe"]]},{"id":"97f481d0.103fe","type":"function","z":"946e02f4.047b7","name":"ZNTSP","func":"i = msg.payload;\nv = i.toFixed(2);\n//var pointNum = parseFloat(v);\nmsg.payload = {\"ZNTSP\": v};\nreturn msg;","outputs":1,"noerr":0,"x":780,"y":320,"wires":[["97b3b1e.4493d5"]]},{"id":"929435b0.ae4148","type":"ui_group","z":"","name":"EasyIO FS","tab":"64f79c7b.6d08a4","order":1,"disp":true,"width":8,"collapse":false},{"id":"64f79c7b.6d08a4","type":"ui_tab","z":"","name":"Brett Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

try this, change the line:
msg.payload = {"WrmClr": v};
to
msg.payload = '{"ZNTSP": ' + v + '}';
You may need to run the output thru a json node

In javascript there is only one way of holding numbers, whether whole numbers or integer. So the number 72 is exactly the same bit pattern as 72.00. Therefore there is not difference between the javascript objects {"WrmClr": 72} and {"WrmClr": 72.00}. Though that is not the same as the string value in the object {"WrmClr": "72.00"}. What exactly are you trying doing with {"WrmClr": 72} that does not work?

HI @Colin. Thank you for the explanation. I have a MQTT device that I am trying to send this value to. Thats all... I can share the specifics about the actual device but I dont think it will be of much help. It is used in the commercial Building Automation Industry. When I am debugging the controller that I am attempting to send the data to, The value is received just fine if there is any precision. I am only assuming that is the issue.

if you see the attached, the 63.75 goes through just fine. The 64 is not read by the controller on the other end. I will reach out to them for input. Ill be back!!! Thank you for your time.

image

@Colin
Here is where it gets interesting. image

The attached is showing 79.0 in the debug window. the controller I am sending to takes this just fine.. This value was passed to the function block with an inject node. so there is a difference between the dashboard and the inject. If we can figure that out I will be in business!!!

@zenofmud

I think you did it my friend. I have no clue what is going on here and would appreciate an explanation if you could help me break this out. This code is what worked for me. I was no expecting the whole object to be a string like in the attached picture but it worked!!

image

i = msg.payload; v = i. toFixed(2); msg.payload = '{"ZNTSP": ' + v + '}'; return msg;

The answer is in what toFixed does:

The toFixed() method converts a number into a string, keeping a specified number of decimals.

so in the code: msg.payload = {"WrmClr": v} v is a string so it got the double quotes included. Since you needed 72 to be sent as 72.00 you needed to build the object as a string.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.