Bridging the gap between the web and the physical world through Bluetooth.

Bluetooth devices are everywhere, and as developers, we want to write useful, fun, and powerful applications for them. Until recently, this meant writing native applications that had to be installed on user devices- a burdensome process for both users and developers. With the number of Bluetooth devices around us, a more direct and intuitive interface was long overdue.



Now, thanks to the Web Bluetooth Community Group and their work to bring us the Web Bluetooth API, we have the ability to interact directly with Bluetooth Low Energy (part of the Bluetooth 4.0 standard) devices through the browser. Connecting, reading, and writing to and from Bluetooth devices is all made possible through the Web Bluetooth API and modern web browsers like Chrome, Firefox, and Opera who are incresingly adding support for new features in the Web Bluetooth API Spec.

We at Sabertooth are excited by the potential for the Web Bluetooth API, but also recognize that developers like ourselves just want to build things, not spend time wading through documentation and hiking up the learning curve with every new technology we use. Sabertooth is an attempt to harness the power of the Web Bluetooth API and make it easily accessible to developers through a simple and intuitive library. In short, we want you to start building powerful, browser-based Bluetooth applications quickly and effortlessly, and have fun doing it.

Overview

Sabertooth is a configurable application library for integrating Bluetooth functionality with client-side Javascript.

Getting Started

Sabertooth has a few easy ways to quickly get started, each one appealing to your preferences.

Note: Sabertooth package names and file names appear as 'web-bluetooth' throughout the documentation, consistent with actual package names and file names you will encounter when searching for or working with Sabertooth.

Install with npm

You can install Sabertooth as the npm package 'web-bluetooth' here.

Or run the command-line script below in the project directory in which you would like to use Sabertooth.

$ npm install web-bluetooth

require('web-bluetooth') will load all of the files necessary to run Sabertooth.

const BluetoothDevice = require('web-bluetooth');

General Accesibility

While the Web Bluetooth API is still in development, certain features have been made available.

Note: The functionality of Sabertooth is contingent upon the permissions and availabilities of the Web Bluetooth API. The Web Bluetooth API is still in development and many features have not been implemented across browsers. For the current status of the API, please follow this link.

Feature ChromeOS Android Mobile MacOSX Device Discovery ✓ ✓ ✓ Device Connecting ✓ ✓ ✓ Device Disconnecting ✓ ✓ ✓ Device Services Read ✓ ✓

Note: To enable the browser to use the Web Bluetooth API (and Sabertooth), experimental flags must be enabled and an https server are required.

Please see Interact with BLE Devices on the Web for more information.

GATT Attributes

A basic understanding of the Generic Attribute Profile (GATT) is helpful when writing applications to interact with Bluetooth devices, but using Sabertooth requires an understanding of two main GATT attributes, GATT services and GATT characteristics.

GATT Services are collections of GATT characteristics, and GATT Characteristics are attributes that contain values.

Sabertooth abstracts over the core features of the Web-Bluetooth API, and allows for the use of virtually any GATT service or GATT characteristic, as well as non-GATT services and non-GATT characteristics.

For the complete list of normative GATT services click here. As the Web Bluetooth API continues to be developed and as this library matures, full support for more service types will be made available.

Creating a New Bluetooth Device

new BluetoothDevice(filters)

To begin interacting with a Bluetooth device, create a new instance of BluetoothDevice and save the result to a variable. BluetoothDevice is a constructor that takes in an object filters containing attributes advertised by the Bluetooth device.

Parameters

filters - an object containing at least one valid filter corresponding to attributes advertised by the bluetooth device through which Sabertooth will attempt to request and connect to the device. Below is a schema representing the optional parameters that can be passed into the BluetoothDevice constructor to create a new BluetoothDevice instance. At least one of the key-value pairs below is needed to request a device and establish an initial connection.

Note: Parameters passed into the filters object of the BluetoothDevice constructor are inclusive; a request and connection to a device can only succeed if the device satisfies all of the provided filters.

{ name: 'device_name', namePrefix: 'devicePrefix', uuid: 'uuid', services: ['service', 'service', 'service'], optional_services: ['service','service','service'] }

name

namePrefix

uuid

/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/

services

Note: Not all services present on a device are advertised. Attempting to access a device by including a filter for a service present on a device but not being advertised by the device will cause the request to the device to fail.

optional_services

Note: Any services on the device included in services will be accessible following a successful connection to the device, so a service need not be included in optional_services if the same service has already been included in services . Services can not be added to a device after the device instance has been created.

BluetoothDevice

var exampleDevice = new BluetoothDevice({ name: 'Surge' });

- the advertised the name of the device; often set by the manufacturer unless modified by the device user- an initial substring of any length that matches an advertised device name- represents a 128-bit universally unique identifier (uuid). A valid uuid is a string that matches the regexp- an array including at least one service being advertised by the device.- an array of services for which data exchange with the device will be allowed, following a successful connection to the device.A newinstance on which Sabertooth methods can be called.

In the example above, a new BluetoothDevice instance exampleDevice has been created with a valid request filter. The device name is one of the many properties advertised by Bluetooth devices and serves as a possible identifier for establishing initial connections to the device. In this example, the device name will act as the provided filter.

Below are several other examples of ways in which a new BluetoothDevice instance can be created using different filters or combinations of filters.

/* Attempts to request a device advertising a name * beginning with the substring 'Po' */ var exampleDevice = new BluetoothDevice({ namePrefix: 'Po' });

/* Attempts to request a device advertising the name * 'Polar H7 Heart Rate Sensor' and ALSO advertising the * GATT service 'heart_rate' */ var exampleDevice = new BluetoothDevice({ name: 'Polar H7 Heart Rate Sensor' service: ['heart_rate'] });

General Methods

.connect()

Method establishes a persistent connection with a Bluetooth device.

Parameters

None.

Returns

A Promise to the device GATT server for the connected device.

exampleDevice.connect();

In the example above, a connection to a previously created BluetoothDevice instance named exampleDevice will be attempted.

.disconnect()

Method removes a previous connection with a Bluetooth device.

None.

A boolean representing the success of the attempt to disconnect from the device where true represents success.

exampleDevice.disconnect();

In the example above, an attempt to disconnect from a previously created BluetoothDevice instance named exampleDevice will be attempted.

.connected()

Method returns the current connection status of the device.

None.

A boolean representing the success of the attempt to disconnect from the device where true is connected and false is disconnected.

exampleDevice.connected();

In the example above, an attempt will be made to check the connection status of a previously created BluetoothDevice instance named exampleDevice .

.getValue(characteristic)

Method attempts to read the value of provided characteristic from a connected BluetoothDevice instance.

characteristic - a GATT characteristic or 128-bit uuid string that resolves to a characteristic accessible on the device.

An object containing the ArrayBuffer value read from the connected BluetoothDevice instance, saved to the key .rawValue . For characteristics fully supported by Sabertooth, the return object will also include any parsed values for available descriptors of the requested characteristic as key-vlaue pairs with the descriptor as the key and the parsed value as the value.

exampleDevice.getValue('battery_level') .then(value => { console.log(value.battery_level); });

In the above example, the .getValue() method is called on the BluetoothDevice instance exampleDevice , which returns an object , in this example referenced as value . value contains the ArrayBuffer returned from the device stored to the property rawValue , and because 'battery_level' is a fully supported characteristic in Sabertooth, value also contains the parsed integer value for the instance's battery level, stored on the value object as the key battery_level . In this example, the parsed integer value representing the device's battery level is being logged to the console.

.writeValue(characteristic, value)

Method takes a characteristic and value and attempts to write the provided value to the provided characteristic on the device.

characteristic - a GATT characteristic or 128-bit uuid string that resolves to a characteristic accessible on the device instance.

value - an ArrayBuffer or DataView

A boolean representing the success of the attempt to write to the provided characteristic where true represents success.

exampleDevice.writeValue('gap.device_name', 'myFitbit' ) .then(writeSuccess => { console.log(writeSuccess); });

