JS reading bytes out of a buffer

Viewed 373

I can parse the buffer with some String hacking but there must be a more direct way to go from the buffer data to the final values. I have been trying to use some buffer.readInt8, readInt16LE etc with no luck yet. The first and last values are on 2 bytes; if I understand the vocabulary involved here. The other two on one.

From the below example, I would have expected to get the temperature (228) with parseInt(buffer.readUInt16BE(6) | (buffer.readUInt16BE(7) << 8), 16). But that gives 345314198, gently showing that I am missing something.

Code

    // (example data in comments)
    
    const buffer = peripheral.advertisement.serviceData[0].data;
    // a4c1380a701400e4233c0ac5c2

    const lameParsing = {
      // Starts with the address a4:c1:38:0a:70:14, then the values
      temperatureC: parseInt(buffer.toString("hex").slice(12, 16), 16) / 10,
      // 22.8
      humidity: parseInt(buffer.toString("hex").slice(16, 18), 16),
      // 35
      battery: parseInt(buffer.toString("hex").slice(18, 20), 16),
      // 60
      batteryV: parseInt(buffer.toString("hex").slice(20, 24), 16) / 1000
      // 2.757
    };

Context

Trying to decode the bluetooth advertised data from a Xiaomi thermometer from a custom firmware described in the docs

1 Answers

This should be what you are looking for:

let Buf = Buffer.from("a4c1380a701400e4233c0ac5c2", "hex");
// Let Buf be the buffer from the Bluetooth thermometer.
// Sample data is used here, which matches in your problem.
let TemperatureC = Buf.readUInt16BE(6) / 10
let Humidity = Buf.readUIntBE(8,1)
let Battery = Buf.readUIntBE(9,1)
let BatteryV = (Buf.readUInt16BE(10)) / 1000
// Just to confirm it works...
console.log(TemperatureC,Humidity,Battery,BatteryV)
// Sample output: 22.8 35 60 2.757 (Correct)

Every byte is 1 on the offset. So, if we read 6 as 2 bytes and then 7, we are really reading the second byte from the temperature. Remember to take into account that 16 bits are 2 bytes; and NodeJS offsets by byte.

Related