Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

webbluetooth

Package Overview
Dependencies
Maintainers
1
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

webbluetooth - npm Package Compare versions

Comparing version 0.0.5 to 1.0.0

docs/interfaces/bluetoothcharacteristicproperties.html

52

examples/eddystone.js

@@ -26,4 +26,3 @@ /*

var webbluetooth = require('../index');
var bluetooth = webbluetooth.bluetooth;
var webbluetooth = require('../');

@@ -62,2 +61,27 @@ var eddystoneUUID = 0xFEAA;

function handleDeviceFound(bluetoothDevice) {
var uuid = webbluetooth.getServiceUUID(eddystoneUUID);
var eddyData = bluetoothDevice.adData.serviceData.get(uuid);
if (eddyData) {
var decoded = decodeEddystone(eddyData);
if (decoded) {
switch(decoded.type) {
case frameTypes.UID:
console.log("txPower: " + decoded.txPower);
break;
case frameTypes.URL:
console.log("url: " + decoded.url);
break;
case frameTypes.TLM:
console.log("version: " + decoded.version);
break;
}
}
}
}
var bluetooth = new webbluetooth.Bluetooth({
deviceFound: handleDeviceFound
});
function decodeEddystone(view) {

@@ -109,23 +133,2 @@ var type = view.getUint8(0);

function handleDeviceFound(bluetoothDevice) {
var uuid = webbluetooth.getServiceUUID(eddystoneUUID);
var eddyData = bluetoothDevice.adData.serviceData.get(uuid);
if (eddyData) {
var decoded = decodeEddystone(eddyData);
if (decoded) {
switch(decoded.type) {
case frameTypes.UID:
console.log("txPower: " + decoded.txPower);
break;
case frameTypes.URL:
console.log("url: " + decoded.url);
break;
case frameTypes.TLM:
console.log("version: " + decoded.version);
break;
}
}
}
}
// Recursively scan

@@ -135,4 +138,3 @@ function scan() {

bluetooth.requestDevice({
filters:[{ services:[ eddystoneUUID ] }],
deviceFound: handleDeviceFound
filters:[{ services:[ eddystoneUUID ] }]
})

@@ -139,0 +141,0 @@ .then(scan)

@@ -26,10 +26,5 @@ /*

var bluetooth = require('../').bluetooth;
var Bluetooth = require('../').Bluetooth;
var bluetoothDevices = [];
function logError(error) {
console.log(error);
process.exit();
}
process.stdin.setEncoding('utf8');

@@ -49,2 +44,26 @@ process.stdin.on('readable', () => {

function handleDeviceFound(bluetoothDevice, selectFn) {
var discovered = bluetoothDevices.some(device => {
return (device.id === bluetoothDevice.id);
});
if (discovered) return;
if (bluetoothDevices.length === 0) {
process.stdin.setRawMode(true);
console.log("select a device:");
}
bluetoothDevices.push({ id: bluetoothDevice.id, select: selectFn });
console.log(bluetoothDevices.length + ": " + bluetoothDevice.name);
}
var bluetooth = new Bluetooth({
deviceFound: handleDeviceFound
});
function logError(error) {
console.log(error);
process.exit();
}
function enumerateGatt(server) {

@@ -80,17 +99,2 @@ return server.getPrimaryServices()

function handleDeviceFound(bluetoothDevice, selectFn) {
var discovered = bluetoothDevices.some(device => {
return (device.id === bluetoothDevice.id);
});
if (discovered) return;
if (bluetoothDevices.length === 0) {
process.stdin.setRawMode(true);
console.log("select a device:");
}
bluetoothDevices.push({ id: bluetoothDevice.id, select: selectFn });
console.log(bluetoothDevices.length + ": " + bluetoothDevice.name);
}
function selectDevice(index) {

@@ -104,5 +108,3 @@ var device = bluetoothDevices[index];

bluetooth.requestDevice({
deviceFound: handleDeviceFound
})
bluetooth.requestDevice()
.then(device => {

@@ -109,0 +111,0 @@ console.log("connecting...");

@@ -31,8 +31,20 @@ "use strict";

const adapter_1 = require("./adapter");
/**
* Bluetooth class
*/
class Bluetooth extends dispatcher_1.EventDispatcher {
constructor(referringDevice) {
/**
* Bluetooth constructor
* @param options Bluetooth initialisation options
*/
constructor(options) {
super();
this.referringDevice = referringDevice;
this.defaultScanTime = 10.24 * 1000;
this.deviceFound = null;
this.scanTime = 10.24 * 1000;
this.scanner = null;
options = options || {};
this.referringDevice = options.referringDevice;
this.deviceFound = options.deviceFound;
if (options.scanTime)
this.scanTime = options.scanTime * 1000;
adapter_1.adapter.on(adapter_1.NobleAdapter.EVENT_ENABLED, value => {

@@ -50,3 +62,3 @@ this.dispatchEvent(Bluetooth.EVENT_AVAILABILITY, value);

if (filter.namePrefix) {
if (filter.namePrefix.length > deviceInfo.name.length)
if (!deviceInfo.name || filter.namePrefix.length > deviceInfo.name.length)
return;

@@ -72,2 +84,6 @@ if (filter.namePrefix !== deviceInfo.name.substr(0, filter.namePrefix.length))

}
/**
* Gets the availability of a bluetooth adapter
* @returns Promise containing a flag indicating bluetooth availability
*/
getAvailability() {

@@ -80,7 +96,13 @@ return new Promise((resolve, _reject) => {

}
/**
* Scans for a device matching optional filters
* @param options The options to use when scanning
* @returns Promise containing a device which matches the options
*/
requestDevice(options) {
return new Promise((resolve, reject) => {
options = options || {};
if (this.scanner !== null)
return reject("requestDevice error: request in progress");
if (!options.acceptAllDevices && !options.deviceFound) {
if (!options.acceptAllDevices && !this.deviceFound) {
// Must have a filter

@@ -147,3 +169,3 @@ if (!options.filters || options.filters.length === 0) {

}
if (!options.deviceFound || options.deviceFound(bluetoothDevice, selectFn.bind(this)) === true) {
if (!this.deviceFound || this.deviceFound(bluetoothDevice, selectFn.bind(this)) === true) {
// If no deviceFound function, or deviceFound returns true, resolve with this device immediately

@@ -160,6 +182,9 @@ complete.call(this, bluetoothDevice);

});
}, options.scanTime || this.defaultScanTime);
}, this.scanTime);
}, error => reject(`requestDevice error: ${error}`));
});
}
/**
* Cancels the scan for devices
*/
cancelRequest() {

@@ -166,0 +191,0 @@ return new Promise((resolve, _reject) => {

@@ -31,24 +31,32 @@ "use strict";

const adapter_1 = require("./adapter");
/**
* Bluetooth Remote GATT Characteristic class
*/
class BluetoothRemoteGATTCharacteristic extends dispatcher_1.EventDispatcher {
/**
* Characteristic constructor
* @param init A partial class to initialise values
*/
constructor(init) {
super();
/**
* The service the characteristic is related to
*/
this.service = null;
/**
* The unique identifier of the characteristic
*/
this.uuid = null;
this.properties = {
broadcast: false,
read: false,
writeWithoutResponse: false,
write: false,
notify: false,
indicate: false,
authenticatedSignedWrites: false,
reliableWrite: false,
writableAuxiliaries: false
};
this._value = null;
this.handle = null;
this.descriptors = null;
Object.assign(this, init);
this.service = init.service;
this.uuid = init.uuid;
this.properties = init.properties;
this._value = init.value;
this.handle = this.uuid;
}
/**
* The value of the characteristic
*/
get value() {

@@ -66,9 +74,14 @@ return this._value;

}
getDescriptor(descriptorUUID) {
/**
* Gets a single characteristic descriptor
* @param descriptor descriptor UUID
* @returns Promise containing the descriptor
*/
getDescriptor(descriptor) {
return new Promise((resolve, reject) => {
if (!this.service.device.gatt.connected)
return reject("getDescriptor error: device not connected");
if (!descriptorUUID)
if (!descriptor)
return reject("getDescriptor error: no descriptor specified");
this.getDescriptors(descriptorUUID)
this.getDescriptors(descriptor)
.then(descriptors => {

@@ -84,3 +97,8 @@ if (descriptors.length !== 1)

}
getDescriptors(descriptorUUID) {
/**
* Gets a list of the characteristic's descriptors
* @param descriptor descriptor UUID
* @returns Promise containing an array of descriptors
*/
getDescriptors(descriptor) {
return new Promise((resolve, reject) => {

@@ -90,6 +108,6 @@ if (!this.service.device.gatt.connected)

function complete() {
if (!descriptorUUID)
if (!descriptor)
return resolve(this.descriptors);
const filtered = this.descriptors.filter(descriptor => {
return (descriptor.uuid === helpers_1.getDescriptorUUID(descriptorUUID));
const filtered = this.descriptors.filter(descriptorObject => {
return (descriptorObject.uuid === helpers_1.getDescriptorUUID(descriptor));
});

@@ -115,2 +133,6 @@ if (filtered.length !== 1)

}
/**
* Gets the value of the characteristic
* @returns Promise containing the value
*/
readValue() {

@@ -128,3 +150,7 @@ return new Promise((resolve, reject) => {

}
writeValue(bufferSource) {
/**
* Updates the value of the characteristic
* @param value The value to write
*/
writeValue(value) {
return new Promise((resolve, reject) => {

@@ -136,3 +162,3 @@ if (!this.service.device.gatt.connected)

}
const arrayBuffer = isView(bufferSource) ? bufferSource.buffer : bufferSource;
const arrayBuffer = isView(value) ? value.buffer : value;
const dataView = new DataView(arrayBuffer);

@@ -147,2 +173,6 @@ adapter_1.adapter.writeCharacteristic(this.handle, dataView, () => {

}
/**
* Start notifications of changes for the characteristic
* @returns Promise containing the characteristic
*/
startNotifications() {

@@ -161,2 +191,6 @@ return new Promise((resolve, reject) => {

}
/**
* Stop notifications of changes for the characteristic
* @returns Promise containing the characteristic
*/
stopNotifications() {

@@ -163,0 +197,0 @@ return new Promise((resolve, reject) => {

@@ -28,14 +28,36 @@ "use strict";

const adapter_1 = require("./adapter");
/**
* Bluetooth Remote GATT Descriptor class
*/
class BluetoothRemoteGATTDescriptor {
/**
* Descriptor constructor
* @param init A partial class to initialise values
*/
constructor(init) {
/**
* The characteristic the descriptor is related to
*/
this.characteristic = null;
/**
* The unique identifier of the descriptor
*/
this.uuid = null;
this._value = null;
this.handle = null;
Object.assign(this, init);
this.characteristic = init.characteristic;
this.uuid = init.uuid;
this._value = init.value;
this.handle = `${this.characteristic.uuid}-${this.uuid}`;
}
/**
* The value of the descriptor
*/
get value() {
return this._value;
}
/**
* Gets the value of the descriptor
* @returns Promise containing the value
*/
readValue() {

@@ -53,3 +75,7 @@ return new Promise((resolve, reject) => {

}
writeValue(bufferSource) {
/**
* Updates the value of the descriptor
* @param value The value to write
*/
writeValue(value) {
return new Promise((resolve, reject) => {

@@ -61,3 +87,3 @@ if (!this.characteristic.service.device.gatt.connected)

}
const arrayBuffer = isView(bufferSource) ? bufferSource.buffer : bufferSource;
const arrayBuffer = isView(value) ? value.buffer : value;
const dataView = new DataView(arrayBuffer);

@@ -64,0 +90,0 @@ adapter_1.adapter.writeDescriptor(this.handle, dataView, () => {

@@ -29,8 +29,27 @@ "use strict";

const server_1 = require("./server");
/**
* Bluetooth Device class
*/
class BluetoothDevice extends dispatcher_1.EventDispatcher {
/**
* Device constructor
* @param init A partial class to initialise values
*/
constructor(init) {
super();
this.id = "unknown";
/**
* The unique identifier of the device
*/
this.id = null;
/**
* The name of the device
*/
this.name = null;
/**
* The gatt server of the device
*/
this.gatt = null;
/**
* Whether adverts are being watched (not implemented)
*/
this.watchingAdvertisements = false;

@@ -49,5 +68,31 @@ /**

this._serviceUUIDs = [];
Object.assign(this, init);
this.gatt = new server_1.BluetoothRemoteGATTServer(this);
this.id = init.id;
this.name = init.name;
this.gatt = init.gatt;
this.watchAdvertisements = init.watchAdvertisements;
this.adData = init.adData;
this._bluetooth = init._bluetooth;
this._allowedServices = init._allowedServices;
this._serviceUUIDs = init._serviceUUIDs;
if (!this.name)
this.name = `Unknown or Unsupported Device (${this.id})`;
if (!this.gatt)
this.gatt = new server_1.BluetoothRemoteGATTServer(this);
}
/**
* Starts watching adverts from this device (not implemented)
*/
watchAdvertisements() {
return new Promise((_resolve, reject) => {
reject("watchAdvertisements error: method not implemented");
});
}
/**
* Stops watching adverts from this device (not implemented)
*/
unwatchAdvertisements() {
return new Promise((_resolve, reject) => {
reject("unwatchAdvertisements error: method not implemented");
});
}
}

@@ -59,4 +104,9 @@ /**

BluetoothDevice.EVENT_DISCONNECTED = "gattserverdisconnected";
/**
* Advertisement Received event
* @event
*/
BluetoothDevice.EVENT_ADVERT = "advertisementreceived";
exports.BluetoothDevice = BluetoothDevice;
//# sourceMappingURL=device.js.map

@@ -27,2 +27,5 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
/**
* Known services enum
*/
var bluetoothServices;

@@ -63,2 +66,5 @@ (function (bluetoothServices) {

})(bluetoothServices = exports.bluetoothServices || (exports.bluetoothServices = {}));
/**
* Known characteristics enum
*/
var bluetoothCharacteristics;

@@ -228,2 +234,5 @@ (function (bluetoothCharacteristics) {

})(bluetoothCharacteristics = exports.bluetoothCharacteristics || (exports.bluetoothCharacteristics = {}));
/**
* Known descriptors enum
*/
var bluetoothDescriptors;

@@ -247,2 +256,7 @@ (function (bluetoothDescriptors) {

})(bluetoothDescriptors = exports.bluetoothDescriptors || (exports.bluetoothDescriptors = {}));
/**
* Gets a canonical UUID from a partial UUID in string or hex format
* @param uuid The partial UUID
* @returns canonical UUID
*/
function getCanonicalUUID(uuid) {

@@ -259,18 +273,33 @@ if (typeof uuid === "number")

exports.getCanonicalUUID = getCanonicalUUID;
function getServiceUUID(uuid) {
if (bluetoothServices[uuid])
uuid = bluetoothServices[uuid];
return getCanonicalUUID(uuid);
/**
* Gets a canonical service UUID from a known service name or partial UUID in string or hex format
* @param service The known service name
* @returns canonical UUID
*/
function getServiceUUID(service) {
if (bluetoothServices[service])
service = bluetoothServices[service];
return getCanonicalUUID(service);
}
exports.getServiceUUID = getServiceUUID;
function getCharacteristicUUID(uuid) {
if (bluetoothCharacteristics[uuid])
uuid = bluetoothCharacteristics[uuid];
return getCanonicalUUID(uuid);
/**
* Gets a canonical characteristic UUID from a known characteristic name or partial UUID in string or hex format
* @param characteristic The known characteristic name
* @returns canonical UUID
*/
function getCharacteristicUUID(characteristic) {
if (bluetoothCharacteristics[characteristic])
characteristic = bluetoothCharacteristics[characteristic];
return getCanonicalUUID(characteristic);
}
exports.getCharacteristicUUID = getCharacteristicUUID;
function getDescriptorUUID(uuid) {
if (bluetoothDescriptors[uuid])
uuid = bluetoothDescriptors[uuid];
return getCanonicalUUID(uuid);
/**
* Gets a canonical descriptor UUID from a known descriptor name or partial UUID in string or hex format
* @param descriptor The known descriptor name
* @returns canonical UUID
*/
function getDescriptorUUID(descriptor) {
if (bluetoothDescriptors[descriptor])
descriptor = bluetoothDescriptors[descriptor];
return getCanonicalUUID(descriptor);
}

@@ -277,0 +306,0 @@ exports.getDescriptorUUID = getDescriptorUUID;

@@ -40,3 +40,16 @@ "use strict";

__export(require("./helpers"));
/**
* Other classes if required
*/
var device_1 = require("./device");
exports.BluetoothDevice = device_1.BluetoothDevice;
var server_1 = require("./server");
exports.BluetoothRemoteGATTServer = server_1.BluetoothRemoteGATTServer;
var service_1 = require("./service");
exports.BluetoothRemoteGATTService = service_1.BluetoothRemoteGATTService;
var characteristic_1 = require("./characteristic");
exports.BluetoothRemoteGATTCharacteristic = characteristic_1.BluetoothRemoteGATTCharacteristic;
var descriptor_1 = require("./descriptor");
exports.BluetoothRemoteGATTDescriptor = descriptor_1.BluetoothRemoteGATTDescriptor;
//# sourceMappingURL=index.js.map

@@ -31,10 +31,31 @@ "use strict";

const adapter_1 = require("./adapter");
/**
* Bluetooth Remote GATT Server class
*/
class BluetoothRemoteGATTServer {
/**
* Server constructor
* @param device Device the gatt server relates to
*/
constructor(device) {
this.device = device;
this.connected = false;
/**
* The device the gatt server is related to
*/
this.device = null;
this._connected = false;
this.handle = null;
this.services = null;
this.device = device;
this.handle = this.device.id;
}
/**
* Whether the gatt server is connected
*/
get connected() {
return this._connected;
}
/**
* Connect the gatt server
* @returns Promise containing the gatt server
*/
connect() {

@@ -45,7 +66,7 @@ return new Promise((resolve, reject) => {

adapter_1.adapter.connect(this.handle, () => {
this.connected = true;
this._connected = true;
resolve(this);
}, () => {
this.services = null;
this.connected = false;
this._connected = false;
this.device.dispatchEvent(device_1.BluetoothDevice.EVENT_DISCONNECTED);

@@ -58,13 +79,21 @@ this.device._bluetooth.dispatchEvent(device_1.BluetoothDevice.EVENT_DISCONNECTED);

}
/**
* Disconnect the gatt server
*/
disconnect() {
adapter_1.adapter.disconnect(this.handle);
this.connected = false;
this._connected = false;
}
getPrimaryService(serviceUUID) {
/**
* Gets a single primary service contained in the gatt server
* @param service service UUID
* @returns Promise containing the service
*/
getPrimaryService(service) {
return new Promise((resolve, reject) => {
if (!this.connected)
return reject("getPrimaryService error: device not connected");
if (!serviceUUID)
if (!service)
return reject("getPrimaryService error: no service specified");
this.getPrimaryServices(serviceUUID)
this.getPrimaryServices(service)
.then(services => {

@@ -80,3 +109,8 @@ if (services.length !== 1)

}
getPrimaryServices(serviceUUID) {
/**
* Gets a list of primary services contained in the gatt server
* @param service service UUID
* @returns Promise containing an array of services
*/
getPrimaryServices(service) {
return new Promise((resolve, reject) => {

@@ -86,6 +120,6 @@ if (!this.connected)

function complete() {
if (!serviceUUID)
if (!service)
return resolve(this.services);
const filtered = this.services.filter(service => {
return (service.uuid === helpers_1.getServiceUUID(serviceUUID));
const filtered = this.services.filter(serviceObject => {
return (serviceObject.uuid === helpers_1.getServiceUUID(service));
});

@@ -92,0 +126,0 @@ if (filtered.length !== 1)

@@ -31,7 +31,23 @@ "use strict";

const adapter_1 = require("./adapter");
/**
* Bluetooth Remote GATT Service class
*/
class BluetoothRemoteGATTService extends dispatcher_1.EventDispatcher {
/**
* Service constructor
* @param init A partial class to initialise values
*/
constructor(init) {
super();
/**
* The device the service is related to
*/
this.device = null;
/**
* The unique identifier of the service
*/
this.uuid = null;
/**
* Whether the service is a primary one
*/
this.isPrimary = false;

@@ -41,3 +57,5 @@ this.handle = null;

this.characteristics = null;
Object.assign(this, init);
this.device = init.device;
this.uuid = init.uuid;
this.isPrimary = init.isPrimary;
this.handle = this.uuid;

@@ -48,9 +66,14 @@ this.dispatchEvent(BluetoothRemoteGATTService.EVENT_ADDED);

}
getCharacteristic(characteristicUUID) {
/**
* Gets a single characteristic contained in the service
* @param characteristic characteristic UUID
* @returns Promise containing the characteristic
*/
getCharacteristic(characteristic) {
return new Promise((resolve, reject) => {
if (!this.device.gatt.connected)
return reject("getCharacteristic error: device not connected");
if (!characteristicUUID)
if (!characteristic)
return reject("getCharacteristic error: no characteristic specified");
this.getCharacteristics(characteristicUUID)
this.getCharacteristics(characteristic)
.then(characteristics => {

@@ -66,3 +89,8 @@ if (characteristics.length !== 1)

}
getCharacteristics(characteristicUUID) {
/**
* Gets a list of characteristics contained in the service
* @param characteristic characteristic UUID
* @returns Promise containing an array of characteristics
*/
getCharacteristics(characteristic) {
return new Promise((resolve, reject) => {

@@ -72,6 +100,6 @@ if (!this.device.gatt.connected)

function complete() {
if (!characteristicUUID)
if (!characteristic)
return resolve(this.characteristics);
const filtered = this.characteristics.filter(characteristic => {
return (characteristic.uuid === helpers_1.getCharacteristicUUID(characteristicUUID));
const filtered = this.characteristics.filter(characteristicObject => {
return (characteristicObject.uuid === helpers_1.getCharacteristicUUID(characteristic));
});

@@ -97,9 +125,14 @@ if (filtered.length !== 1)

}
getIncludedService(serviceUUID) {
/**
* Gets a single service included in the service
* @param service service UUID
* @returns Promise containing the service
*/
getIncludedService(service) {
return new Promise((resolve, reject) => {
if (!this.device.gatt.connected)
return reject("getIncludedService error: device not connected");
if (!serviceUUID)
if (!service)
return reject("getIncludedService error: no service specified");
this.getIncludedServices(serviceUUID)
this.getIncludedServices(service)
.then(services => {

@@ -115,3 +148,8 @@ if (services.length !== 1)

}
getIncludedServices(serviceUUID) {
/**
* Gets a list of services included in the service
* @param service service UUID
* @returns Promise containing an array of services
*/
getIncludedServices(service) {
return new Promise((resolve, reject) => {

@@ -121,6 +159,6 @@ if (!this.device.gatt.connected)

function complete() {
if (!serviceUUID)
if (!service)
return resolve(this.services);
const filtered = this.services.filter(service => {
return (service.uuid === helpers_1.getServiceUUID(serviceUUID));
const filtered = this.services.filter(serviceObject => {
return (serviceObject.uuid === helpers_1.getServiceUUID(service));
});

@@ -127,0 +165,0 @@ if (filtered.length !== 1)

@@ -27,10 +27,22 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const dispatcher_1 = require("./dispatcher");
const device_1 = require("./device");
const helpers_1 = require("./helpers");
const adapter_1 = require("./adapter");
class WebBluetooth {
constructor(adapter = new adapter_1.NobleAdapter()) {
this.adapter = adapter;
/**
* WebBluetooth class
*/
class WebBluetooth extends dispatcher_1.EventDispatcher {
/**
* WebBluetooth constructor
* @param referringDevice An optional referring device
*/
constructor(referringDevice) {
super();
this.referringDevice = referringDevice;
this.defaultScanTime = 10.24 * 1000;
this.scanner = null;
adapter_1.adapter.on(adapter_1.NobleAdapter.EVENT_ENABLED, value => {
this.dispatchEvent(WebBluetooth.EVENT_AVAILABILITY, value);
});
}

@@ -45,3 +57,3 @@ filterDevice(options, deviceInfo, validServices) {

if (filter.namePrefix) {
if (filter.namePrefix.length > deviceInfo.name.length)
if (!deviceInfo.name || filter.namePrefix.length > deviceInfo.name.length)
return;

@@ -55,3 +67,3 @@ if (filter.namePrefix !== deviceInfo.name.substr(0, filter.namePrefix.length))

const servicesValid = serviceUUIDs.every(serviceUUID => {
return (deviceInfo.uuids.indexOf(serviceUUID) > -1);
return (deviceInfo._serviceUUIDs.indexOf(serviceUUID) > -1);
});

@@ -68,2 +80,18 @@ if (!servicesValid)

}
/**
* Gets the availability of a bluetooth adapter
* @returns Promise containing a flag indicating bluetooth availability
*/
getAvailability() {
return new Promise((resolve, _reject) => {
adapter_1.adapter.getEnabled(enabled => {
resolve(enabled);
});
});
}
/**
* Scans for a device matching optional filters
* @param options The options to use when scanning
* @returns Promise containing a device which matches the options
*/
requestDevice(options) {

@@ -105,3 +133,3 @@ return new Promise((resolve, reject) => {

let found = false;
this.adapter.startScan(searchUUIDs, deviceInfo => {
adapter_1.adapter.startScan(searchUUIDs, deviceInfo => {
let validServices = [];

@@ -125,12 +153,16 @@ function complete(bluetoothDevice) {

// Set unique list of allowed services
deviceInfo._allowedServices = validServices.filter((item, index, array) => {
const allowedServices = validServices.filter((item, index, array) => {
return array.indexOf(item) === index;
});
Object.assign(deviceInfo, {
_bluetooth: this,
_allowedServices: allowedServices
});
const bluetoothDevice = new device_1.BluetoothDevice(deviceInfo);
function selectFn() {
complete(bluetoothDevice);
complete.call(this, bluetoothDevice);
}
if (!options.deviceFound || options.deviceFound(bluetoothDevice, selectFn)) {
if (!options.deviceFound || options.deviceFound(bluetoothDevice, selectFn.bind(this)) === true) {
// If no deviceFound function, or deviceFound returns true, resolve with this device immediately
complete(bluetoothDevice);
complete.call(this, bluetoothDevice);
}

@@ -145,6 +177,9 @@ }

});
}, options.scanTime || this.defaultScanTime);
}, options.scanTime ? options.scanTime * 1000 : this.defaultScanTime);
}, error => reject(`requestDevice error: ${error}`));
});
}
/**
* Cancels the scan for devices
*/
cancelRequest() {

@@ -155,3 +190,3 @@ return new Promise((resolve, _reject) => {

this.scanner = null;
this.adapter.stopScan();
adapter_1.adapter.stopScan();
}

@@ -162,4 +197,9 @@ resolve();

}
/**
* Bluetooth Availability Changed event
* @event
*/
WebBluetooth.EVENT_AVAILABILITY = "availabilitychanged";
exports.WebBluetooth = WebBluetooth;
//# sourceMappingURL=webbluetooth.js.map
{
"name": "webbluetooth",
"version": "0.0.5",
"version": "1.0.0",
"description": "Node.js implementation of the Web Bluetooth Specification",

@@ -5,0 +5,0 @@ "homepage": "https://github.com/thegecko/webbluetooth",

@@ -18,3 +18,3 @@ # Node Web Bluetooth

See the examples in [examples](https://github.com/thegecko/webbluetooth/tree/master/examples/) or view the API documentation at:
See the [examples](https://github.com/thegecko/webbluetooth/tree/master/examples/) or view the API documentation at:

@@ -31,3 +31,3 @@ https://thegecko.github.io/webbluetooth/

### Bluetooth
### bluetooth

@@ -37,42 +37,60 @@ - [x] referringDevice - specification unstable

- [x] requestDevice()
- [x] RequestDeviceOptions.name
- [x] RequestDeviceOptions.namePrefix
- [x] RequestDeviceOptions.services
- [x] RequestDeviceOptions.optionalServices
- [x] RequestDeviceOptions.acceptAllDevices
- [ ] RequestDeviceOptions.manufacturerData - specification unstable
- [ ] RequestDeviceOptions.serviceData - specification unstable
### Bluetooth Device
### BluetoothDevice
- [x] BluetoothDevice
- [ ] BluetoothDevice.watchAdvertisements() - specification unstable
- [ ] BluetoothDevice.unwatchAdvertisements() - specification unstable
- [x] id
- [x] name
- [x] gatt
- [ ] watchingAdvertisements - specification unstable
- [ ] watchAdvertisements() - specification unstable
- [ ] unwatchAdvertisements() - specification unstable
### Bluetooth Server
### BluetoothRemoteGATTServer
- [x] BluetoothRemoteGATTServer
- [x] BluetoothRemoteGATTServer.connect()
- [x] BluetoothRemoteGATTServer.disconnect()
- [x] BluetoothRemoteGATTServer.getPrimaryService()
- [x] BluetoothRemoteGATTServer.getPrimaryServices()
- [x] connected
- [x] device
- [x] connect()
- [x] disconnect()
- [x] getPrimaryService()
- [x] getPrimaryServices()
### Bluetooth Services
### BluetoothRemoteGATTService
- [x] BluetoothRemoteGATTService
- [x] BluetoothRemoteGATTService.getCharacteristic()
- [x] BluetoothRemoteGATTService.getCharacteristics()
- [x] BluetoothRemoteGATTService.getIncludedService()
- [x] BluetoothRemoteGATTService.getIncludedServices()
- [x] device
- [x] uuid
- [x] isPrimary
- [x] getCharacteristic()
- [x] getCharacteristics()
- [x] getIncludedService()
- [x] getIncludedServices()
### Bluetooth Characteristics
### BluetoothRemoteGATTCharacteristic
- [x] BluetoothRemoteGATTCharacteristic
- [x] BluetoothRemoteGATTCharacteristic.getDescriptor()
- [x] BluetoothRemoteGATTCharacteristic.getDescriptors()
- [x] BluetoothRemoteGATTCharacteristic.readValue()
- [x] BluetoothRemoteGATTCharacteristic.writeValue()
- [x] BluetoothRemoteGATTCharacteristic.startNotifications()
- [x] BluetoothRemoteGATTCharacteristic.stopNotifications()
- [x] service
- [x] uuid
- [x] properties
- [x] value
- [x] getDescriptor()
- [x] getDescriptors()
- [x] readValue()
- [x] writeValue()
- [x] startNotifications()
- [x] stopNotifications()
### Bluetooth Descriptors
### BluetoothRemoteGATTDescriptor
- [x] BluetoothRemoteGATTDescriptor
- [x] BluetoothRemoteGATTDescriptor.readValue()
- [x] BluetoothRemoteGATTDescriptor.writeValue()
- [x] characteristic
- [x] uuid
- [x] value
- [x] readValue()
- [x] writeValue()
### Bluetooth Events
### Events

@@ -92,2 +110,2 @@ - [x] availabilitychanged - specification unstable

- [x] Examples
- [ ] API Documentation
- [x] API Documentation

@@ -31,6 +31,41 @@ /*

/**
* Bluetooth Options interface
*/
export interface BluetoothOptions {
/**
* A `device found` callback function to allow the user to select a device
*/
deviceFound?: (device: BluetoothDevice, selectFn: () => void) => boolean;
/**
* The amount of seconds to scan for the device (default is 10)
*/
scanTime?: number;
/**
* An optional referring device
*/
referringDevice?: BluetoothDevice;
}
/**
* BluetoothLE Scan Filter Init interface
*/
export interface BluetoothLEScanFilterInit {
/**
* An array of service UUIDs to filter on
*/
services?: Array<string>;
/**
* The device name to filter on
*/
name?: string;
/**
* The device name prefix to filter on
*/
namePrefix?: string;
// Maps unsigned shorts to BluetoothDataFilters.

@@ -42,10 +77,25 @@ // object manufacturerData;

/**
* Request Device Options interface
*/
export interface RequestDeviceOptions {
/**
* An array of device filters to match
*/
filters?: Array<BluetoothLEScanFilterInit>;
/**
* An array of optional services to have access to
*/
optionalServices?: Array<string>;
/**
* Whether to accept all devices
*/
acceptAllDevices?: boolean;
deviceFound?: (device: BluetoothDevice, selectFn: any) => boolean;
filters?: Array<BluetoothLEScanFilterInit>;
optionalServices?: Array<any>;
scanTime?: any;
}
/**
* Bluetooth class
*/
export class Bluetooth extends EventDispatcher {

@@ -59,7 +109,23 @@

private defaultScanTime = 10.24 * 1000;
/**
* Referring device for the bluetooth instance
*/
public readonly referringDevice?: BluetoothDevice;
private deviceFound: (device: BluetoothDevice, selectFn: () => void) => boolean = null;
private scanTime: number = 10.24 * 1000;
private scanner = null;
constructor(public readonly referringDevice?: BluetoothDevice) {
/**
* Bluetooth constructor
* @param options Bluetooth initialisation options
*/
constructor(options?: BluetoothOptions) {
super();
options = options || {};
this.referringDevice = options.referringDevice;
this.deviceFound = options.deviceFound;
if (options.scanTime) this.scanTime = options.scanTime * 1000;
adapter.on(NobleAdapter.EVENT_ENABLED, value => {

@@ -79,3 +145,3 @@ this.dispatchEvent(Bluetooth.EVENT_AVAILABILITY, value);

if (filter.namePrefix) {
if (filter.namePrefix.length > deviceInfo.name.length) return;
if (!deviceInfo.name || filter.namePrefix.length > deviceInfo.name.length) return;
if (filter.namePrefix !== deviceInfo.name.substr(0, filter.namePrefix.length)) return;

@@ -102,2 +168,6 @@ }

/**
* Gets the availability of a bluetooth adapter
* @returns Promise containing a flag indicating bluetooth availability
*/
public getAvailability(): Promise<boolean> {

@@ -111,7 +181,14 @@ return new Promise((resolve, _reject) => {

public requestDevice(options: RequestDeviceOptions): Promise<BluetoothDevice> {
/**
* Scans for a device matching optional filters
* @param options The options to use when scanning
* @returns Promise containing a device which matches the options
*/
public requestDevice(options?: RequestDeviceOptions): Promise<BluetoothDevice> {
return new Promise((resolve, reject) => {
options = options || {};
if (this.scanner !== null) return reject("requestDevice error: request in progress");
if (!options.acceptAllDevices && !options.deviceFound) {
if (!options.acceptAllDevices && !this.deviceFound) {
// Must have a filter

@@ -191,3 +268,3 @@ if (!options.filters || options.filters.length === 0) {

if (!options.deviceFound || options.deviceFound(bluetoothDevice, selectFn.bind(this)) === true) {
if (!this.deviceFound || this.deviceFound(bluetoothDevice, selectFn.bind(this)) === true) {
// If no deviceFound function, or deviceFound returns true, resolve with this device immediately

@@ -203,3 +280,3 @@ complete.call(this, bluetoothDevice);

});
}, options.scanTime || this.defaultScanTime);
}, this.scanTime);
}, error => reject(`requestDevice error: ${error}`));

@@ -209,2 +286,5 @@ });

/**
* Cancels the scan for devices
*/
public cancelRequest(): Promise<void> {

@@ -211,0 +291,0 @@ return new Promise((resolve, _reject) => {

@@ -32,2 +32,47 @@ /*

/**
* Bluetooth Characteristic Propertiesinterface
*/
export interface BluetoothCharacteristicProperties {
/**
* Broadcast property
*/
broadcast: boolean;
/**
* Read property
*/
read: boolean;
/**
* Write without response property
*/
writeWithoutResponse: boolean;
/**
* Write property
*/
write: boolean;
/**
* Notify property
*/
notify: boolean;
/**
* Indicate property
*/
indicate: boolean;
/**
* Authenticated signed writes property
*/
authenticatedSignedWrites: boolean;
/**
* Reliable write property
*/
reliableWrite: boolean;
/**
* Writable auxiliaries property
*/
writableAuxiliaries: boolean;
}
/**
* Bluetooth Remote GATT Characteristic class
*/
export class BluetoothRemoteGATTCharacteristic extends EventDispatcher {

@@ -41,17 +86,21 @@

/**
* The service the characteristic is related to
*/
public readonly service: BluetoothRemoteGATTService = null;
/**
* The unique identifier of the characteristic
*/
public readonly uuid = null;
public readonly properties = {
broadcast: false,
read: false,
writeWithoutResponse: false,
write: false,
notify: false,
indicate: false,
authenticatedSignedWrites: false,
reliableWrite: false,
writableAuxiliaries: false
};
/**
* The properties of the characteristic
*/
public readonly properties: BluetoothCharacteristicProperties;
private _value: DataView = null;
/**
* The value of the characteristic
*/
public get value(): DataView {

@@ -64,5 +113,14 @@ return this._value;

constructor(init?: Partial<BluetoothRemoteGATTCharacteristic>) {
/**
* Characteristic constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothRemoteGATTCharacteristic>) {
super();
Object.assign(this, init);
this.service = init.service;
this.uuid = init.uuid;
this.properties = init.properties;
this._value = init.value;
this.handle = this.uuid;

@@ -81,8 +139,13 @@ }

public getDescriptor(descriptorUUID): Promise<BluetoothRemoteGATTDescriptor> {
/**
* Gets a single characteristic descriptor
* @param descriptor descriptor UUID
* @returns Promise containing the descriptor
*/
public getDescriptor(descriptor: string): Promise<BluetoothRemoteGATTDescriptor> {
return new Promise((resolve, reject) => {
if (!this.service.device.gatt.connected) return reject("getDescriptor error: device not connected");
if (!descriptorUUID) return reject("getDescriptor error: no descriptor specified");
if (!descriptor) return reject("getDescriptor error: no descriptor specified");
this.getDescriptors(descriptorUUID)
this.getDescriptors(descriptor)
.then(descriptors => {

@@ -98,3 +161,8 @@ if (descriptors.length !== 1) return reject("getDescriptor error: descriptor not found");

public getDescriptors(descriptorUUID): Promise<Array<BluetoothRemoteGATTDescriptor>> {
/**
* Gets a list of the characteristic's descriptors
* @param descriptor descriptor UUID
* @returns Promise containing an array of descriptors
*/
public getDescriptors(descriptor?: string): Promise<Array<BluetoothRemoteGATTDescriptor>> {
return new Promise((resolve, reject) => {

@@ -104,6 +172,6 @@ if (!this.service.device.gatt.connected) return reject("getDescriptors error: device not connected");

function complete() {
if (!descriptorUUID) return resolve(this.descriptors);
if (!descriptor) return resolve(this.descriptors);
const filtered = this.descriptors.filter(descriptor => {
return (descriptor.uuid === getDescriptorUUID(descriptorUUID));
const filtered = this.descriptors.filter(descriptorObject => {
return (descriptorObject.uuid === getDescriptorUUID(descriptor));
});

@@ -132,2 +200,6 @@

/**
* Gets the value of the characteristic
* @returns Promise containing the value
*/
public readValue(): Promise<DataView> {

@@ -146,3 +218,7 @@ return new Promise((resolve, reject) => {

public writeValue(bufferSource: ArrayBuffer | ArrayBufferView): Promise<void> {
/**
* Updates the value of the characteristic
* @param value The value to write
*/
public writeValue(value: ArrayBuffer | ArrayBufferView): Promise<void> {
return new Promise((resolve, reject) => {

@@ -155,3 +231,3 @@ if (!this.service.device.gatt.connected) return reject("writeValue error: device not connected");

const arrayBuffer = isView(bufferSource) ? bufferSource.buffer : bufferSource;
const arrayBuffer = isView(value) ? value.buffer : value;
const dataView = new DataView(arrayBuffer);

@@ -168,2 +244,6 @@

/**
* Start notifications of changes for the characteristic
* @returns Promise containing the characteristic
*/
public startNotifications(): Promise<BluetoothRemoteGATTCharacteristic> {

@@ -183,2 +263,6 @@ return new Promise((resolve, reject) => {

/**
* Stop notifications of changes for the characteristic
* @returns Promise containing the characteristic
*/
public stopNotifications(): Promise<BluetoothRemoteGATTCharacteristic> {

@@ -185,0 +269,0 @@ return new Promise((resolve, reject) => {

@@ -29,8 +29,21 @@ /*

/**
* Bluetooth Remote GATT Descriptor class
*/
export class BluetoothRemoteGATTDescriptor {
/**
* The characteristic the descriptor is related to
*/
public readonly characteristic: BluetoothRemoteGATTCharacteristic = null;
/**
* The unique identifier of the descriptor
*/
public readonly uuid: string = null;
private _value: DataView = null;
/**
* The value of the descriptor
*/
public get value(): DataView {

@@ -42,7 +55,18 @@ return this._value;

constructor(init?: Partial<BluetoothRemoteGATTDescriptor>) {
Object.assign(this, init);
/**
* Descriptor constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothRemoteGATTDescriptor>) {
this.characteristic = init.characteristic;
this.uuid = init.uuid;
this._value = init.value;
this.handle = `${this.characteristic.uuid}-${this.uuid}`;
}
/**
* Gets the value of the descriptor
* @returns Promise containing the value
*/
public readValue(): Promise<DataView> {

@@ -61,3 +85,7 @@ return new Promise((resolve, reject) => {

public writeValue(bufferSource: ArrayBuffer | ArrayBufferView): Promise<void> {
/**
* Updates the value of the descriptor
* @param value The value to write
*/
public writeValue(value: ArrayBuffer | ArrayBufferView): Promise<void> {
return new Promise((resolve, reject) => {

@@ -70,3 +98,3 @@ if (!this.characteristic.service.device.gatt.connected) return reject("writeValue error: device not connected");

const arrayBuffer = isView(bufferSource) ? bufferSource.buffer : bufferSource;
const arrayBuffer = isView(value) ? value.buffer : value;
const dataView = new DataView(arrayBuffer);

@@ -73,0 +101,0 @@

@@ -30,2 +30,5 @@ /*

/**
* Bluetooth Device class
*/
export class BluetoothDevice extends EventDispatcher {

@@ -39,5 +42,26 @@

public readonly id: string = "unknown";
/**
* Advertisement Received event
* @event
*/
public static EVENT_ADVERT: string = "advertisementreceived";
/**
* The unique identifier of the device
*/
public readonly id: string = null;
/**
* The name of the device
*/
public readonly name: string = null;
/**
* The gatt server of the device
*/
public readonly gatt: BluetoothRemoteGATTServer = null;
/**
* Whether adverts are being watched (not implemented)
*/
public readonly watchingAdvertisements: boolean = false;

@@ -68,16 +92,42 @@

*/
public _serviceUUIDs: Array<string> = [];
public readonly _serviceUUIDs: Array<string> = [];
constructor(init?: Partial<BluetoothDevice>) {
/**
* Device constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothDevice>) {
super();
Object.assign(this, init);
this.gatt = new BluetoothRemoteGATTServer(this);
this.id = init.id;
this.name = init.name;
this.gatt = init.gatt;
this.watchAdvertisements = init.watchAdvertisements;
this.adData = init.adData;
this._bluetooth = init._bluetooth;
this._allowedServices = init._allowedServices;
this._serviceUUIDs = init._serviceUUIDs;
if (!this.name) this.name = `Unknown or Unsupported Device (${this.id})`;
if (!this.gatt) this.gatt = new BluetoothRemoteGATTServer(this);
}
/*
/**
* Starts watching adverts from this device (not implemented)
*/
public watchAdvertisements(): Promise<void> {
return new Promise((_resolve, reject) => {
reject("watchAdvertisements error: method not implemented");
});
}
/**
* Stops watching adverts from this device (not implemented)
*/
public unwatchAdvertisements() {
return new Promise((_resolve, reject) => {
reject("unwatchAdvertisements error: method not implemented");
});
}
*/
}

@@ -14,2 +14,62 @@ # Node Web Bluetooth

## Usage
The module exports a default `navigator.bluetooth` instance, the `Bluetooth` class to allow you to instantiate your own bluetooth instances and some helper methods:
- [bluetooth](globals.html#bluetooth)
- [Bluetooth()](classes/bluetooth.html)
- [getCanonicalUUID()](globals.html#getcanonicaluuid)
- [getServiceUUID()](globals.html#getserviceuuid)
- [getCharacteristicUUID()](globals.html#getcharacteristicuuid)
- [getDescriptorUUID()](globals.html#getdescriptoruuid)
### Using the default bluetooth instance
To use existing Web Bluetooth scripts, you can simply use the default `bluetooth` instance in place of the `navigator.bluetooth` object:
```JavaScript
var bluetooth = require("webbluetooth").bluetooth;
bluetooth.requestDevice({
filters:[{ services:[ "heart_rate" ] }]
})
.then(device => {
return device.gatt.connect();
})
.then(server => {
...
})
```
The first device matching the filters will be returned.
### Creating your own bluetooth instances
You may want to create your own instance of the `Bluetooth` class. For example, to inject a device chooser function or control the referring device:
```JavaScript
var Bluetooth = require("webbluetooth").Bluetooth;
function handleDeviceFound(device, selectFn) {
// If device can be automatically selected, do so by returning true
if (device.name === "myName") return true;
// Otherwise store the selectFn somewhere and execute it later to select this device
}
var bluetooth = new Bluetooth({
deviceFound: handleDeviceFound
});
bluetooth.requestDevice({
filters:[{ services:[ "heart_rate" ] }]
})
.then(device => {
return device.gatt.connect();
})
.then(server => {
...
})
```
## Specification

@@ -16,0 +76,0 @@

@@ -26,2 +26,5 @@ /*

/**
* Known services enum
*/
export enum bluetoothServices {

@@ -62,2 +65,5 @@ "alert_notification" = 0x1811,

/**
* Known characteristics enum
*/
export enum bluetoothCharacteristics {

@@ -227,2 +233,5 @@ "aerobic_heart_rate_lower_limit" = 0x2A7E,

/**
* Known descriptors enum
*/
export enum bluetoothDescriptors {

@@ -246,2 +255,7 @@ "gatt.characteristic_extended_properties" = 0x2900,

/**
* Gets a canonical UUID from a partial UUID in string or hex format
* @param uuid The partial UUID
* @returns canonical UUID
*/
export function getCanonicalUUID(uuid: string | number): string {

@@ -255,15 +269,30 @@ if (typeof uuid === "number") uuid = uuid.toString(16);

export function getServiceUUID(uuid: string | number): string {
if (bluetoothServices[uuid]) uuid = bluetoothServices[uuid];
return getCanonicalUUID(uuid);
/**
* Gets a canonical service UUID from a known service name or partial UUID in string or hex format
* @param service The known service name
* @returns canonical UUID
*/
export function getServiceUUID(service: string | number): string {
if (bluetoothServices[service]) service = bluetoothServices[service];
return getCanonicalUUID(service);
}
export function getCharacteristicUUID(uuid: string | number): string {
if (bluetoothCharacteristics[uuid]) uuid = bluetoothCharacteristics[uuid];
return getCanonicalUUID(uuid);
/**
* Gets a canonical characteristic UUID from a known characteristic name or partial UUID in string or hex format
* @param characteristic The known characteristic name
* @returns canonical UUID
*/
export function getCharacteristicUUID(characteristic: string | number): string {
if (bluetoothCharacteristics[characteristic]) characteristic = bluetoothCharacteristics[characteristic];
return getCanonicalUUID(characteristic);
}
export function getDescriptorUUID(uuid: string | number): string {
if (bluetoothDescriptors[uuid]) uuid = bluetoothDescriptors[uuid];
return getCanonicalUUID(uuid);
/**
* Gets a canonical descriptor UUID from a known descriptor name or partial UUID in string or hex format
* @param descriptor The known descriptor name
* @returns canonical UUID
*/
export function getDescriptorUUID(descriptor: string | number): string {
if (bluetoothDescriptors[descriptor]) descriptor = bluetoothDescriptors[descriptor];
return getCanonicalUUID(descriptor);
}

@@ -34,2 +34,7 @@ /*

/**
* Helper methods and enums
*/
export * from "./helpers";
/**
* Bluetooth class for creating new instances

@@ -40,4 +45,8 @@ */

/**
* Helper methods and enums
* Other classes if required
*/
export * from "./helpers";
export { BluetoothDevice } from "./device";
export { BluetoothRemoteGATTServer } from "./server";
export { BluetoothRemoteGATTService } from "./service";
export { BluetoothRemoteGATTCharacteristic } from "./characteristic";
export { BluetoothRemoteGATTDescriptor } from "./descriptor";

@@ -31,13 +31,36 @@ /*

/**
* Bluetooth Remote GATT Server class
*/
export class BluetoothRemoteGATTServer {
public connected: boolean = false;
/**
* The device the gatt server is related to
*/
public readonly device: BluetoothDevice = null;
private _connected: boolean = false;
/**
* Whether the gatt server is connected
*/
public get connected(): boolean {
return this._connected;
}
private handle: string = null;
private services: Array<BluetoothRemoteGATTService> = null;
constructor(public device: BluetoothDevice) {
/**
* Server constructor
* @param device Device the gatt server relates to
*/
constructor(device: BluetoothDevice) {
this.device = device;
this.handle = this.device.id;
}
/**
* Connect the gatt server
* @returns Promise containing the gatt server
*/
public connect(): Promise<BluetoothRemoteGATTServer> {

@@ -48,7 +71,7 @@ return new Promise((resolve, reject) => {

adapter.connect(this.handle, () => {
this.connected = true;
this._connected = true;
resolve(this);
}, () => {
this.services = null;
this.connected = false;
this._connected = false;
this.device.dispatchEvent(BluetoothDevice.EVENT_DISCONNECTED);

@@ -62,13 +85,21 @@ this.device._bluetooth.dispatchEvent(BluetoothDevice.EVENT_DISCONNECTED);

/**
* Disconnect the gatt server
*/
public disconnect() {
adapter.disconnect(this.handle);
this.connected = false;
this._connected = false;
}
public getPrimaryService(serviceUUID): Promise<BluetoothRemoteGATTService> {
/**
* Gets a single primary service contained in the gatt server
* @param service service UUID
* @returns Promise containing the service
*/
public getPrimaryService(service: string): Promise<BluetoothRemoteGATTService> {
return new Promise((resolve, reject) => {
if (!this.connected) return reject("getPrimaryService error: device not connected");
if (!serviceUUID) return reject("getPrimaryService error: no service specified");
if (!service) return reject("getPrimaryService error: no service specified");
this.getPrimaryServices(serviceUUID)
this.getPrimaryServices(service)
.then(services => {

@@ -84,3 +115,8 @@ if (services.length !== 1) return reject("getPrimaryService error: service not found");

public getPrimaryServices(serviceUUID): Promise<Array<BluetoothRemoteGATTService>> {
/**
* Gets a list of primary services contained in the gatt server
* @param service service UUID
* @returns Promise containing an array of services
*/
public getPrimaryServices(service?: string): Promise<Array<BluetoothRemoteGATTService>> {
return new Promise((resolve, reject) => {

@@ -90,6 +126,6 @@ if (!this.connected) return reject("getPrimaryServices error: device not connected");

function complete() {
if (!serviceUUID) return resolve(this.services);
if (!service) return resolve(this.services);
const filtered = this.services.filter(service => {
return (service.uuid === getServiceUUID(serviceUUID));
const filtered = this.services.filter(serviceObject => {
return (serviceObject.uuid === getServiceUUID(service));
});

@@ -96,0 +132,0 @@

@@ -32,2 +32,5 @@ /*

/**
* Bluetooth Remote GATT Service class
*/
export class BluetoothRemoteGATTService extends EventDispatcher {

@@ -53,4 +56,15 @@

/**
* The device the service is related to
*/
public readonly device: BluetoothDevice = null;
/**
* The unique identifier of the service
*/
public readonly uuid: string = null;
/**
* Whether the service is a primary one
*/
public readonly isPrimary: boolean = false;

@@ -62,6 +76,15 @@

constructor(init?: Partial<BluetoothRemoteGATTService>) {
/**
* Service constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothRemoteGATTService>) {
super();
Object.assign(this, init);
this.device = init.device;
this.uuid = init.uuid;
this.isPrimary = init.isPrimary;
this.handle = this.uuid;
this.dispatchEvent(BluetoothRemoteGATTService.EVENT_ADDED);

@@ -72,8 +95,13 @@ this.device.dispatchEvent(BluetoothRemoteGATTService.EVENT_ADDED);

public getCharacteristic(characteristicUUID): Promise<BluetoothRemoteGATTCharacteristic> {
/**
* Gets a single characteristic contained in the service
* @param characteristic characteristic UUID
* @returns Promise containing the characteristic
*/
public getCharacteristic(characteristic: string): Promise<BluetoothRemoteGATTCharacteristic> {
return new Promise((resolve, reject) => {
if (!this.device.gatt.connected) return reject("getCharacteristic error: device not connected");
if (!characteristicUUID) return reject("getCharacteristic error: no characteristic specified");
if (!characteristic) return reject("getCharacteristic error: no characteristic specified");
this.getCharacteristics(characteristicUUID)
this.getCharacteristics(characteristic)
.then(characteristics => {

@@ -89,3 +117,8 @@ if (characteristics.length !== 1) return reject("getCharacteristic error: characteristic not found");

public getCharacteristics(characteristicUUID): Promise<Array<BluetoothRemoteGATTCharacteristic>> {
/**
* Gets a list of characteristics contained in the service
* @param characteristic characteristic UUID
* @returns Promise containing an array of characteristics
*/
public getCharacteristics(characteristic?: string): Promise<Array<BluetoothRemoteGATTCharacteristic>> {
return new Promise((resolve, reject) => {

@@ -95,6 +128,6 @@ if (!this.device.gatt.connected) return reject("getCharacteristics error: device not connected");

function complete() {
if (!characteristicUUID) return resolve(this.characteristics);
if (!characteristic) return resolve(this.characteristics);
const filtered = this.characteristics.filter(characteristic => {
return (characteristic.uuid === getCharacteristicUUID(characteristicUUID));
const filtered = this.characteristics.filter(characteristicObject => {
return (characteristicObject.uuid === getCharacteristicUUID(characteristic));
});

@@ -123,8 +156,13 @@

public getIncludedService(serviceUUID): Promise<BluetoothRemoteGATTService> {
/**
* Gets a single service included in the service
* @param service service UUID
* @returns Promise containing the service
*/
public getIncludedService(service: string): Promise<BluetoothRemoteGATTService> {
return new Promise((resolve, reject) => {
if (!this.device.gatt.connected) return reject("getIncludedService error: device not connected");
if (!serviceUUID) return reject("getIncludedService error: no service specified");
if (!service) return reject("getIncludedService error: no service specified");
this.getIncludedServices(serviceUUID)
this.getIncludedServices(service)
.then(services => {

@@ -140,3 +178,8 @@ if (services.length !== 1) return reject("getIncludedService error: service not found");

public getIncludedServices(serviceUUID): Promise<Array<BluetoothRemoteGATTService>> {
/**
* Gets a list of services included in the service
* @param service service UUID
* @returns Promise containing an array of services
*/
public getIncludedServices(service?: string): Promise<Array<BluetoothRemoteGATTService>> {
return new Promise((resolve, reject) => {

@@ -146,6 +189,6 @@ if (!this.device.gatt.connected) return reject("getIncludedServices error: device not connected");

function complete() {
if (!serviceUUID) return resolve(this.services);
if (!service) return resolve(this.services);
const filtered = this.services.filter(service => {
return (service.uuid === getServiceUUID(serviceUUID));
const filtered = this.services.filter(serviceObject => {
return (serviceObject.uuid === getServiceUUID(service));
});

@@ -152,0 +195,0 @@

import { EventDispatcher } from "./dispatcher";
import { BluetoothDevice } from "./device";
/**
* Bluetooth Options interface
*/
export interface BluetoothOptions {
/**
* A `device found` callback function to allow the user to select a device
*/
deviceFound?: (device: BluetoothDevice, selectFn: () => void) => boolean;
/**
* The amount of seconds to scan for the device (default is 10)
*/
scanTime?: number;
/**
* An optional referring device
*/
referringDevice?: BluetoothDevice;
}
/**
* BluetoothLE Scan Filter Init interface
*/
export interface BluetoothLEScanFilterInit {
/**
* An array of service UUIDs to filter on
*/
services?: Array<string>;
/**
* The device name to filter on
*/
name?: string;
/**
* The device name prefix to filter on
*/
namePrefix?: string;
}
/**
* Request Device Options interface
*/
export interface RequestDeviceOptions {
/**
* An array of device filters to match
*/
filters?: Array<BluetoothLEScanFilterInit>;
/**
* An array of optional services to have access to
*/
optionalServices?: Array<string>;
/**
* Whether to accept all devices
*/
acceptAllDevices?: boolean;
deviceFound?: (device: BluetoothDevice, selectFn: any) => boolean;
filters?: Array<BluetoothLEScanFilterInit>;
optionalServices?: Array<any>;
scanTime?: any;
}
/**
* Bluetooth class
*/
export declare class Bluetooth extends EventDispatcher {
readonly referringDevice: BluetoothDevice;
/**

@@ -22,9 +63,30 @@ * Bluetooth Availability Changed event

static EVENT_AVAILABILITY: string;
private defaultScanTime;
/**
* Referring device for the bluetooth instance
*/
readonly referringDevice?: BluetoothDevice;
private deviceFound;
private scanTime;
private scanner;
constructor(referringDevice?: BluetoothDevice);
/**
* Bluetooth constructor
* @param options Bluetooth initialisation options
*/
constructor(options?: BluetoothOptions);
private filterDevice(options, deviceInfo, validServices);
/**
* Gets the availability of a bluetooth adapter
* @returns Promise containing a flag indicating bluetooth availability
*/
getAvailability(): Promise<boolean>;
requestDevice(options: RequestDeviceOptions): Promise<BluetoothDevice>;
/**
* Scans for a device matching optional filters
* @param options The options to use when scanning
* @returns Promise containing a device which matches the options
*/
requestDevice(options?: RequestDeviceOptions): Promise<BluetoothDevice>;
/**
* Cancels the scan for devices
*/
cancelRequest(): Promise<void>;
}
import { EventDispatcher } from "./dispatcher";
import { BluetoothRemoteGATTService } from "./service";
import { BluetoothRemoteGATTDescriptor } from "./descriptor";
/**
* Bluetooth Characteristic Propertiesinterface
*/
export interface BluetoothCharacteristicProperties {
/**
* Broadcast property
*/
broadcast: boolean;
/**
* Read property
*/
read: boolean;
/**
* Write without response property
*/
writeWithoutResponse: boolean;
/**
* Write property
*/
write: boolean;
/**
* Notify property
*/
notify: boolean;
/**
* Indicate property
*/
indicate: boolean;
/**
* Authenticated signed writes property
*/
authenticatedSignedWrites: boolean;
/**
* Reliable write property
*/
reliableWrite: boolean;
/**
* Writable auxiliaries property
*/
writableAuxiliaries: boolean;
}
/**
* Bluetooth Remote GATT Characteristic class
*/
export declare class BluetoothRemoteGATTCharacteristic extends EventDispatcher {

@@ -10,27 +54,59 @@ /**

static EVENT_CHANGED: string;
/**
* The service the characteristic is related to
*/
readonly service: BluetoothRemoteGATTService;
/**
* The unique identifier of the characteristic
*/
readonly uuid: any;
readonly properties: {
broadcast: boolean;
read: boolean;
writeWithoutResponse: boolean;
write: boolean;
notify: boolean;
indicate: boolean;
authenticatedSignedWrites: boolean;
reliableWrite: boolean;
writableAuxiliaries: boolean;
};
/**
* The properties of the characteristic
*/
readonly properties: BluetoothCharacteristicProperties;
private _value;
/**
* The value of the characteristic
*/
readonly value: DataView;
private handle;
private descriptors;
constructor(init?: Partial<BluetoothRemoteGATTCharacteristic>);
/**
* Characteristic constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothRemoteGATTCharacteristic>);
private setValue(value?, emit?);
getDescriptor(descriptorUUID: any): Promise<BluetoothRemoteGATTDescriptor>;
getDescriptors(descriptorUUID: any): Promise<Array<BluetoothRemoteGATTDescriptor>>;
/**
* Gets a single characteristic descriptor
* @param descriptor descriptor UUID
* @returns Promise containing the descriptor
*/
getDescriptor(descriptor: string): Promise<BluetoothRemoteGATTDescriptor>;
/**
* Gets a list of the characteristic's descriptors
* @param descriptor descriptor UUID
* @returns Promise containing an array of descriptors
*/
getDescriptors(descriptor?: string): Promise<Array<BluetoothRemoteGATTDescriptor>>;
/**
* Gets the value of the characteristic
* @returns Promise containing the value
*/
readValue(): Promise<DataView>;
writeValue(bufferSource: ArrayBuffer | ArrayBufferView): Promise<void>;
/**
* Updates the value of the characteristic
* @param value The value to write
*/
writeValue(value: ArrayBuffer | ArrayBufferView): Promise<void>;
/**
* Start notifications of changes for the characteristic
* @returns Promise containing the characteristic
*/
startNotifications(): Promise<BluetoothRemoteGATTCharacteristic>;
/**
* Stop notifications of changes for the characteristic
* @returns Promise containing the characteristic
*/
stopNotifications(): Promise<BluetoothRemoteGATTCharacteristic>;
}
import { BluetoothRemoteGATTCharacteristic } from "./characteristic";
/**
* Bluetooth Remote GATT Descriptor class
*/
export declare class BluetoothRemoteGATTDescriptor {
/**
* The characteristic the descriptor is related to
*/
readonly characteristic: BluetoothRemoteGATTCharacteristic;
/**
* The unique identifier of the descriptor
*/
readonly uuid: string;
private _value;
/**
* The value of the descriptor
*/
readonly value: DataView;
private handle;
constructor(init?: Partial<BluetoothRemoteGATTDescriptor>);
/**
* Descriptor constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothRemoteGATTDescriptor>);
/**
* Gets the value of the descriptor
* @returns Promise containing the value
*/
readValue(): Promise<DataView>;
writeValue(bufferSource: ArrayBuffer | ArrayBufferView): Promise<void>;
/**
* Updates the value of the descriptor
* @param value The value to write
*/
writeValue(value: ArrayBuffer | ArrayBufferView): Promise<void>;
}
import { EventDispatcher } from "./dispatcher";
import { Bluetooth } from "./bluetooth";
import { BluetoothRemoteGATTServer } from "./server";
/**
* Bluetooth Device class
*/
export declare class BluetoothDevice extends EventDispatcher {

@@ -10,5 +13,22 @@ /**

static EVENT_DISCONNECTED: string;
/**
* Advertisement Received event
* @event
*/
static EVENT_ADVERT: string;
/**
* The unique identifier of the device
*/
readonly id: string;
/**
* The name of the device
*/
readonly name: string;
/**
* The gatt server of the device
*/
readonly gatt: BluetoothRemoteGATTServer;
/**
* Whether adverts are being watched (not implemented)
*/
readonly watchingAdvertisements: boolean;

@@ -35,4 +55,16 @@ /**

*/
_serviceUUIDs: Array<string>;
constructor(init?: Partial<BluetoothDevice>);
readonly _serviceUUIDs: Array<string>;
/**
* Device constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothDevice>);
/**
* Starts watching adverts from this device (not implemented)
*/
watchAdvertisements(): Promise<void>;
/**
* Stops watching adverts from this device (not implemented)
*/
unwatchAdvertisements(): Promise<{}>;
}

@@ -0,1 +1,4 @@

/**
* Known services enum
*/
export declare enum bluetoothServices {

@@ -35,2 +38,5 @@ "alert_notification" = 6161,

}
/**
* Known characteristics enum
*/
export declare enum bluetoothCharacteristics {

@@ -199,2 +205,5 @@ "aerobic_heart_rate_lower_limit" = 10878,

}
/**
* Known descriptors enum
*/
export declare enum bluetoothDescriptors {

@@ -217,5 +226,25 @@ "gatt.characteristic_extended_properties" = 10496,

}
/**
* Gets a canonical UUID from a partial UUID in string or hex format
* @param uuid The partial UUID
* @returns canonical UUID
*/
export declare function getCanonicalUUID(uuid: string | number): string;
export declare function getServiceUUID(uuid: string | number): string;
export declare function getCharacteristicUUID(uuid: string | number): string;
export declare function getDescriptorUUID(uuid: string | number): string;
/**
* Gets a canonical service UUID from a known service name or partial UUID in string or hex format
* @param service The known service name
* @returns canonical UUID
*/
export declare function getServiceUUID(service: string | number): string;
/**
* Gets a canonical characteristic UUID from a known characteristic name or partial UUID in string or hex format
* @param characteristic The known characteristic name
* @returns canonical UUID
*/
export declare function getCharacteristicUUID(characteristic: string | number): string;
/**
* Gets a canonical descriptor UUID from a known descriptor name or partial UUID in string or hex format
* @param descriptor The known descriptor name
* @returns canonical UUID
*/
export declare function getDescriptorUUID(descriptor: string | number): string;

@@ -7,2 +7,6 @@ import { Bluetooth } from "./bluetooth";

/**
* Helper methods and enums
*/
export * from "./helpers";
/**
* Bluetooth class for creating new instances

@@ -12,4 +16,8 @@ */

/**
* Helper methods and enums
* Other classes if required
*/
export * from "./helpers";
export { BluetoothDevice } from "./device";
export { BluetoothRemoteGATTServer } from "./server";
export { BluetoothRemoteGATTService } from "./service";
export { BluetoothRemoteGATTCharacteristic } from "./characteristic";
export { BluetoothRemoteGATTDescriptor } from "./descriptor";
import { BluetoothDevice } from "./device";
import { BluetoothRemoteGATTService } from "./service";
/**
* Bluetooth Remote GATT Server class
*/
export declare class BluetoothRemoteGATTServer {
device: BluetoothDevice;
connected: boolean;
/**
* The device the gatt server is related to
*/
readonly device: BluetoothDevice;
private _connected;
/**
* Whether the gatt server is connected
*/
readonly connected: boolean;
private handle;
private services;
/**
* Server constructor
* @param device Device the gatt server relates to
*/
constructor(device: BluetoothDevice);
/**
* Connect the gatt server
* @returns Promise containing the gatt server
*/
connect(): Promise<BluetoothRemoteGATTServer>;
/**
* Disconnect the gatt server
*/
disconnect(): void;
getPrimaryService(serviceUUID: any): Promise<BluetoothRemoteGATTService>;
getPrimaryServices(serviceUUID: any): Promise<Array<BluetoothRemoteGATTService>>;
/**
* Gets a single primary service contained in the gatt server
* @param service service UUID
* @returns Promise containing the service
*/
getPrimaryService(service: string): Promise<BluetoothRemoteGATTService>;
/**
* Gets a list of primary services contained in the gatt server
* @param service service UUID
* @returns Promise containing an array of services
*/
getPrimaryServices(service?: string): Promise<Array<BluetoothRemoteGATTService>>;
}
import { EventDispatcher } from "./dispatcher";
import { BluetoothDevice } from "./device";
import { BluetoothRemoteGATTCharacteristic } from "./characteristic";
/**
* Bluetooth Remote GATT Service class
*/
export declare class BluetoothRemoteGATTService extends EventDispatcher {

@@ -20,4 +23,13 @@ /**

static EVENT_REMOVED: string;
/**
* The device the service is related to
*/
readonly device: BluetoothDevice;
/**
* The unique identifier of the service
*/
readonly uuid: string;
/**
* Whether the service is a primary one
*/
readonly isPrimary: boolean;

@@ -27,7 +39,31 @@ private handle;

private characteristics;
constructor(init?: Partial<BluetoothRemoteGATTService>);
getCharacteristic(characteristicUUID: any): Promise<BluetoothRemoteGATTCharacteristic>;
getCharacteristics(characteristicUUID: any): Promise<Array<BluetoothRemoteGATTCharacteristic>>;
getIncludedService(serviceUUID: any): Promise<BluetoothRemoteGATTService>;
getIncludedServices(serviceUUID: any): Promise<Array<BluetoothRemoteGATTService>>;
/**
* Service constructor
* @param init A partial class to initialise values
*/
constructor(init: Partial<BluetoothRemoteGATTService>);
/**
* Gets a single characteristic contained in the service
* @param characteristic characteristic UUID
* @returns Promise containing the characteristic
*/
getCharacteristic(characteristic: string): Promise<BluetoothRemoteGATTCharacteristic>;
/**
* Gets a list of characteristics contained in the service
* @param characteristic characteristic UUID
* @returns Promise containing an array of characteristics
*/
getCharacteristics(characteristic?: string): Promise<Array<BluetoothRemoteGATTCharacteristic>>;
/**
* Gets a single service included in the service
* @param service service UUID
* @returns Promise containing the service
*/
getIncludedService(service: string): Promise<BluetoothRemoteGATTService>;
/**
* Gets a list of services included in the service
* @param service service UUID
* @returns Promise containing an array of services
*/
getIncludedServices(service?: string): Promise<Array<BluetoothRemoteGATTService>>;
}

@@ -0,18 +1,78 @@

import { EventDispatcher } from "./dispatcher";
import { BluetoothDevice } from "./device";
import { Adapter } from "./adapter";
export interface FilterOptions {
acceptAllDevices: boolean;
deviceFound: (device: BluetoothDevice, selectFn: any) => void;
filters: Array<any>;
optionalServices: Array<any>;
scanTime: any;
/**
* BluetoothLE Scan Filter Init interface
*/
export interface BluetoothLEScanFilterInit {
/**
* An array of service UUIDs to filter on
*/
services?: Array<string>;
/**
* The device name to filter on
*/
name?: string;
/**
* The device name prefix to filter on
*/
namePrefix?: string;
}
export declare class WebBluetooth {
private adapter;
/**
* Request Device Options interface
*/
export interface RequestDeviceOptions {
/**
* Whether to accept all devices
*/
acceptAllDevices?: boolean;
/**
* A `device found` callback function to allow the user to select a device
*/
deviceFound?: (device: BluetoothDevice, selectFn: any) => boolean;
/**
* An array of device filters to match
*/
filters?: Array<BluetoothLEScanFilterInit>;
/**
* An array of optional services to have access to
*/
optionalServices?: Array<any>;
/**
* The amount of seconds to scan for the device (default is 10)
*/
scanTime?: number;
}
/**
* WebBluetooth class
*/
export declare class WebBluetooth extends EventDispatcher {
readonly referringDevice: BluetoothDevice;
/**
* Bluetooth Availability Changed event
* @event
*/
static EVENT_AVAILABILITY: string;
private defaultScanTime;
private scanner;
constructor(adapter?: Adapter);
/**
* WebBluetooth constructor
* @param referringDevice An optional referring device
*/
constructor(referringDevice?: BluetoothDevice);
private filterDevice(options, deviceInfo, validServices);
requestDevice(options: FilterOptions): Promise<{}>;
cancelRequest(): Promise<{}>;
/**
* Gets the availability of a bluetooth adapter
* @returns Promise containing a flag indicating bluetooth availability
*/
getAvailability(): Promise<boolean>;
/**
* Scans for a device matching optional filters
* @param options The options to use when scanning
* @returns Promise containing a device which matches the options
*/
requestDevice(options?: RequestDeviceOptions): Promise<BluetoothDevice>;
/**
* Cancels the scan for devices
*/
cancelRequest(): Promise<void>;
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc