Convert array of UINT (16bit) numbers to array of Double (64bit) numbers

Guys, I need to join 4 positions of this array and only join 1, turning 4x16bits into 64 bits. So basically I need to merge 4 by 4 sequences into just 1 and turn that 4 16-bit data into a 64-bit one. Can you help me?

Is this still related to the question in the other thread about getting a 64-bit float from 16-bit ints? Did you try what I suggested with the TypedArrays?

https://discourse.nodered.org/t/modbus-tcp-read-32-bit-registers/1710/20?u=thatcadguy

I was able to transform it to 64 bits (with readDoubleBE), but reading one register at a time. Since I have 160 registers and 40 final information, I wanted to make a function that would gather 4 by 4 ModBus read positions and transform the value optimally by arranging it into just one vector to send to the broker. I tried to make an algorithm but it is not working. Could you help me?

Looking at your example, try doing "i += 4" instead of "i+4". Also, not sure that you need the ".value" after msg.payload.

The message that appears in debud is this:fdsfdsf
Looks like it's not incrementing the vector ...

Post some actual data (use the copy button that appears on the right of your debug message when you hover over the data) and the actual function code (not a screen shot but text) placed between two lines of ``` and I will fix it for you.

E.g.
```
var blah = "blahdiblah";
```

This has gone on too long :wink:

Never mind. I wrote it out by hand. In future, please provide sample data and something we can copy paste (screen shots are great for looking at only)

Sample data I used...

[16705,46555,13517,48779,0,0,0,0,16466,25789,26863,40598,0,0,0,0,16589,8742,32208,27469]

Function code I wrote...

var arrDBE = [];//array to store results
var buf = new Buffer(msg.payload.length*2);//create a buffer with enough space

//first loop through and populate buffer with UINT 16 values
//probably a better way but off the top of my head, this works
for(let i=0; i < msg.payload.length; i++){
    let v = msg.payload[i];
    let offset = i*2;
    buf.writeUInt16BE(v,offset);
}

//now loop the buffer and read Double values
//push them into the array
for(let i=0; i < buf.length; i+=8){
    let vBE = buf.readDoubleBE(i);
    arrDBE.push(vBE);
}

//assign the array to msg.doubleData. Doing this
//leaves the original msg.payload in tact
//(you may need it later or wish to debug both sets of data)
msg.doubleData = arrDBE;
return msg;

the flow I created for testing...

[{"id":"adffb031.38861","type":"inject","z":"86c99817.23b7c8","name":"simulate modbus data","topic":"","payload":"[16705,46555,13517,48779,0,0,0,0,16466,25789,26863,40598,0,0,0,0,16589,8742,32208,27469]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":140,"wires":[["b0b61d1c.7c502"]]},{"id":"b0b61d1c.7c502","type":"function","z":"86c99817.23b7c8","name":"writeUInt16BE, readDoubleBE","func":"var arrDBE = [];//array to store results\nvar buf = new Buffer(msg.payload.length*2);//create a buffer with enough space\n\n//first loop through and populate buffer with UINT 16 values\n//probably a better way but off the top of my head, this works\nfor(let i=0; i < msg.payload.length; i++){\n    let v = msg.payload[i];\n    let offset = i*2;\n    buf.writeUInt16BE(v,offset);\n}\n\n//now loop the buffer and read Double values\n//pusg them into the array\nfor(let i=0; i < buf.length; i+=8){\n    let vBE = buf.readDoubleBE(i);\n    arrDBE.push(vBE);\n}\n\n//assign the array to msg.doubleData. Doing this\n//leaves the original msg.payload in tact\n//(you may need it later or wish to debug both sets of data)\nmsg.doubleData = arrDBE;\nreturn msg;","outputs":1,"noerr":0,"x":290,"y":180,"wires":[["7b2f88cd.512748"]]},{"id":"7b2f88cd.512748","type":"debug","z":"86c99817.23b7c8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":450,"y":220,"wires":[]}]

Screen shot of the flow

EDIT TITLE...

I updated the title of this topic to something a bit more descriptive - for future users searching for similar answers.

2 Likes

@eduardotodero

Did this work for you?

Perhaps you could mark it as the solution to let future users searching similar requirements know it worked?

Hi guys,
By starting from this topic, i need to pick up 4 16bit registers from an instrument connected via Modbus and merge all into an UINT64 integer.
Could you please help me to fine a way?

thanks a lot.

Have a look at this excellent contrib node: https://flows.nodered.org/node/node-red-contrib-buffer-parser

Handling 64bit values with Javascript can be a bit tricky, though. I think you need to use the new BigInt type that should be available in recent NodeJS (>=10) versions. The contrib node already supports it with the biguint64(be|le) types, depending on your data.

1 Like

@ilmisu See answer I posted to a very similar question here