noble / bleno

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

Using "Long" Write Characteristics #354

Closed vicatcu closed 6 years ago

vicatcu commented 6 years ago

I know there are two other (closed) issues related to this, but I'm new here, and I couldn't make sense of the discussions in those issues.

I'm using a Raspberry Pi 3, and trying to use BLE as a means to set / read some values on the Pi from my phone. Here's an example of such a value (spinning off the test.js in the repo).

var Password_Characteristic = function() {
  Password_Characteristic.super_.call(this, {
    uuid: 'fffffffffffffffffffffffffffffff4',
    properties: ['write', 'writeWithoutResponse']
  });
};

util.inherits(Password_Characteristic, BlenoCharacteristic);

Password_Characteristic.prototype.onWriteRequest = function(data, offset, withoutResponse, callback) {
  console.log('Password_Characteristic write request: ' + data.toString() + ' ' + offset + ' ' + withoutResponse);

  callback(this.RESULT_SUCCESS);
};

I'm using LightBlue on Android to play with this idea. The problem that I'm experiencing is that if I send a long value (> 20 bytes) the console.log on the Raspberry pi shows a truncated write. So if I send "ABCDEFGHIJKLMNOPQRSTUVWXYZ" from LightBlue, the Raspberry Pi prints out only "ABCDEFGHIJKLMNOPQRST" (i.e. the first 20 bytes of the string). Specifically the following is printed:

Password_Characteristic write request: ABCDEFGHIJKLMNOPQRST 0 true

I know if I want up to 40 characters (instead of up to 20), I can make two characteristics, one for each half. But maybe there's just something I need to do to more correctly define the write-able characteristic in Bleno? Or is this actually a deficiency in LightBlue? Hopefully someone can help steer me in the right direction.

elovin commented 6 years ago

This is also from interest to me, I will check how many characters I can write to my characteristic tomorrow and report back here.

This however does relay seem to be a limitation of Bluetooth itself, so the question is how to write larger data even though this limitation exists.

The same limitation exists for read requests.

Also see this stackoverflow question about this topic.

Did you see this issue, it mentions that this is a Bluetooth limitation. I will try to split up my data in 20 byte chunks as I need to send up to some kilobytes of data.

Okay I just tried it with the on Read request, (by the way im using typescript hand have subclassed the bleno service and characteristic class)

Edit:

I just changed the on readRequest data from the characteristic class right after receiving a readRequest, and on the client side I read the characteristic again to get the next chunk.

Now you could follow the stackoverflow example and use a view bytes to indicate which chunk of how many chunks this is and keep reading / writing them until you got your entire message.

  public onReadRequest(offset: any, callback: any): void {
    console.log("read request received");
    if (offset) {
      callback(Bleno.Characteristic.RESULT_ATTR_NOT_LONG, null)
    } else {
      let responseData: Buffer = new Buffer(this.advertisingData);
      this.advertisingData = "ASDFASDF"; // changing the data right after the last readRequest
      callback(Bleno.Characteristic.RESULT_SUCCESS, responseData);
    }
  }
vicatcu commented 6 years ago

Yea I've scoured the web and come across those links as well. I have no problem with "long reads"... but I've only managed to work around the "long writes" limitation by modeling my characteristic as two characteristics if it won't fit into 20 bytes, but will fit into 40 bytes... I just find the asymmetry strange and certainly inconvenient.

sandeepmistry commented 6 years ago

Are you sure the Android side is doing a long write?

Please provide a btmon or hcidump capture and re-open.