In the above example, .writeValue() changes the name of the instantiated device to myFitbit.

.startNotifications(characteristic, callback)

Method takes a characteristic name and a callback function. Provided that the characteristic has a 'notify' property, .startNotifications() will pass the event object broadcasted by the characteristic as the parameter of the callback, and run the callback each time a new event occurs.

characteristic - a GATT characteristic or 128-bit uuid string that resolves to a characteristic accessible on the device instance.

callback - a callback triggered as result of a notification from the provided characteristic advertised by the device. The parameter eventObj will automatically be passed into callback for each notification received from the device.



eventObj - an object passed as the sole parameter into the callback provided. eventObj contains the ArrayBuffer value notified from the connected BluetoothDevice instance, saved to the key .rawValue . For characteristics fully supported by Sabertooth, eventObj will also include any parsed values for available descriptors of the requested characteristic as key-vlaue pairs with the descriptor as the key and the parsed value as the value.

None.

exampleDevice.startNotifications('heart_rate_measurement', eventObj => { var newHR = eventObj.heart_rate_measurement; console.log(newHR); });

In the above example, the .startNotifications() method is called on the BluetoothDevice instance exampleDevice , which attempts to initiate a stream of notifications from the Bluetooth device, where the provided callback, in this example an anonymous function with the parameter eventObj , will be applied to the eventObj returned from each notification from the device. In this example, eventObj contains the ArrayBuffer returned from the device notification, stored to the property rawValue , and because 'heart_rate_measurement' is a fully supported characteristic in Sabertooth, eventObj also contains the parsed integer value for the device's heart rate measurement, stored on the eventObj object as the key heart_rate_measurement . In this example, the parsed integer value representing the notification's heart rate measurement is being logged to the console.

.stopNotifications(characteristic)

This method stops the notifications from the provided characteristic for the BluetoothDevice instance.

Parameters

None.

Returns

None.

exampleDevice.stopNotifications('heart_rate_measurement');

In the above example, the .stopNotifications() method is called on the BluetoothDevice instance exampleDevice , which attempts to end a stream of notifications from the Bluetooth device.

.addCharacteristic(characteristic, service, properties)

This method adds Sabertooth support for the provided characteristic to device instance on which the method was called.



Parameters:

characteristic - a GATT characteristic or 128-bit uuid string that resolves to a characteristic accessible on the device instance

service - a GATT service or 128-bit uuid string that resolves to a service accessible on the device instance

properties - an array containing at least one property existing on the characteristic to be added. Currently, Sabertooth supports the properties 'read', 'write', and 'notify'.



Returns:

A boolean representing the success of the attempt to add the characteristic to the device instance where true represents success.

Note: For characteristics added to the device instance, Sabertooth cannot parse values read from the device or prepare values to be written to the device. Returned values from device calls to the .readValue() method will return an object containing the raw data returned from the device; device calls to the .writeValue() method will attempt to write the provided value directly to the device in its provided form.

exampleDevice.addCharacteristic( '9a66fd22-0800-9191-11e4-012d1540cb8e', '9a66fd21-0800-9191-11e4-012d1540cb8e', ['read','write','notify']);

In the above example, the .addCharacteristic() method is called on the BluetoothDevice instance exampleDevice , which returns an object , in this example referenced as value , containing the parsed integer value for the instance's battery level, stored on the value object as the key battery_level .

Demos

Heart Rate Service

This demo uses the Sabertooth library to connect to a heart rate monitor broadcasting a Heart Rate Service characteristic and reads it's measurement.

Visit the GitHub page.

Battery Service

This demo uses the Sabertooth library to connect to a device broadcasting a Battery Service characteristic and reads it's level.

Visit the GitHub page.

Notes:

• Requires Android 6.0 Marshmallow, ChromeOS, or Chrome for Linux.

• Enable the 'Web Bluetooth' flag.

Authors and Contributors

Sabertooth is a team of four software developers enthusiastic to be contributing to the open source community. Visit their GitHub pages for more information.