Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with more than four characteristics #35

Closed
Wardleth opened this issue Mar 27, 2014 · 13 comments
Closed

Issue with more than four characteristics #35

Wardleth opened this issue Mar 27, 2014 · 13 comments
Labels

Comments

@Wardleth
Copy link

Hi Sandeep,

I have an issue trying to simulate a peripheral with your tool.
I coded a unique service with five characteristics with notify and write properties. From an Android app, I enable notifications for every characteristics and then I simulate modifications by sending 'write' commands and catching notifications.
The problem is that after a variable amount of commands sent, bleno does not send back the 'write response' as before (but still send the notification), so Android waits until a timeout disconnects the device. If I disable a characteristic, so I now have four of them instead of five, I get no issue and everything works fine...
Is there any limitations in the number of characterstics that a service can have ?

Wardleth

@sandeepmistry
Copy link
Collaborator

There should be no limitations on the number of characteristics. Do you have some sample code you can share?

I'll test it out with an iOS device. Also, which Android app are you using? A few people have mentioned BLE on Android is a little flaky sometimes.

@Wardleth
Copy link
Author

Yes, Android BLE stack can be a bit unstable, but here the problem seams to come from the bleno part.

Here is the piece of code I use on bleno side:
main.js :

var bleno = require('bleno');

var SensorService = require('./sensor-service');

var sensorService = new SensorService();

bleno.on('stateChange', function(state) {
  console.log('on -> stateChange: ' + state);

  if (state === 'poweredOn') {
    bleno.startAdvertising('My service', [sensorService.uuid]);
  } else {
    bleno.stopAdvertising();
  }
});

bleno.on('advertisingStart', function(error) {
  console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));

  if (!error) {
    bleno.setServices([
       sensorService
    ]);
  }
});

bleno.on('servicesSet', function() {
  console.log('on -> servicesSet');
});
bleno.on('accept', function() {
  console.log('on -> accept');
});

service.js :

var util = require('util');

var bleno = require('bleno');
var BlenoPrimaryService = bleno.PrimaryService;

var SensorACharacteristic = require('./sensor-a-characteristic');
var SensorBCharacteristic = require('./sensor-b-characteristic');
var SensorCCharacteristic = require('./sensor-c-characteristic');
var SensorDCharacteristic = require('./sensor-d-characteristic');
var SensorECharacteristic = require('./sensor-e-characteristic');

function SensorService() {
  SensorService.super_.call(this, {
    uuid: '00000000000000000000000000101010',
    characteristics: [
      new SensorACharacteristic(),
      new SensorBCharacteristic(),
      new SensorCCharacteristic(),
      new SensorDCharacteristic(),
      //new SensorECharacteristic(),
    ]
  });
}

util.inherits(SensorService, BlenoPrimaryService);

module.exports = SensorService;

sensorXCharacteristic.js :

var util = require('util');

var bleno = require('bleno');
var BlenoCharacteristic = bleno.Characteristic;
var BlenoDescriptor = bleno.Descriptor;

function SensorACharacteristic() {
  SensorACharacteristic.super_.call(this, {
    uuid: '00000000000000000000000000101011',
    properties: ['notify', 'write'],
    descriptors: [
      new BlenoDescriptor({
        uuid: '2901',
        value: 'notify sensor A state changed'
      })
    ]
  });
}

util.inherits(SensorACharacteristic, BlenoCharacteristic);

SensorACharacteristic.prototype.onWriteRequest = function(data, offset, withoutResponse, callback) {
  console.log('SensorACharacteristic onWriteRequest');
  if (offset) {
    callback(this.RESULT_ATTR_NOT_LONG);
  } else if (data.length !== 1) {
    callback(this.RESULT_INVALID_ATTRIBUTE_LENGTH);
  } else {
    if (this.updateValueCallback) {
      this.updateValueCallback(data);
    } else {
      console.log('no updateValueCallback');
    }

    callback(this.RESULT_SUCCESS);
  }
};

SensorACharacteristic.prototype.onSubscribe = function(maxValueSize, updateValueCallback) {
  console.log('SensorACharacteristic subscribe');
  this.updateValueCallback = updateValueCallback;
};

SensorACharacteristic.prototype.onUnsubscribe = function() {
  console.log('SensorACharacteristic unsubscribe');
};

SensorACharacteristic.prototype.onNotify = function() {
  console.log('SensorACharacteristic on notify');
};

module.exports = SensorACharacteristic;

On the Android side, I use an app on my own. When I connect to the device, I enable notifications for each characteristic. Their value can be 0 or 1, so I have squares 'lights' to display the value of the characteristics (green for 1 and red for 0).
I send sequences of write commands (ex: 'A B C ; D E' write 1 to characteristics A B and C, and write back 0 after 1 sec, and then write 1 to characteristics D and E, and write back 0 after 1 sec [';' is a separator]).

With 5 characteristic on bleno side, after a while the Android app does not reflect the latest write command on the 'lights' because the 'write response' packet is never send by the bleno app.

@sandeepmistry
Copy link
Collaborator

@Wardleth thanks for the sample code. I'll add it to my list of things to try out.

In the mean time, do you think you can try it out with the nRF Master Control Panel (BLE) for Android

@Wardleth
Copy link
Author

Hi Sandeep,

I have side tasks today, so I'll try the application tomorrow.
Thank you for your time.

@Wardleth
Copy link
Author

Wardleth commented Apr 1, 2014

Sandeep,
I tried the nRF Master Control Panel application. It seams to work fine with my bleno server after sending multiple write commands. But the write process is long so I cannot really reproduce the test case of my application by sending big sequence of write commands =(
I do not know what to deduce from that.

@sandeepmistry
Copy link
Collaborator

Thanks for taking the time to try this out!

Interesting, maybe it's the big write sequence causing the issues. Would you able to try and create a script that uses noble to replicate the behaviour?

@Wardleth
Copy link
Author

Wardleth commented Apr 2, 2014

I'm not very skilled in Javascript, but I'll try to reproduce the bug with noble.

@Wardleth
Copy link
Author

Wardleth commented Apr 3, 2014

Hi Sandeep,

I'm trying the develop a noble script. I tried your example to discover devices but I cannot find any devices. I run the bleno and noble scripts on the same device (internal bluetooth), so the issue might come from there ? Is it possible to use my linux as peripheral and as central with only one local device ?

@dragom
Copy link
Contributor

dragom commented Apr 3, 2014

Probably you need two. They can be on same machine. You state on which your program should run with setting environment variables.
bleno: sudo BLENO_HCI_DEVICE_ID=device_id number 0,1,... node your_file.js
noble: sudo NOBLE_HCI_DEVICE_ID=device_id number 0,1,... node your_file.js

You can state that way even debug level to see more what is going on:
sudo BLENO_HCI_DEVICE_ID=device_id number 0,1,... DEBUG=hci-ble,l2cap-ble node your_file.js

@Wardleth
Copy link
Author

Wardleth commented Apr 4, 2014

Humm ok. This is sad. I have no other local device to test bleno and noble together.

@sandeepmistry
Copy link
Collaborator

No worries, can you share what you have so far, preferably on a Github repo or Gist. An outline of the write sequence would also be useful.

@Wardleth
Copy link
Author

Wardleth commented Apr 4, 2014

The bleno code that I already posted is globally everything i've done on the peripheral side. I just have 5 SensorXCharacteristic files with X = A, B, C, D, E.
As the projet is confidential, I cannot really share more with you but I can describe you the write sequence I do on the Android side:

sequence = 'A B C ; A B C ; A B C'
array = sequence.split(';')
for s in array
    for each letter of s as X
        write 1 to SensorXCharacteristic
    wait 1 second
    for each letter of s as X
        write 0 to SensorXCharacteristic
    wait 1 second

Say this, I found an alternative to my issue by combining the 5 characteristics in only one, so there is no more issue. But there is still a problem with the first version, and it might comme from bleno, I don't know.

@sandeepmistry
Copy link
Collaborator

This should be fixed by 40497e8, there was some buffering issues with the stdin/stdout C/node.js pipe, the newline wasn't guarantee to be there after a single read call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants