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

Guidance on TypeError / Buffer and returning string data from a custom characteristic #86

Closed
rexstjohn opened this issue Nov 26, 2014 · 11 comments
Labels

Comments

@rexstjohn
Copy link

Hello, I am having a lot of fun with Bleno thanks for creating it. I am really excited about the possibilities with Intel Edison and have been working on a BLE service for everyone to use (https://github.com/rexstjohn/edison-ble).

I having issues with Buffers (probably due to a misunderstanding as to how to prepare data for BLE). In this case, I am trying to return a human readable hard disk storage space value from Edison. What is the proper way to return a piece of information like "220.23M?" I have tried a number of things with no success.

Example:

var EdisonStorageSpaceCharacteristic = function() {
EdisonStorageSpaceCharacteristic.super_.call(this, {
uuid: 'e602af1e-b2f2-46cb-beff-364d5d96eb76',
properties: ['read'],
descriptors: [
new Descriptor({
uuid: '2901',
value: 'Available hard disk space'
})
]
});
};

util.inherits(EdisonStorageSpaceCharacteristic, Characteristic);

EdisonStorageSpaceCharacteristic.prototype.onReadRequest = function(offset, callback) {
// Fetch free space in M, I know this to work properly but I get the buffer error
exec('df -h | grep /dev/root | awk '{ print $4; }'', function (error, stdout, stderr) {
var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data.substring(0, data.length - 3));
console.log("available storage: " + data);
callback(this.RESULT_SUCCESS, data);
});
};

And I am getting:

buffer.js:784
throw TypeError('value is out of bounds');
^
TypeError: value is out of bounds
at TypeError ()
at checkInt (buffer.js:784:11)
at Buffer.writeUInt8 (buffer.js:794:5)
at L2capBle.errorResponse (/node_app_slot/node_modules/bleno/lib/linux/l2cap-ble.js:314:7)
at null. (/node_app_slot/node_modules/bleno/lib/linux/l2cap-ble.js:716:35)
at /node_app_slot/edison-wifi-status-characteristic.js:40:7
at ChildProcess.exithandler (child_process.js:645:7)
at ChildProcess.EventEmitter.emit (events.js:98:17)
at maybeClose (child_process.js:753:16)
at Socket. (child_process.js:966:11)

@sandeepmistry
Copy link
Collaborator

@rexstjohn edison-ble looks cool!

Do you want to return a string or bytes? It looks like you are passing a string into the callback.

String:

var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data.substring(0, data.length - 3));
callback(this.RESULT_SUCCESS, new Buffer(data));

Bytes:

var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data.substring(0, data.length - 3));
var buffer = new Buffer(4); // 4 bytes - 32 bit int
buffer.writeUInt32LE(data, 0); // Little Endian - use writeUInt32BE for Big Endian
callback(this.RESULT_SUCCESS, buffer);

See node.js Buffer API docs for more info.

@rexstjohn
Copy link
Author

@sandeepmistry Thanks for your response. I'd like to return a string. I am using the LightBlue iOS app to read the characteristics. I am able to send a string as bytes and read them using the iOS app but I have to decode them myself as in this Device Manufacturer example: (https://github.com/rexstjohn/edison-ble-gatt/blob/master/edison-device-manufacturer-characteristic.js). I have tried simply returning a string and it doesn't seem to be read as I would hope.

Is it possible to send a string or do I need to first convert the string into Bytes and then decode them on whatever client app I am using?

Would be happy to contribute an example custom service like the one I am building (complete with string examples) to the examples section once I get a handle on things.

@sandeepmistry
Copy link
Collaborator

@rexstjohn a change could be made to have the API detect the callback param is a string and auto convert to a buffer. Another option is to extend the Characteristic class for specific types (StringCharacteristic, UInt16Characteristic, etc.). I did this in arduino-BLEPeripheral.

Either way, each client app, needs to decode the data. Some "smarter generic" GATT explorer apps use the Characteristic Presentation Format Descriptor (when the characteristic has one) to auto detect the data type for display purposes.

Examples would be awesome!

@rexstjohn
Copy link
Author

@sandeepmistry Thanks for clarifying that, I really appreciate your work on this!

@sandeepmistry
Copy link
Collaborator

@rexstjohn no problem.

Does it make sense to close this issue and create a new enhancement one for "typed" characteristics?

@ldmohan
Copy link

ldmohan commented Jan 24, 2015

Hello Sandep,
I need to read some values from a txt file and send to the central. I just modified battery-level-characteristic file as follows.

BatteryLevelCharacteristic.prototype.onReadRequest = function(offset, callback) {

exec('tail -1 test.txt', function (error, stdout, stderr) {

    var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data);
console.log ("last value "+data);
callback(this.RESULT_SUCCESS, new Buffer(data));
});

};
module.exports = BatteryLevelCharacteristic;

but when i try to read from central i got an error ...

on -> stateChange: poweredOn
on -> advertisingStart: success
last value 50

buffer.js:705
throw TypeError('value is out of bounds');
^
TypeError: value is out of bounds
at TypeError ()
at checkInt (buffer.js:705:11)
at Buffer.writeUInt8 (buffer.js:715:5)
at L2capBle.errorResponse (/home/pi/node_modules/bleno/lib/linux/l2cap-ble.js:314:7)
at null. (/home/pi/node_modules/bleno/lib/linux/l2cap-ble.js:716:35)
at /home/pi/node_modules/bleno/examples/battery-service/battery-level-characteristic.js:36:2
at ChildProcess.exithandler (child_process.js:646:7)
at ChildProcess.emit (events.js:98:17)
at maybeClose (child_process.js:756:16)
at Socket. (child_process.js:969:11)

Any help please

@sandeepmistry
Copy link
Collaborator

@ldmohan please see my first reply.

You are using the Buffer API incorrectly.

exec('tail -1 test.txt', function (error, stdout, stderr) {
    var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
    data = parseInt(data);
   console.log ("last value "+data);

   var buffer = new Buffer(4); // arg to Buffer is size in bytes
   buffer.writeUInt32LE(data, 0); // fill in bytes

   callback(this.RESULT_SUCCESS, buffer);
});

@ldmohan
Copy link

ldmohan commented Jan 25, 2015

Hello Sandeep, Unfortunately the same error has occurred even for the hardcode value.

BatteryLevelCharacteristic.prototype.onReadRequest = function(offset, callback) {

exec('tail -1 test.txt', function (error, stdout, stderr) {

/* var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data);
console.log ("last value "+data);
var buffer = new Buffer(4); // arg to Buffer is size in bytes
buffer.writeUInt32LE(data, 0); // fill in bytes*/

callback(this.RESULT_SUCCESS, new Buffer([98]));
});

};
module.exports = BatteryLevelCharacteristic;

throws error...........

on -> stateChange: poweredOn
on -> advertisingStart: success

buffer.js:705
throw TypeError('value is out of bounds');
^
TypeError: value is out of bounds
at TypeError ()
at checkInt (buffer.js:705:11)
at Buffer.writeUInt8 (buffer.js:715:5)
at L2capBle.errorResponse (/home/pi/node_modules/bleno/lib/linux/l2cap-ble.js:314:7)
at null. (/home/pi/node_modules/bleno/lib/linux/l2cap-ble.js:716:35)
at /home/pi/node_modules/bleno/examples/battery-service/battery-level-characteristic.js:38:4
at ChildProcess.exithandler (child_process.js:646:7)
at ChildProcess.emit (events.js:98:17)
at maybeClose (child_process.js:756:16)
at Socket. (child_process.js:969:11)

Thanks
Mohan

@ldmohan
Copy link

ldmohan commented Jan 25, 2015

Hello Sandeep, Unfortunately the same error has occurred even for the hardcode value.

BatteryLevelCharacteristic.prototype.onReadRequest = function(offset, callback) {exec('tail -1 test.txt', function (error, stdout, stderr) {
/* var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data);
console.log ("last value "+data);
var buffer = new Buffer(4); // arg to Buffer is size in bytes
buffer.writeUInt32LE(data, 0); // fill in bytes*/
callback(this.RESULT_SUCCESS, new Buffer([98]));
});};
module.exports = BatteryLevelCharacteristic;
throws error...........

