Git Product home page Git Product logo

ble-ble113a's Introduction

[UNMAINTAINED] This library does not have a maintainer. The source code and repository will be kept at this URL indefinitely. If you'd like to help maintain this codebase, create an issue on this repo explaining why you'd like to become a maintainer and tag @tessel/maintainers in the body.

#Bluetooth Low Energy Driver for the ble-ble113 Tessel Bluetooth Low Energy module. The hardware documentation for this module can be found here.

If you run into any issues you can ask for support on the ble Module Forums.

###Installation

npm install ble-ble113a

You can use module port A, B, or D. We will be implementing software UART on port C in the near future.

###Getting Started If you're interested in learning more about BLE, check out our getting started guide here!

###Examples ####Basic Example

/*********************************************
This Bluetooth Low Energy module demo scans
for nearby BLE peripherals. Much more fun if
you have some BLE peripherals around.
*********************************************/

var tessel = require('tessel');
var blelib = require('ble-ble113a');

var ble = blelib.use(tessel.port['A']);

ble.on('ready', function() {
  console.log('Scanning...');
  ble.startScanning();
});

ble.on('discover', function(peripheral) {
  console.log("Discovered peripheral!", peripheral.toString());
});

####Master - Subscribing to updates from a peripheral with known profile (example with bluetooth-enabled multimeter, mooshimeter).

var tessel = require('tessel');
var blePort = tessel.port['A'];
var bleDriver = require('ble-ble113a');

bluetooth = bleDriver.use(blePort, function(err) {
  if (err) {
    return console.log("Failed to connect", err);
  }
  else {
    // Connect to moosh
    connectToMoosh(function(moosh) {
      // Tell the meter to start reading, pass back char to read
      setMeterSettings(moosh, function(meterSample) {
        // Start reading that char
        startReadingMeter(meterSample);
      });
    });
  }
});

function startReadingMeter(meterSample) {

    meterSample.on('notification', function(value) {
      var voltage = 0;
      for (var i = 0; i < 3; i++) {
        voltage += value[3+i] << (i*8);
      }
      voltage = (0x1000000 - voltage) * (1.51292917e-04);

      console.log("Voltage", voltage);
    });

    console.log("Turning on async readings...");
    meterSample.startNotifications();
}

function setMeterSettings(mooshimeter, callback) {
  if (mooshimeter) {
    // Find the characteristic with meter settings
    console.log("Searching for characteristics...");
    mooshimeter.discoverCharacteristics(['ffa2', 'ffa6'], function(err, characteristics) {

      console.log("Characteristics Found.");
      var meterSample = characteristics[0];
      var meterSettings = characteristics[1];

      // Update meter settings struct to start reading...
      console.log("Turning on analog reads");
      meterSettings.write(new Buffer([3, 2, 0, 0, 0, 0, 0, 0, 23]), function(err, valueWritten) {
        console.log("Turned on!");
        callback && callback(meterSample);
      });
    });
  }
}

function connectToMoosh(callback) {

  bluetooth.startScanning({serviceUUIDs:['ffa0']});

  bluetooth.once('discover', function(moosh) {
    bluetooth.stopScanning(function(stopError) {
      moosh.connect(function(connectError) {
        callback && callback(moosh);
      })
    })
  });
}

####Peripheral - Updating multiple characteristics

var tessel = require('tessel');
var blePort = tessel.port['A'];
var accelPort = tessel.port['B'];
var ambientPort = tessel.port['C'];

var ble;
var accel;
var ambient;

// Connect to BLE
ble = require('ble-ble113a').use(blePort, function(err) {
  // Connect to Accel
  accel = require('accel-mma84').use(accelPort, function(err) {
    // Connect to ambient
    ambient = require('ambient-attx4').use(ambientPort, function(err) {
      // start adveristing to any listening masters
      ble.startAdvertising();
    });
  });
});

// Once a master connects
ble.on('connect', function(master) {
  // Start streaming light data
  ambient.on('light', function(lightValues) {
    // Save it to the first available characteristic
    ble.writeLocalValue(0, floatArrayToBuffer(lightValues));
  });

  // Start streaming sound data
  ambient.on('sound', function(soundValues) {
    // Save it to the next available characteristic
    ble.writeLocalValue(1, floatArrayToBuffer(soundValues));
  });

  // Start streaming accelerometer data
  accel.on('data', function(accelValues) {
    // Save it to the next available characteristic
    ble.writeLocalValue(2, floatArrayToBuffer(accelValues));
  });  
});

