What to do with the return of Modbus-Flex-Getter?

Hi there !
I'm facing a bit of an issue, I'm developing a flow witch reads data from a Modbus oxygen probe.
There are three different data to read :
Temperature : holding register ; adr.83 ; float ; 2 registers
Oxy Saturation : holding register ; adr.85 ; float ; 2 registers
Oxy Concentration : holding register ; adr.87 ; float ; 2 registers

So I use the Modbus-Flex-Getter Node with this function : (Ex. for the temperature)
msg.payload =
'fc': 3,
'unitid': 10,
'address': 83,
'quantity': 2
return msg;

The msg.payload returned from the Node is an array like : [17105,54193]

My question is : What do I do with this array ? What I want is the result in °C... I'm pretty sure the current temperature of the room is not 17105,5°C :sweat_smile:

The documentation of the probe says that the data is encoded using the IEEE-754 standard. So I've tried the toFloat node from node-red-contrib-float but whatever I do with those numbers before to pass them to this node, it always gives me a very odd result !
By the way, I've also noticed that the results are always kind off the same with all of the three data.
Ex. :
Temperature : [16761,61148]
Saturation : [17104,57272]
Concentration : [16678,55517]

If I concatenate the numbers in the arrays, pass the to toFloat and apply a Math.log() function on the results (Yes, I've tried everything :joy:) I always get a result around 50 to 60 for all of those data.

Does anyone here have a solution ? I'm kind of stuck here !

Thanks a lot !!

I forgot to mention that before to start reading I have to do a few things :

  • Ask the probe how long it takes to take the measures by reading a holding register at the address 164 (return a int in ms)
  • Ask to take the measures by writing 1 to register 1
  • Wait x ms (depends on the response of the first step)
  • Read the new data

The first step works just fine an return a value of 400ms witch is what it's supposed to be according to the documentation of the probe.

Probably would help if we knew a couple of things:

  • The make & model of the sensor
  • What temperature are you expecting to see?

The array presumably represents 2 32bit integers (42D1‬, D3B1 - the 2 registers) that somehow make up a floating point number?

Maybe something like this ?

[{"id":"6e50105d.4d6f9","type":"inject","z":"846d7832.3348c8","name":"","topic":"","payload":"[17105,54193]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":1360,"wires":[["20815420.a690ec"]]},{"id":"20815420.a690ec","type":"function","z":"846d7832.3348c8","name":"","func":"const a =  msg.payload;\nconst a1 = (a[0] >> 8) & 255;\nconst a2 = a[0] & 255;\nconst a3 = (a[1] >> 8) & 255;\nconst a4 = a[1] & 255;\nconst buf = Buffer.from([a1,a2,a3,a4]);\nmsg.payload = buf.readFloatBE(0);\nreturn msg;","outputs":1,"noerr":0,"x":290,"y":1360,"wires":[["980f57ae.2459b8"]]},{"id":"980f57ae.2459b8","type":"debug","z":"846d7832.3348c8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":490,"y":1360,"wires":[]},{"id":"97fcf467.919958","type":"inject","z":"846d7832.3348c8","name":"","topic":"","payload":"[16761,61148]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":1420,"wires":[["20815420.a690ec"]]},{"id":"358e818a.41a63e","type":"inject","z":"846d7832.3348c8","name":"","topic":"","payload":"[17105,54193]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":1460,"wires":[["20815420.a690ec"]]},{"id":"e805b265.6a30d","type":"inject","z":"846d7832.3348c8","name":"","topic":"","payload":"[16678,55517]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":1500,"wires":[["20815420.a690ec"]]}]


Anywhere close ?

1 Like

Hi TotallyInformation ! Thanks for your response !

The probe is an OPTOD from the brand Ponsel (Company is Aqualabo, they make lab probes for water quality check)
I'm expecting to see the room temperature so roughly 15 to 18°C...
For the concentration I'm expecting any number between 8 and 12 (saturation in mg/L in the air).
For the saturation, a percentage in the form of a number like 0.85 for example... (most likely around 1 since it's the oxygene saturation of the air)

The doc doesn't say anything about what the array represents. It only says :

The "floats" correspond to the ANSI / IEEE Std 754-1985 standard - simple precision (32 bits) (most significant in mind, "big-Endian")

great - that is what my function does :slight_smile:

1 Like

Yes ! It's perfectly what I need ! Thanks a lot !!
Thing is, I can't make it work on my flow ? And I don't understand it... (I like to understand what I do)

Well you said it was an array coming in - that is what I am using...
but maybe add a debug to your flow and show us exactly what you get.

I'm trying the code on the temperature. This is what i wrote :

msg.payload = [{    
    "id":"9704b942.0c2a88", #ID of the node the array is coming from ?
    "z":"846d7832.3348c8", #??
    "payload":msg.payload, #I guess ?
    "wires":[["20815420.a690ec"]] #No idea...
return msg;

If I just use the code as you gave it to me it just returns the original array.
Sorry I super new with Node Red and even more with JS.
Thanks again for your help !

OMG I'm so dense ^^
I reread the entire thing after formatting it and I get it !! What you gave me is the code of the entire flow ! No wonder why it didn't work... sorry guys, like I said I'm really new with all that.

The actual function is :

const a = msg.payload;
const a1 = (a[0] >> 8) & 255;
const a2 = a[0] & 255;
const a3 = (a[1] >> 8) & 255;
const a4 = a[1] & 255;
const buf = Buffer.from([a1,a2,a3,a4]);
msg.payload = buf.readFloatBE(0);
return msg;

And it works like a charm !!!
Problem solved ! Thanks again dceejay !

This gets asked so often that perhaps it would be worth adding to the cookbook.

1 Like