noble / bleno

A Node.js module for implementing BLE (Bluetooth Low Energy) peripherals
MIT License
2.12k stars 448 forks source link

onReadRequest buffer gets corrupted #336

Closed rynop closed 7 years ago

rynop commented 7 years ago

I'm using noble to consume my bleno peripheral. The data buffer I return in my onReadRequest() callback is somehow getting corrupted when it gets to my noble Characteristic.read(). I dump the buffer right before the callback in my onReadRequest() and I dump it right away when I get it in Characteristic.read():

Consumer

...
Characteristic.read((err, data) => {
      if (err) {
        reject(err);
      } else {     
        console.log(data);
      }
    });
...

Producer

...
const bleno = require('bleno');

const flags = {
    a: 1 << 0,
    b: 1 << 1,
    c: 1 << 2
  },
  numBytesInReturnData = 18,
  supportedFlags = flags.a | flags.b | flags.c,
  accelPrecision = Math.pow(10, 5),
  bPrecision = Math.pow(10, 3);

module.exports = class DataCharacteristic extends bleno.Characteristic {
  constructor(pin) {
    super({
      uuid: '1234',
      properties: ['read'],
      descriptors: [new bleno.Descriptor({
        uuid: '2901',
        value: 'blah'
      })]
    });
    this._hardware = hardware;
    this._hasData = false;
    this._dataBuffer = new Buffer.allocUnsafe(numBytesInReturnData).fill(0);
  }

  onReadRequest(offset, callback) {
    if (!offset) {
      this._hasData = false;
      this._dataBuffer.fill(0);
      Promise.all([
          this._hardware.getA),
          this._hardware.getB(),
          this._hardware.getC(),
        ]).then((responses) => {
          this._dataBuffer.writeUInt8(supportedFlags, 0);

          this._dataBuffer.writeUInt8(responses[0], 1);
          this._dataBuffer.writeInt32LE(responses[0] * aPrecision, 2, true);
          this._dataBuffer.writeInt32LE(responses[2].x * accelPrecision, 6, true); //accel
          this._dataBuffer.writeInt32LE(responses[2].y * accelPrecision, 10, true);
          this._dataBuffer.writeInt32LE(responses[2].z * accelPrecision, 14, true);

          console.log(this._dataBuffer);

          this._hasData = true;
          callback(this.RESULT_SUCCESS, this._dataBuffer);
        })
        .catch(err => {
          console.error('Error when reading hardware data', err);
          callback(this.RESULT_UNLIKELY_ERROR);
        });
    } else if (this._hasData) { //reading a second time for rest of data
      callback(this.RESULT_SUCCESS, this._dataBuffer.slice(offset));
    } else {
      callback(this.RESULT_ATTR_NOT_LONG);
    }
  }
}

Producer outupt

<Buffer 07 00 00 00 00 00 c2 c9 ff ff e4 2c 00 00 1c 47 0f 00>

consumer outupt

<Buffer 07 00 00 00 00 00 c2 c9 ff ff 5f 34 00 00 5f 43 0f 00>

As you can see only part of the buffer gets corrupted. Why does this happen?

sandeepmistry commented 7 years ago

@rynop what operating systems are you using?

Could you provide debug logs?

rynop commented 7 years ago

Consumer was macOS, producer was Pi Zero W. I can't seem to reproduce this problem now, if I can I will provide logs.

Is there an env var that needs to be set to provide more verbose logs? Don't see anything on the README.md..

sandeepmistry commented 7 years ago

For mac: DEBUG=* node <file>.js, for Linux: sudo DEBUG=* node <file>.js.

Let's close this issue for now, and when you can reproduce please re-open with any logs you collect. Thanks.