on -> stateChange: poweredOn
on -> advertisingStart: successbuffer.js:705
throw TypeError('value is out of bounds');
^
TypeError: value is out of bounds
at TypeError ()
at checkInt (buffer.js:705:11)
at Buffer.writeUInt8 (buffer.js:715:5)
at L2capBle.errorResponse (/home/pi/node_modules/bleno/lib/linux/l2cap-ble.js:314:7)
at null. (/home/pi/node_modules/bleno/lib/linux/l2cap-ble.js:716:35)
at /home/pi/node_modules/bleno/examples/battery-service/battery-level-characteristic.js:38:4
at ChildProcess.exithandler (child_process.js:646:7)
at ChildProcess.emit (events.js:98:17)
at maybeClose (child_process.js:756:16)
at Socket. (child_process.js:969:11)
Actually what I want is just read a value from a file and send it to the master device. Here I use two RPi and CSR dongle for both central and peripheral devices. 
Thanks
Mohan
From: Sandeep Mistry notifications@github.com
To: sandeepmistry/bleno bleno@noreply.github.com
Cc: ldmohan ldmohan@yahoo.com
Sent: Sunday, January 25, 2015 12:02 AM
Subject: Re: [bleno] Guidance on TypeError / Buffer and returning string data from a custom characteristic (#86)

@ldmohan please see my first reply.You are using the Buffer API incorrectly.exec('tail -1 test.txt', function (error, stdout, stderr) {
var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data);
console.log ("last value "+data);

var buffer = new Buffer(4); // arg to Buffer is size in bytes
buffer.writeUInt32LE(data, 0); // fill in bytes

callback(this.RESULT_SUCCESS, buffer);
});—
Reply to this email directly or view it on GitHub.

@sandeepmistry
Copy link
Collaborator

Hmm, @ldmohan it might actually be related to the value of this, try out:

exec('tail -1 test.txt', function (error, stdout, stderr) {
    var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
    data = parseInt(data);
   console.log ("last value "+data);

   var buffer = new Buffer(4); // arg to Buffer is size in bytes
   buffer.writeUInt32LE(data, 0); // fill in bytes

   callback(this.RESULT_SUCCESS, buffer);
}.bind(this));

or

exec('tail -1 test.txt', function (error, stdout, stderr) {
    var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
    data = parseInt(data);
   console.log ("last value "+data);

   var buffer = new Buffer(4); // arg to Buffer is size in bytes
   buffer.writeUInt32LE(data, 0); // fill in bytes

   callback(Characteristic.RESULT_SUCCESS, buffer);
});

@ldmohan
Copy link

ldmohan commented Jan 26, 2015

Thanks Sandeep!"callback(Characteristic.RESULT_SUCCESS, buffer);"is working
  From: Sandeep Mistry notifications@github.com
To: sandeepmistry/bleno bleno@noreply.github.com
Cc: ldmohan ldmohan@yahoo.com
Sent: Monday, January 26, 2015 2:17 AM
Subject: Re: [bleno] Guidance on TypeError / Buffer and returning string data from a custom characteristic (#86)

Hmm, @ldmohan it might actually be related to the value of this, try out:exec('tail -1 test.txt', function (error, stdout, stderr) {
var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data);
console.log ("last value "+data);

var buffer = new Buffer(4); // arg to Buffer is size in bytes
buffer.writeUInt32LE(data, 0); // fill in bytes

callback(this.RESULT_SUCCESS, buffer);
}.bind(this));orexec('tail -1 test.txt', function (error, stdout, stderr) {
var data = stdout.toString().replace(/(\r\n|\n|\r)/gm,"");
data = parseInt(data);
console.log ("last value "+data);

var buffer = new Buffer(4); // arg to Buffer is size in bytes
buffer.writeUInt32LE(data, 0); // fill in bytes

callback(Characteristic.RESULT_SUCCESS, buffer);
});—
Reply to this email directly or view it on GitHub.

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