// Convert an array of floats to a Buffer
function floatArrayToBuffer(array){
  var buf = new Buffer(array.length*4);
  for (var i=0; i < array.length; i++){
    buf.writeFloatLE(array[i], i*4);
  }
  return buf;
}

###API ####Bluetooth (Primary Controller) #####Master Commands # bluetooth.startScanning( [options], callback(err)) Start searching for BLE peripherals (options dict is... optional ).

options =
{
  // Boolean of whether duplicate peripherals should be reported
  allowDuplicates:true/false,
  // An array of uuids that, if existing in advertising data, will cause peripheral to be reported as discovered
  serviceUUIDs:['ffa0']
}

# bluetooth.stopScanning( callback(err) ) Stop Searching for BLE peripherals.

# bluetooth.connect( peripheral, callback(err) )

# bluetooth.disconnect( peripheral, callback(err )

# bluetooth.discoverServices( peripheral, [serviceUUIDs], callback(err, services) ) Search for specific Services by passing in array of uuids. Returns array of Service objects.

# bluetooth.discoverAllServices( peripheral, callback(err, services) ) Search for all Services of a peripheral. Returns array of Service objects.

# bluetooth.discoverIncludedServices( periphreal, serviceUUID, callback(err, includedServices)) Find what services are included in this service, if any (pretty rare).

# bluetooth.discoverCharacteristics( peripheral, [characteristicsUUIDs], callback(err, characteristics) ) Search for specific Characteristics by passing in array of uuids. Returns array of Characteristic objects.

# bluetooth.discoverAllCharacteristics( peripheral, callback(err, characteristics) ) Search for all Characteristics of a peripheral. Returns array of Characteristic objects.

# bluetooth.discoverAllServicesAndCharacteristics( peripheral, callback(err, results) ) Return all services and characteristics of a peripheral.

# bluetooth.discoverCharacteristicsOfService( service, [characteristicUUIDs], callback(err, characteristics) ) Discover specific UUIDs of a service.

# bluetooth.discoverAllCharacteristicsOfService( service, callback(err, characteristics) ) Discover the characteristics of a specific service.

# bluetooth.discoverDescriptorsOfCharacteristic( characteristic, callback(err, descriptors) ) Discover the descriptors of a specific service.

# bluetooth.discoverAllAttributes( peripheral, callback(err, attributes) ) Read all the services, characteristics, and descriptors of a peripheral.

# bluetooth.read( characteristic, callback(err, value) ) Get the value of a remote characteristic.

# bluetooth.write( characteristic, value, callback(err) ) Write the value of a remote characteristic. Value should be a buffer.

# bluetooth.readDescriptor( descriptor, callback(err, value) ) Get the value of a remote descriptor.

# bluetooth.writeDescriptor( descriptor, value callback(err) ) Get the value of a remote descriptor.

# bluetooth.notify( characteristic, notify, callback(err) ) Alias for start/stopNotifications methods. notify is true/false value that indicates whether to start or stop notifications.

# bluetooth.startNotifications( characteristic, callback(err) ) Subscribe to remote characteristic updates without having to indicate it was received.

# bluetooth.stopNotifications( characteristic, callback(err) ) Stop being notified about remote characteristic updates.

# bluetooth.startIndications( characteristic, callback(err) ) Subscribe to remote characteristic updates and indicate it was received.

# bluetooth.stopIndications( characteristic, callback(err) ) Stop receiving remote characteristic updates and indicate it was received.

# bluetooth.updateRssi( peripheral, callback(err, rssi) ) Get signal strength of peripheral that we're connected to.

# bluetooth.reset( callback(err)) Reset the module (useful in case of unexpected state ).

#####Master Events # bluetooth.on( 'error', callback(err) ) Emitted on error.

# bluetooth.on( 'scanStart', callback() )

# bluetooth.on( 'scanStop', callback() )

# bluetooth.on( 'discover', callback(peripheral) )

# bluetooth.on( 'connect', callback(peripheral) )

# bluetooth.on( 'disconnect', callback(peripheral, reason) )

# bluetooth.on( 'servicesDiscover', callback(services) )

# bluetooth.on( 'characteristicsDiscover', callback(characteristics) )

# bluetooth.on( 'descriptorsDiscover', callback(descriptors) )

# bluetooth.on( 'characteristicRead', callback(characteristicRead, valueRead) )

# bluetooth.on( 'characteristicWrite', callback(characteristicWritten, valueWritten) )

# bluetooth.on( 'descriptorRead', callback(descriptorRead, valueRead) )

# bluetooth.on( 'descriptorWrite', callback(descriptorWritten, valueWritten) )

# bluetooth.on( 'notification', callback(characteristic, valueUpdated) )

# bluetooth.on( 'indication', callback(characteristic, valueUpdated) )

# bluetooth.on( 'rssiUpdate', callback(peripheral, rssi) )

#####Slave Commands # bluetooth.startAdvertising(callback(err)) Begin advertising to master devices.

# bluetooth.stopAdvertising( callback(err) ) Stop advertising.

# bluetooth.setAdvertisingData( data, callback(err) ) Set the data the master receives in advertising packet.

# bluetooth.writeLocalValue( index, data, callback(err) ) Write a local value to be read by a master.

# bluetooth.readLocalValue( index, offset, callback(err, value)) Read local values that have been written. Offset is how many bytes in to read (reads in 32 byte chunks max ).

# bluetooth.sendReadResponse( connection, errorCode, value, callback(err) ) If a master device requests to read a "user" attribute, you'll need to manually send it to them. This should be called after the "remoteReadRequest" event. If errorCode is zero, it will send the value, else it will send the error code back.

# bluetooth.maxNumValues( callback(err, maxNumValues)) Get max number of values (V1.0.1ย  is 12 ).

#####Slave Events # bluetooth.on( 'startAdvertising', callback() )

# bluetooth.on( 'stopAdvertising', callback() )

# bluetooth.on( 'connect', callback(connection) )

# bluetooth.on( 'disconnect', callback(connection, reason) )

# bluetooth.on( 'remoteWrite', callback(connection, index, valueWritten) )

# bluetooth.on( 'remoteReadRequest', callback(connection, index) )

# bluetooth.on( 'remoteNotification', callback(connection, index) )

# bluetooth.on( 'remoteIndication', callback(connection, index) )

# bluetooth.on( 'remoteUpdateStop', callback(connection, index) )

# bluetooth.on( 'indicated', callback(connection, index) )

####Hardware # bleI2C = bluetooth.I2C( address ) Make a new I2C port on the BLE hardware.

# bleI2C.transfer( txbuf, rxLen, callback(err, rxbuf) ) Transfer data over I2C.

# bleI2C.receive( len, callback(err, rxbuf) ) Receive data over I2C.

# bleI2C.send( txbuf, callback(err) ) Send data over I2C.

# var bleGPIO = bluetooth.gpio( pin) Get one of the two GPIO ports (pin must be 'p0_2' or 'p0_3' ).

# bleGPIO.direction Configured as input or output.

# bleGPIO.setInput( callback(err) ) Set as an input.

# bleGPIO.setOutput( initial, callback(err) ) Set as an output with initial value.

# bleGPIO.write( value, callback(err) ) Write a value to the GPIO port.

# bleGPIO.read( callback(err, value) ) Read a value.

# bleGPIO.watch( type, callback(err, time, type) ) Watch one of the GPIOs for an interrupt.

# bleGPIO.unwatch( [type], callback() ) Stop watching the interrupt.

# bluetooth.readADC( callback(err, value) ) Read the ADC.

####Security # bluetooth.setBondable( bondable, callback(err)) Set whether a peripheral can be bonded to (not sure if this pertains to master mode as well ).

#bluetooth.getBonds( callback(err, bonds) ) Get bonds with current devices.

# bluetooth.deleteBonds( peripheral, callback(err) ) Delete any bonds with devices.

# bluetooth.startEncryption( peripheral, callback(err) ) Start the encryption process.

# bluetooth.enterPasskey( peripheral, callback(err) ) When a remote requests a passkey, you'll need to enter it.

# bluetooth.setEncryptionKeySize( keysize, callback(err) ) Set the size of the encryption key.

# bluetooth.setOOBData( data, callback(err) ) Set the out of band data.

# bluetooth.enableMITMProtection( enable, callback(err) ) Choose whether to enable or disable MITM protection.

####System # bluetooth.getBluetoothAddress( callback(err, address) ) Get the current address of the device.

# bluetooth.getMaxConnections( callback(err, maxConnections)) Get how many connections are supported by the module (currently at 4 ).

# bluetooth.reset( callback(err) ) Reset the module.

###Object Functions ####Peripheral Properties # peripheral.rssi
# peripheral.services
# peripheral.characteristics
# peripheral.advertisingData
# peripheral.address
# peripheral.connection
# peripheral.flags

####Peripheral Commands # peripheral.connect( function(err) ) Connect to a peripheral as a master.

# peripheral.disconnect( function(err) ) Disconnected from a peripheral as a master.

# peripheral.updateRssi( function(err, rssi) ) Get the peripheral's signal strength.

# peripheral.discoverServices( uuids, function(err, services) ) Discover a subset of the peripheral's services.

