-
Notifications
You must be signed in to change notification settings - Fork 6
Home
cc-bnp allows you to interact with TI's CC254X BLE network processor (BNP) on node.js via TI BLE Vendor-Specific HCI Command APIs. Each Command API is in an asynchronous manner and supports both err-back callback style and promise-style.
cc-bnp let you get rid of multiple Vendor-Specific Events handling of each command. cc-bnp gathers the multiple responses up, and finally passes the result to the Command API callback. With cc-bnp, it's easy and fun in designing BLE applications on node.js.
## 2. BLE Network Processor (BNP)
The following diagram shows the scenario when CC254X operates as a BNP. In this case, the controller and host are implemented together on CC2540/41, and the application can be externally developed on an application processor (e.g., another mcu or PC). The application and profiles can communicate with BNP through TI's vendor-specific HCI commands upon an UART interface.
## 3. Installation
$ npm install cc-bnp --save
## 4. Usage
To begin with cc-bnp, you must firstly set up the serial port and initialize the BNP with a given role. To do this, simply call the .init() method:
var ccbnp = require('cc-bnp');
var cfg = {
path: '/dev/ttyUSB0'
};
ccbnp.on('ready', function () {
console.log('Initialization completes.');
});
ccbnp.init(cfg, 'central');
Here are some examples.
## 5. Basic APIs
The basic APIs are about how to initialize the BNP with a given role and how to close connection from the processor. cc-bnp also allows you to define your own characteristics with registration methods. After the BNP accomplishes its initializing procedure, a 'ready'
event will be fired by cc-bnp. When there comes a BLE indication message, cc-bnp will fire an 'ind'
event along with the message content.
Connect to CC254X SoC upon a serial port as well as initialize the BNP with a given role.
Arguments
-
config (Object): This value-object has two properties
path
andoptions
to configure the serial port.-
path
- A string that refers to the serial-port system path, e.g.,'/dev/ttyUSB0'
. -
options
- A value-object to set up the seiralport instance. Its default value is shown in the following example.
-
-
role (String): Device role. cc-bnp supports four types of single role and two types of multi-roles:
-
'broadcaster'
- Single role. An advertiser that is non-connectable. -
'observer'
- Single role. An observer that scans for advertisements. It can not initiate connections. -
'peripheral'
- Single role. An advertiser that operates as a slave in a single link layer connection. -
'central'
- Single role. A central that scans for advertisements and operates as a master in a single or multiple link layer connections. -
'central_broadcaster'
- Multi-roles. The processor plays as a central and a broadcaster. -
'peripheral_observer'
- Multi-roles. The processor plays as a peripheral and an observer.
-
-
callback(err, result)
-
'err'
(Error) - Error Message -
'result'
(Object) - Device information. It has the following properties:
-
{
devAddr: '0x78c5e59b5ef8', // Device public address
irk: <Buffer 72 74 73 20 3d 20 44 75 70 6c 65 78 3b 0a 0a 2f>, // 16 bytes IRK (Identity Resolving Key)
csrk: <Buffer 2a 3c 72 65 70 6c 61 63 65 6d 65 6e 74 3e 2a 2f> // 16 bytes CSRK (Connection Signature Resolving Key)
}
Returns
- (Promise)
Example
var ccbnp = require('cc-bnp'),
role = 'broadcaster',
cfg = {
path: '/dev/ttyUSB0',
options: {
baudRate: 115200, // default value
rtscts: true, // default value
flowControl: true // default value
}
};
// init() example: callback-style
ccbnp.init(cfg, role, function (err, result) {
if (err)
console.log(err);
else
console.log(result);
});
// init() example: promise-style
ccbnp.init(cfg, role).then(function (result) {
console.log(result);
}).fail(function (err) {
console.log(err);
}).done();
Close the opened serial port.
Arguments
- callback(err)
-
'err'
(Error) - Error Message
-
Returns
- (Promise)
Example
ccbnp.close(function (err) {
if (err)
console.log(err);
});
Register a characteristic UUID and its value format.
If a characteristic UUID is defined by GATT Specifications or BIPSO Specifications, cc-bnp will automatically parse it. If you have a private characteristic (defined by yourself, not by SIG or BIPSO), please use this method to register your characteristic to cc-bnp. This will tell cc-bnp how to parse private characteristics from the received messages.
[WARNING]: This method can overwrite a public UUID definition (GATT Specifications). It is better to choose a private UUID different from public-defined ones.
Arguments
-
regObj (Object): The object should be given with the following properties
-
uuid
(Hex string) - Characteristic UUID to register (e.g., '0xaaa0', '0xaac2'). -
params
(Array) - Field names in the characteristic value. -
types
(Array) - Data type of each parameter inparams
array.
Note: The order of entries in
types
andparams
array should be exactly matched. -
Returns
- (none)
Example
var regObj = {
uuid: '0xfff1',
params: [ 'foo', 'bar', 'certainName' ],
types: [ 'uint8', 'uint16', 'float' ]
};
ccbnp.regChar(regObj);
Register a table that maps each characteristic handle to its characteristic UUID under a connection. cc-bnp will use this table to find out the characteristic UUID when you use the characteristic handle to operate upon a characteristic.
Arguments
- connHdl (Number): Connection handle that identifies a connection.
- uuidHdlTable (Object): Characteristic handle-to-UUID mapping table (key-value pairs). Key is characteristic handle and value is characteristic UUID.
Returns
- (none)
Example
var myCharUuidHdlTable1 = {
// handle: uuid
3: '0x2a00',
5: '0x2a01',
7: '0x2a02',
9: '0x2a03',
11: '0x2a04',
14: '0x2a05'
},
myCharUuidHdlTable2 = {
4: '0x2a00',
6: '0x2a01',
8: '0x2a02',
10: '0x2a03',
12: '0x2a04',
16: '0x2a05'
};
ccbnp.regUuidHdlTable(0, myCharUuidHdlTable1); // under connection handle 0
ccbnp.regUuidHdlTable(1, myCharUuidHdlTable2); // under connection handle 1
Register the timeout configuration of HCI commands. This will tell cc-bnp of how long time it should wait for the response.
Arguments
-
connHdl (Number): Connection handle that identifies a connection
-
timeoutConfig (Object): Timeout configuration. The following table shows the details of each property
Property Type Mandatory Description Default Value level1 Number Optional Timeout of remote control commands (mSec) 3000 level2 Number Optional Timeout of remote control and operating many characteristics commands (mSec) 10000 scan Number Optional Timeout of gap.deviceDiscReq
command (mSec)15000
Returns
- (none)
Example
var timeoutConfig1 = {
level1: 2000,
level2: 5000,
scan: 3000
},
timeoutConfig2 = {
scan: 5000
};
ccbnp.regTimeoutConfig(0, timeoutConfig1); // for connection handle 0
ccbnp.regTimeoutConfig(1, timeoutConfig2); // for connection handle 1
## 6. TI's BLE Vendor-Specific HCI Command APIs
TI's BLE Vendor-Specific HCI Commands are organized in subgroups: hci, l2cap, att, gatt, gap, and util. The description of each command is documented in TI_BLE_Vendor_Specific_HCI_Guide.pdf.
Command SubGroup (CSG) | Namespace | Number of Commands |
---|---|---|
hci | ccbnp.hci | 32 |
l2cap | ccbnp.l2cap | 1 |
att | ccbnp.att | 26 |
gatt | ccbnp.gatt | 25 |
gap | ccbnp.gap | 24 |
util | ccbnp.util | 3 |
To call the Command API:
ccbnp[subGroup][cmdName](..., callback);
, where cmdName is the Command API function name which can be found from this reference table.
For example:
ccbnp.gap.deviceDiscReq(..., function (err, result) { });
Here is an example of calling deviceDiscReq() in subgroup gap:
// Please see Section 12.3 in TI BLE Vendor Specific HCI Reference Guide for API details.
// arguments: (mode, activeScan, whiteList, callback)
ccbnp.gap.deviceDiscReq(3, 1, 0, function (err, result) {
if (err)
console.log(err);
else
console.log(result);
};
Here is another example of calling writeCharValue() in subgroup gatt:
// Please see Section 18.14 in TI BLE Vendor Specific HCI Reference Guide for API details.
// arguments: (connHandle, handle, value, [uuid], callback)
var valObj = { // value object for this command
flags: 15, // bit0 = 1, bit1 = 1, bit2 = 1, bit3 = 1
sequenceNum: 1,
year: 2015,
month: 12,
day: 22,
hours: 18,
minutes: 37,
seconds: 41,
timeOffset: 0,
glucoseMol: 0.0068,
type: 1,
sampleLocation: 1,
sensorStatus: 0
};
// If _uuid_ is not given, ccbnp will automatically initiate a request to ask characteristic uuid to build value packet.
ccbnp.gatt.writeCharValue(0, 37, valObj, '0x2a18', function (err, result) {
if (err)
console.log(err);
else
console.log(result);
});
The 'uuid' of a public characteristic value can be found in GATT Specifications and Bipso characteristic value can be found in BIPSO Specifications. If you are using a private characteristic, please use .regChar() to register your uuid first.
## 7. Events
The 'ready' event is fired when the initializing procedure completes, where msg
is object of device information with the following properties
{
devAddr: '0x78c5e59b5ef8', // Device public address
irk: <Buffer 72 74 73 20 38 20 44 75 70 63 65 78 31 00 09 25>, // 16 bytes IRK
csrk: <Buffer 21 33 72 65 70 63 61 63 65 64 65 62 74 34 20 27> // 16 bytes CSRK
}
Examples:
ccbnp.on('ready', function (msg) {
console.log(msg);
});
The 'error' event is fired when when an error occurs
Examples:
ccbnp.on('error', function (err) {
console.log(err);
});
When there is an incoming BLE indication message, cc-bnp fires an 'ind'
event along with the message object. The msg
is an object with the properties given in the table:
Property | Type | Description |
---|---|---|
type | String | Indication type, can be 'linkEstablished', 'linkTerminated', 'linkParamUpdate', 'attNoti','attInd', 'authenComplete', 'passkeyNeeded' and 'bondComplete'. |
data | Object | Data along with the indication, which depends on the type of indication |
-
linkEstablished
A connection is established with another device.
-
msg.type
(String):'linkEstablished'
-
msg.data
(Object): Content of the'linkEstablished'
type event.
msg.data = { addr: '0x9059af0b8159', // Address of the connected device connHandle: 0, // Handle of the connection connInterval: 80, // Connection interval used on this connection, time = 80 * 1.25 msec connLatency: 0, // Connection latency used on this connection connTimeout: 2000, // Connection supervision timeout, time = 2000 * 10 msec clockAccuracy: 0, // The accuracy of clock }
-
-
linkTerminated
A link is terminated.
-
msg.type
(String):'linkTerminated'
-
msg.data
(Object): Content of the'linkTerminated'
type event.
msg.data = { connHandle: 0, // Connection Handle of the terminated link reason: 8, // The reason of termination }
-
-
linkParamUpdate
Connection parameter update is completed.
-
msg.type
(String):'linkParamUpdate'
-
msg.data
(Object): Content of the'linkParamUpdate'
type event.
msg.data = { connHandle: 0, connInterval: 80, connLatency: 0, connTimeout: 2000 }
-
-
attNoti
A notification of an remote attribute’s value.
-
msg.type
(String):'attNoti'
-
msg.data
(Object): Content of the'attNoti'
type event.
msg.data = { connHandle: 0, authenticated: 0, // Whether or not an authenticated link is required handle: 93, // The handle of the attribute value: <Buffer C3 01> // The value of the attribute }
-
-
attInd
An indication of an remote attribute’s value.
-
msg.type
(String):'attInd'
-
msg.data
(Object): Content of the'attInd'
type event.
msg.data = { connHandle: 0, authenticated: 0, handle: 94, value: <Buffer 08 00> }
-
-
authenComplete
The pairing process is completed (pass or fail).
-
msg.type
(String):'authenComplete'
-
msg.data
(Object): Content of the'authenComplete'
type event.
msg.data = { connHandle: 0, mitm: 1, // 0 or 1 means true or false bond: 1, // 0 or 1 means true or false ltk: <Buffer 23 84 11 48 95 39 54 36 26 54 47 64 44 63 54 73>, // 16 bytes LTK div: 0x668b, // The DIV used with this LTK. rand: <Buffer 56 68 35 55 43 46 59 99> // 8 bytes random number generated for this LTK. }
-
-
passkeyNeeded
A connection is requesting for a passkey during the pairing process .
-
msg.type
(String):'passkeyNeeded'
-
msg.data
(Object): Content of the'passkeyNeeded'
type event.
msg.data = { devAddr: '0x78c5e570796e', connHandle: 0, uiInput: 1, // Whether to ask user to input a passcode, 0 or 1 means no or yes uiOutput: 0 // Whether to display a passcode, 0 or 1 means no or yes }
-
-
bondComplete
A bond is complete and the connection is encrypted.
-
msg.type
(String):'bondComplete'
-
msg.data
(Object): Content of the'bondComplete'
type event.
msg.data = { connHandle: 0 }
-
Examples:
ccbnp.on('ind', function (msg) {
console.log(msg);
});