# peripheral.discoverAllServices( function(services) ) Discover all the peripheral's services.

# peripheral.discoverAllServicesAndCharacteristics( uuids, function(err, results) ) Discover all the services and characteristics of a peripheral.

# peripheral.discoverCharacteristics( uuids, function(err, characteristic) ) Discover specific characteristics of a peripheral.

# peripheral.discoverAllAttributes( function(err, attributes) ) Discover all services, characteristics, and descriptors.

# peripheral.deleteBond( function(err) ) Delete bonding data from peripheral.

# peripheral.startEncryption( function(err) ) Make connection encrypted with device.

# peripheral.enterPasskey( function(err) ) Enter passkey for bonding.

# peripheral.toString() Print out the peripheral's data.

####Peripheral Events # peripheral.on( 'connect', callback() )

# peripheral.on( 'disconnect', callback(reason) )

# peripheral.on( 'servicesDiscover', callback(services) )

# peripheral.on( 'characteristicsDiscover', callback(characteristics) )

# peripheral.on( 'descriptorsDiscover', callback(descriptors) )

# peripheral.on( 'characteristicRead', callback(characteristic, value) )

# peripheral.on( 'characteristicWrite', callback(characteristic, value) )

# peripheral.on( 'descriptorRead', callback(characteristic, value) )

# peripheral.on( 'descriptorWrite', callback(characteristic, value) )

# peripheral.on( 'notification', callback(characteristic, valueUpdated) )

# peripheral.on( 'indication', callback(characteristic, valueUpdated) )

# peripheral.on( 'rssiUpdate', callback(rssi) )

####Service Properties # service.uuid
# service.handle
# service.name
# service.type
# service.characteristics
# service.includedServices

####Service Commands # service.discoverIncludedServices( callback(err, includedServices) ) Discover what other sercices are included by this one.

# service.discoverAllCharacteristics( callback(err, characteristics) ) Discover the characteristics in this service.

# service.discoverCharacteristics( [characteristicUUIDs], callback(err, characteristics) )

# service.toString() Print out the service.

####Service Events # service.on( 'discoverIncludedServices', callback(includedServices) )

# service.on( 'characteristicsDiscover', callback(characteristics) )

####Characteristic Properties # characteristic.uuid
# characteristic.handle
# characteristic.name
# characteristic.type
# characteristic.descriptors
# characteristic.value

####Characteristic Commands # characteristic.discoverAllDescriptors( callback(err, descriptors) ) Gather all descriptors for a characteristic.

# characteristic.read( callback(err, value) ) Read the value of a characteristic.

# characteristic.write( value, callback(err) ) Write the value of a characteristic.

# characteristic.notify( notify, callback(err) ) Alias for start/stopNotifications methods. notify is true/false value that indicates whether to start or stop notifications.

# characteristic.startNotifications( callback(err, value) ) Subscribe to async notifications.

# characteristic.stopNotifications( listener, callback(err) ) Unsubscribe to async notifications.

# characteristic.startIndications( callback(err)) Subscribe to indications (same as notification except you must indicate received ).

# characteristic.stopIndications( callback(err) ) Unsubscribe from indications.

# characteristic.confirmIndication( callback(err)) Tell remote you received indication (same as notification except you must indicate received ).

# characteristic.toString() Print out the characteristic.

####Characteristic Events # characteristic.on( 'characteristicRead', callback(valueRead) )

# characteristic.on( 'characteristicWrite', callback(valueWritten) )

# characteristic.on( 'discoverDescriptors', callback(descriptors) )

# characteristic.on( 'notification', callback(data) )

# characteristic.on( 'indication', callback(data) )

####Descriptor Properties # descriptor.uuid
# descriptor.handle
# descriptor.name
# descriptor.type
# descriptor.value

####Descriptor Commands # descriptor.read( callback(err, value) ) Read the value of a descriptor.

# descriptor.write( value, callback(err) ) Write the value of a descriptor.

# descriptor.toString() Print out the descriptor.

####Descriptor Events # descriptor.on( 'descriptorRead', callback(valueRead )

# descriptor.on( 'descriptorWrite', callback(valuewritten )

###Gatt Profile To access the Tessel's full GATT profile in JSON format, use the property exposed through the library or Bluetooth Controller object.

var tessel = require('tessel');
var bleLib = require('ble-ble113a');
bleLib.profile; // GATT profile object exposed through the library.

var ble = bleLib.use(tessel.port['A']);
ble.profile; // The same profile object exposed through the Bluetooth Controller

###Further Examples

  • ble Advertise. This Bluetooth Low Energy module demo turns the module on, starts it advertising as a peripheral, and writes information when connected.

  • ble Scan. This Bluetooth Low Energy module demo scans for nearby BLE peripherals.

License

MIT or Apache 2.0, at your option

ble-ble113a's People

Contributors

adkron avatar evansimpson avatar frijol avatar johnnyman727 avatar mfferreira avatar pmcote avatar rbobbins avatar tcr avatar tm-rampart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ble-ble113a's Issues

Add ability to change transmission power

The feature to change the transmission power has been requested on the forums.

To do this, a function needs to be added to messenger.js (the agent that sends and receives packages from the BLE113) to send the correct packet. To do that, call the bglib. hwSetTxPower function and pass in a value from 0 to 15 to sent the transmission power. 15 is the highest. Then, expose the function in index.js, where the BluetoothController will ask the messenger API to send the message and receive the response.

Best way to send serial (with specified baud rate) to a connected slave.

I have connected to an Arduino based BLE Slave and am listening for serial commands on it right now. Can't seem to find a good way to explicitly write out and listen to it through the Tessel BLE api.

Here is the device (LightBlue Bean)

{
    "services": {},
    "rssi": -52,
    "advertisingData": [
        {
            "typeFlag": 1,
            "type": "Flags",
            "raw": {},
            "data": [
                "LE General Discoverable Mode",
                "BR/EDR Not Supported"
            ],
            "byteOrder": "BE"
        },
        {
            "typeFlag": 6,
            "type": "Incomplete List of 128-bit Service Class UUIDs",
            "raw": {},
            "data": [
                "a495ff10c5b14b44b5121370f02d74de"
            ],
            "byteOrder": "BE"
        }
    ],
    "address": "194.45.205.114.57.208"
}

[Compat] Fails on Tessel 2

Here is the output from trying to run the example:

INFO Looking for your Tessel...
INFO Connected to doorman.
INFO Building project.
INFO Writing project to RAM on doorman (149.504 kB)...
INFO Deployed.
INFO Running ble.js...
Trace: <Buffer ef bf bd 0c 00 00 01 00 02 00 02 00 5d 00 03 00 01 06>
    at e.parseIncomingPackets (/tmp/remote-script/node_modules/ble-ble113a/lib/messenger.js:1:7049)
    at emitOne (events.js:77:13)
    at emit (events.js:169:7)
    at readableAddChunk (_stream_readable.js:146:16)
    at Readable.push (_stream_readable.js:110:10)
    at null.<anonymous> (/usr/lib/node/tessel-export.js:229:24)
    at emitNone (events.js:67:13)
    at Socket.emit (events.js:166:7)
    at emitReadable_ (_stream_readable.js:411:10)
    at emitReadable (_stream_readable.js:405:7)
[Error: No existing response creator for packet of class 0 and command id 93]
events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: Unable to connect to module.
    at Error (native)
    at e.<anonymous> (/tmp/remote-script/node_modules/ble-ble113a/lib/messenger.js:1:524)
    at processImmediate [as _immediateCallback] (timers.js:368:17)

The first byte should be an 0x80, instead there are three nonsense bytes (0xef, 0xbf, 0xed) so there may be an issue with the UART peripheral in T2 firmware.

Add ability to change advertising rate

It would be nice to be able to set the advertising rate of a BLE module acting as a beacon.

To do that, we need to add a function to messenger.js which outlines the raw packet that is being sent over UART to the module. It will use the bglib.gapSetAdvParameters function. The function expects a 16 bit number describing the min interval, a 16 bit number specifying the max interval, and a bit mask to specify which advertisement channels are used. The interval argument can be between 0x20 and 0x400. The advertisement channel should probably be 0x07 to continue using all three channels.

Then, this messenger API function should be surfaced to the BluetoothController object in index.js.

No Events for Passkey entry

Without the passkey display and passkey entry events it is impossible to connect to a passkey enabled BLE device.

Can't connect to iOS device

The connection_status event is not being fired when trying to connect to an iOS device. See more details and test code on this forum post.

Bonus points if you make example code that other people can use to integrate Tessel BLE with iOS and/or Android

startAdvertising() does not work on iphone

I tried using your example by running it directly from the example directory and my iphone does not pick up on it.

npm init
npm i tessel --save
npm i 

Then in the ble-advertise.js

var tessel = require('tessel');
var blelib = require('ble-ble113a');

var ble = blelib.use(tessel.port['A']);
// var ble = require('../').use(tessel.port['A']); // Replace '../' with 'ble-ble113a' in your own code

var interval;

then

tessel run ble-advertise.js

I get started advertising... but with nothing showing on my iphone.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.