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

web-bluetooth

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

web-bluetooth - npm Package Compare versions

Comparing version 0.0.11 to 0.0.12

700

lib/BluetoothDevice.js

@@ -1,435 +0,297 @@

import { errorHandler } from "/utils/errorHandler";
import { bluetooth } from "/utils/bluetoothMap";
import { errorHandler } from '/utils/errorHandler';
import { bluetooth } from '/utils/bluetoothMap';
/**
* @method connect - Establishes a connection with the device
* NOTE: This method must be triggered by a user gesture to satisfy the native API's permissions
*
* @param {object} filters - Collection of filters for device selection
* all filters are optional, but at least 1 is required
* .name {string}
* .namePrefix {string}
* .uuid {string}
* .services {array}
* .optionalServices {array} - defaults to all available services,
* use an empty array to get no optional services
*
* @return {object} Returns a new instance of BluetoothDevice
*
*/
/**
* @method connect - Establishes a connection with the device
* @method connected - checks apiDevice to see whether device is connected
* @method disconnect - terminates the connection with the device and pauses all data stream subscriptions
* @method getValue - reads the value of a specified characteristic
* @method writeValue - writes data to a specified characteristic of the device
* @method startNotifications - attempts to start notifications for changes to device values and attaches an event listener for each data transmission
* @method stopNotifications - attempts to stop previously started notifications for a provided characteristic
* @method addCharacteristic - adds a new characteristic object to bluetooth.gattCharacteristicsMapping
* @method _returnCharacteristic - _returnCharacteristic - returns the value of a cached or resolved characteristic or resolved characteristic
*
* @param {object} filters - collection of filters for device selectin. All filters are optional, but at least 1 is required.
* .name {string}
* .namePrefix {string}
* .uuid {string}
* .services {array}
* .optionalServices {array} - defaults to all available services, use an empty array to get no optional services
*
* @return {object} Returns a new instance of BluetoothDevice
*
*/
export default class BluetoothDevice {
constructor(requestParams) {
this.requestParams = requestParams;
this.apiDevice = null;
this.apiServer = null;
this.cache = {};
}
constructor(requestParams) {
this.requestParams = requestParams;
this.apiDevice = null;
this.apiServer = null;
this.cache = {};
}
/**
* checks apiDevice to see whether device is connected
*/
connected() {
if(!this.apiDevice) return errorHandler('no_device');
return this.apiDevice.gatt.connected;
}
connected() {
return this.apiDevice ? this.apiDevice.gatt.connected : errorHandler('no_device');
}
/**
* Establishes a new GATT connection w/ the device
* and stores the return of the promise as this.apiServer
*/
connect() {
const filters = this.requestParams;
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
if (Object.keys(filters).length) {
const requestParams = {
filters: [],
};
if (filters.name) requestParams.filters.push({ name: filters.name });
if (filters.namePrefix) requestParams.filters.push({ namePrefix: filters.namePrefix });
if (filters.uuid) {
if (!filters.uuid.match(uuidRegex)) {
errorHandler('uuid_error');
}
else {
requestParams.filters.push({ uuid: filters.uuid });
}
}
if (filters.services) {
let services =[];
filters.services.forEach(service => {
if (!bluetooth.gattServiceList.includes(service)) {
console.warn(`${service} is not a valid service. Please check the service name.`);
}
else {
services.push(service);
}
});
requestParams.filters.push({ services: services });
}
if (filters.optional_services) {
filters.optional_services.forEach(service => {
if(!bluetooth.gattServiceList.includes(service)) bluetooth.gattServiceList.push(service);
});
}
/** connect - establishes a connection with the device
*
* NOTE: This method must be triggered by a user gesture to satisfy the native API's permissions
*
* @return {object} - native browser API device server object
*/
connect() {
const filters = this.requestParams;
const requestParams = { filters: [], };
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]/;
if(!Object.keys(filters).length) { return errorHandler('no_filters'); }
if (filters.name) requestParams.filters.push({ name: filters.name });
if (filters.namePrefix) requestParams.filters.push({ namePrefix: filters.namePrefix });
if (filters.uuid) {
if (!filters.uuid.match(uuidRegex)) {
errorHandler('uuid_error');
} else {
requestParams.filters.push({ uuid: filters.uuid });
}
}
if (filters.services) {
let services = [];
filters.services.forEach(service => {
if (!bluetooth.gattServiceList.includes(service)) {
console.warn(`${service} is not a valid service. Please check the service name.`);
} else { services.push(service); }
});
requestParams.filters.push({ services: services });
}
if (filters.optional_services) {
filters.optional_services.forEach(service => {
if (!bluetooth.gattServiceList.includes(service)) bluetooth.gattServiceList.push(service);
});
} else { requestParams.optionalServices = bluetooth.gattServiceList; }
return navigator.bluetooth.requestDevice(requestParams)
.then(device => {
this.apiDevice = device;
return device.gatt.connect();
}).then(server => {
this.apiServer = server;
return server;
}).catch(err => {
return errorHandler('user_cancelled', err);
});
}
requestParams.optionalServices = bluetooth.gattServiceList;
/** disconnect - terminates the connection with the device and pauses all data stream subscriptions
* @return {boolean} - success
*
*/
disconnect() {
this.apiServer.connected ? this.apiServer.disconnect() : errorHandler('not_connected');
return this.apiServer.connected ? errorHandler('issue_disconnecting') : true;
}
return navigator.bluetooth.requestDevice(requestParams)
.then(device => {
this.apiDevice = device;
return device.gatt.connect()
}).then(server => {
this.apiServer = server;
return server;
}).catch(err => {
errorHandler('user_cancelled',err);
return;
});
} else {
return errorHandler('no_filters');
}
};
/** getValue - reads the value of a specified characteristic
*
* @param {string} characteristic_name - GATT characteristic name
* @return {promise} - resolves with an object that includes key-value pairs for each of the properties
* successfully read and parsed from the device, as well as the
* raw value object returned by a native readValue request to the
* device characteristic.
*/
getValue(characteristic_name) {
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
/**
* Attempts to disconnect from BT device
*
* @return {boolean} successfully disconnected
*
* NOTE: All subscribed data streams will resume automatically upon re-connection
*/
disconnect() {
if (this.apiServer.connected) {
this.apiServer.disconnect();
//TODO: check if this is asynchronous when retesting.
if (!this.apiServer.connected) {
if (!characteristicObj.includedProperties.includes('read')) {
console.warn(`Attempting to access read property of ${characteristic_name},
which is not a included as a supported property of the
characteristic. Attempt will resolve with an object including
only a rawValue property with the native API return
for an attempt to readValue() of ${characteristic_name}.`);
}
return new Promise((resolve, reject) => { return resolve(this._returnCharacteristic(characteristic_name)); })
.then(characteristic => { return characteristic.readValue(); })
.then(value => {
const returnObj = characteristicObj.parseValue ? characteristicObj.parseValue(value) : {};
returnObj.rawValue = value;
return returnObj;
}).catch(err => { return errorHandler('read_error', err); });
}
/** writeValue - writes data to a specified characteristic of the device
*
* @param {string} characteristic_name - name of the GATT characteristic
* https://www.bluetooth.com/specifications/assigned-numbers/generic-attribute-profile
*
* @param {string|number} value - value to write to the requested device characteristic
*
*
* @return {boolean} - Result of attempt to write characteristic where true === successfully written
*/
writeValue(characteristic_name, value) {
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
if (!characteristicObj.includedProperties.includes('write')) {
console.warn(`Attempting to access write property of ${characteristic_name},
which is not a included as a supported property of the
characteristic. Attempt will resolve with native API return
for an attempt to writeValue(${value}) to ${characteristic_name}.`);
}
return new Promise((resolve, reject) => { return resolve(this._returnCharacteristic(characteristic_name)); })
.then(characteristic => { return characteristic.writeValue(characteristicObj.prepValue ? characteristicObj.prepValue(value) : value); })
.then(changedChar => { return value; })
.catch(err => { return errorHandler('write_error', err, characteristic_name); });
}
/** startNotifications - attempts to start notifications for changes to device values and attaches an event listener for each data transmission
*
* @param {string} characteristic_name - GATT characteristic name
* @param {callback} transmissionCallback - callback function to apply to each event while notifications are active
*
* @return
*
*/
startNotifications(characteristic_name, transmissionCallback) {
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) { return errorHandler('characteristic_error', null, characteristic_name); }
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
const primary_service_name = characteristicObj.primaryServices[0];
if (!characteristicObj.includedProperties.includes('notify')) {
console.warn(`Attempting to access notify property of ${characteristic_name},
which is not a included as a supported property of the
characteristic. Attempt will resolve with an object including
only a rawValue property with the native API return
for an attempt to startNotifications() for ${characteristic_name}.`);
}
return new Promise((resolve, reject) => { return resolve(this._returnCharacteristic(characteristic_name)); })
.then(characteristic => {
characteristic.startNotifications().then(() => {
this.cache[primary_service_name][characteristic_name].notifying = true;
return characteristic.addEventListener('characteristicvaluechanged', event => {
const eventObj = characteristicObj.parseValue ? characteristicObj.parseValue(event.target.value) : {};
eventObj.rawValue = event;
return transmissionCallback(eventObj);
});
});
}).catch(err => { return errorHandler('start_notifications_error', err, characteristic_name); });
}
/** stopNotifications - attempts to stop previously started notifications for a provided characteristic
*
* @param {string} characteristic_name - GATT characteristic name
*
* @return {boolean} success
*
*/
stopNotifications(characteristic_name) {
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
const primary_service_name = characteristicObj.primaryServices[0];
if (this.cache[primary_service_name][characteristic_name].notifying) {
return new Promise((resolve, reject) => { return resolve(this._returnCharacteristic(characteristic_name)); })
.then(characteristic => {
characteristic.stopNotifications().then(() => {
this.cache[primary_service_name][characteristic_name].notifying = false;
return true;
}
return errorHandler('issue_disconnecting');
}
return errorHandler('not_connected');
}
});
}).catch(err => {
return errorHandler('stop_notifications_error', err, characteristic_name);
});
} else {
return errorHandler('stop_notifications_not_notifying', null, characteristic_name);
}
}
/**
* Gets requested characteristic before attempting to read value of that characteristic
* and returning an object with the parsed value (if characterisitc is fully supported)
* and raw value (provided regardles of whether device is fully supported or not).
*
* @param {string} characteristic_name - GATT characteristic name
* @return {Object} An object that includes key-value pairs for each of the properties
* successfully read and parsed from the device, as well as the
* raw value object returned by a native readValue request to the
* device characteristic.
*/
getValue(characteristic_name) {
// Check to see if characteristic exists in bluetooth.gattCharacteristicsMapping and throw error if not found.
if(!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
// Retrieve characteristic object from bluetooth.gattCharacteristicsMapping
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
/*
* Check characteristic object to see if support for read property is provided.
* If not provided, proceed with attempt to read value of characteristic but
* provide warning indicating such.
*/
if (!characteristicObj.includedProperties.includes('read')) {
console.warn(`Attempting to access read property of ${characteristic_name},
which is not a included as a supported property of the
characteristic. Attempt will resolve with an object including
only a rawValue property with the native API return
for an attempt to readValue() of ${characteristic_name}.`);
}
// Call returnCharacteristic to retrieve characteristic from which to read
return new Promise((resolve,reject) => {
return resolve(this.returnCharacteristic(characteristic_name));
}).then(characteristic =>{
return characteristic.readValue();
}).then(value =>{
/*
* Check characteristic object to see if parsing method exists. If present,
* call the parseValue method with value returned from readValue() as the
* argument, and add returned value from readValue() as another parameter to
* the returned object from parseValue before returning. If no parsing method
* is present, return an object with the returned value from readValue() as
* the only parameter.
*/
const returnObj = characteristicObj.parseValue ? characteristicObj.parseValue(value):{};
// Always include the raw value returned from readValue() in the object returned
returnObj.rawValue = value;
return returnObj;
}).catch(err => {
return errorHandler('read_error',err);
});
}
/**
* addCharacteristic - adds a new characteristic object to bluetooth.gattCharacteristicsMapping
*
* @param {string} characteristic_name - GATT characteristic name or other characteristic
* @param {string} primary_service_name - GATT primary service name or other parent service of characteristic
* @param {array} propertiesArr - Array of GATT properties as Strings
*
* @return {boolean} - Result of attempt to add characteristic where true === successfully added
*/
addCharacteristic(characteristic_name, primary_service_name, propertiesArr) {
if (bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('add_characteristic_exists_error', null, characteristic_name);
}
if (!characteristic_name || characteristic_name.constructor !== String || !characteristic_name.length) {
return errorHandler('improper_characteristic_format', null, characteristic_name);
}
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
if (!primary_service_name || !propertiesArr) {
return errorHandler('new_characteristic_missing_params', null, characteristic_name);
}
if (primary_service_name.constructor !== String || !primary_service_name.length) {
return errorHandler('improper_service_format', null, primary_service_name);
}
if (propertiesArr.constuctor !== Array || !propertiesArr.length) {
return errorHandler('improper_properties_format', null, propertiesArr);
}
/**
* Attempts to write a given value to the device for a given characteristic
* @param {String} characteristic_name - GATT characteristic name
* @param {String or Number} value - String or Number that will be written to
the requested device characteristic
*
* @return {Boolean} - Result of attempt to write characteristic where true === successfully written
*/
writeValue(characteristic_name, value) {
/*
* Check to see if characteristic exists in bluetooth.gattCharacteristicsMapping
* and throw error if not found.
*/
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
// Retrieve characteristic object from bluetooth.gattCharacteristicsMapping
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
/*
* Check characteristic object to see if support for write property is provided.
* If not provided, proceed with attempt to write value to characteristic but
* provide warning indicating such.
*/
if (!characteristicObj.includedProperties.includes('write')) {
console.warn(`Attempting to access write property of ${characteristic_name},
which is not a included as a supported property of the
characteristic. Attempt will resolve with native API return
for an attempt to writeValue(${value}) to ${characteristic_name}.`);
}
// Call returnCharacteristic to retrieve characteristic from which to read
return new Promise((resolve,reject) => {
return resolve(this.returnCharacteristic(characteristic_name))
}).then(characteristic => {
/**
* Check characteristic object to see if prepping method exists. If present,
* call the prepValue method with the provided value as the argument. If
* no prepping method is present, attempt to call writeValue() to the
* characteristic with the provided value as the the argument.
*/
value = characteristicObj.prepValue ? characteristicObj.prepValue(value):value;
return characteristic.writeValue(value);
}).then(changedChar => {
return value;
}).catch(err => {
return errorHandler('write_error',err,characteristic_name);
})
}
console.warn(`${characteristic_name} is not yet fully supported.`);
bluetooth.gattCharacteristicsMapping[characteristic_name] = {
primaryServices: [primary_service_name],
includedProperties: propertiesArr,
};
/**
* startNotifications - Attempts to start notifications for changes to device values and adds an event
* listener for each data transmission
*
* @param {string} characteristic_name - GATT characteristic name
* @param {callback} transmissionCallback - callback function to apply to each event while notifications are active
*
*/
startNotifications(characteristic_name, transmissionCallback){
// Check to see if characteristic exists in bluetooth.gattCharacteristicsMapping and throw error if not found.
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
// Retrieve characteristic object and primary service from bluetooth.gattCharacteristicsMapping
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
const primary_service_name = characteristicObj.primaryServices[0];
/*
* Check characteristic object to see if support for notify property is provided.
* If not provided, proceed with attempt to start notifications from characteristic but
* provide warning indicating such.
*/
if (!characteristicObj.includedProperties.includes('notify')) {
console.warn(`Attempting to access notify property of ${characteristic_name},
which is not a included as a supported property of the
characteristic. Attempt will resolve with an object including
only a rawValue property with the native API return
for an attempt to startNotifications() for ${characteristic_name}.`);
}
// Call returnCharacteristic to retrieve characteristic from which to read
return new Promise((resolve,reject) => {
return resolve(this.returnCharacteristic(characteristic_name))
}).then(characteristic => {
// Start notifications from characteristic and add event listener
characteristic.startNotifications().then(() => {
/*
* After successfully starting notifications from characteristic, update
* cache to reflect current notification status.
*/
this.cache[primary_service_name][characteristic_name].notifying = true;
// Add listener to subscribe to notifications from device
return characteristic.addEventListener('characteristicvaluechanged', event => {
/*
* Check characteristic object to see if parsing method exists. If present,
* call the parseValue method with value attached to the event object,
* and add the raw event object as another parameter to the returned
* object from parseValue before returning. If no parsing method is
* present, return an object with the raw event object as the only parameter.
*/
const eventObj = characteristicObj.parseValue ? characteristicObj.parseValue(event.target.value):{};
// Always include the raw event object in the object returned
eventObj.rawValue = event;
transmissionCallback(eventObj);
});
})
}).catch(err => {
return errorHandler('start_notifications_error', err, characteristic_name);
});
}
return true;
}
}
/**
* Attempts to stop previously started notifications for a provided characteristic
*
* @param {String} characteristic_name - GATT characteristic name
* @return {Boolean} - Result of attempt to stop notifications where true === successfully written
*/
stopNotifications(characteristic_name) {
// Check to see if characteristic exists in bluetooth.gattCharacteristicsMapping and throws an error if not found.
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
// Retrieve characteristic object and primary service from bluetooth.gattCharacteristicsMapping
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
const primary_service_name = characteristicObj.primaryServices[0];
/*
* Check characteristic object to see if notifications are currently active
* and attempt to stop notifications if active, otherwise throw error.
*/
if(this.cache[primary_service_name][characteristic_name].notifying) {
// Call returnCharacteristic to retrieve characteristic from which to read
return new Promise((resolve,reject) => {
return resolve(this.returnCharacteristic(characteristic_name))
}).then(characteristic => {
characteristic.stopNotifications().then(() => {
// After successfully stopping notifications from characteristic, update the cache to reflect current notification status.
this.cache[primary_service_name][characteristic_name].notifying = false;
return true;
})
}).catch(err => {
return errorHandler('stop_notifications_error', err, characteristic_name);
})
}
else {
errorHandler('stop_notifications_not_notifying',null,characteristic_name);
}
}
/**
* _returnCharacteristic - returns the value of a cached or resolved characteristic or resolved characteristic
*
* @param {string} characteristic_name - GATT characteristic name
* @return {object|false} - the characteristic object, if successfully obtained
*/
_returnCharacteristic(characteristic_name) {
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
/**
* Adds a new characteristic object to bluetooth.gattCharacteristicsMapping
*
* @param {String} characteristic_name - GATT characteristic name or other characteristic
* @param {String} primary_service_name - GATT primary service name or other parent service of characteristic
* @param {Array} propertiesArr - Array of GATT properties as Strings
*
* @return {Boolean} - Result of attempt to add characteristic where true === successfully added
*/
addCharacteristic(characteristic_name, primary_service_name, propertiesArr) {
/*
* Check to see if characteristic exists in bluetooth.gattCharacteristicsMapping
* and throw error if found.
*/
if(bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('add_characteristic_exists_error', null, characteristic_name);
}
// Check formatting of characteristic_name and throw error if improperly formatted
if (!characteristic_name || characteristic_name.constructor !== String || !characteristic_name.length){
return errorHandler(`improper_characteristic_format`,null, characteristic_name);
}
/*
* If characteristic does not exist in bluetooth.gattCharacteristicsMapping
* validate presence and format of other required parameters. Throw errors if
* other required parameters are missing or improperly formatted.
*/
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
// If missing any of other required parameters, throw error
if (!primary_service_name || !propertiesArr) {
return errorHandler(`new_characteristic_missing_params`,null, characteristic_name);
}
// Check formatting of primary_service_name and throw error if improperly formatted
if (primary_service_name.constructor !== String || !primary_service_name.length){
return errorHandler(`improper_service_format`,null, primary_service_name);
}
// Check formatting of propertiesArr and throw error if improperly formatted
if (propertiesArr.constuctor !== Array || !propertiesArr.length) {
return errorHandler(`improper_properties_format`,null, propertiesArr);
}
/*
* If all parameters are present and properly formatted add new object to
* bluetooth.gattCharacteristicsMapping and provide warning that added
* characteristic is not fully supported.
*/
console.warn(`Attempting to add ${characteristic_name}. Full support
for this characteristic is not provided.`);
bluetooth.gattCharacteristicsMapping[characteristic_name] = {
primaryServices: [primary_service_name],
includedProperties: propertiesArr
}
return true;
}
}
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
const primary_service_name = characteristicObj.primaryServices[0];
/**
* returnCharacteristic - returns a cached characteristic or resolved characteristic after
* successful connection with device
*
* @param {string} characteristic_name - GATT characteristic name
* @return {object} - If the method successfully retrieves the characteristic,
* that characteristic is returned
*/
returnCharacteristic(characteristic_name) {
/*
* Check to see if characteristic exists in bluetooth.gattCharacteristicsMapping
* and throw error if not found.
*/
if (!bluetooth.gattCharacteristicsMapping[characteristic_name]) {
return errorHandler('characteristic_error', null, characteristic_name);
}
/*
* Retrieve characteristic object from bluetooth.gattCharacteristicsMapping
* and establish primary service
*/
const characteristicObj = bluetooth.gattCharacteristicsMapping[characteristic_name];
const primary_service_name = characteristicObj.primaryServices[0];
/*
* Check to see if requested characteristic has been cached from a previous
* interaction of any type to characteristic_name and return if found
*/
if (this.cache[primary_service_name] && this.cache[primary_service_name][characteristic_name] && this.cache[primary_service_name][characteristic_name].cachedCharacteristic) {
return this.cache[primary_service_name][characteristic_name].cachedCharacteristic;
}
/*
* Check to see if requested characteristic's parent primary service has
* been cached from a any previous interaction with that primary service
*/
else if (this.cache[primary_service_name] && this.cache[primary_service_name].cachedService) {
/*
* If parent primary service has been cached, use getCharacteristic method
* on the cached service and cache resolved characteristic before returning
*/
this.cache[primary_service_name].cachedService.getCharacteristic(characteristic_name).then(characteristic => {
// Cache characteristic before returning characteristic
this.cache[primary_service_name][characteristic_name] = {'cachedCharacteristic': characteristic};
return characteristic;
})
.catch(err => {
return errorHandler('returnCharacteristic_error', err, characteristic_name);
});
}
/*
* If neither characteristic nor any parent primary service of that characteristic
* has been cached, use cached device server to access and cache both the
* characteristic and primary parent service before returning characteristic
*/
else {
return this.apiServer.getPrimaryService(primary_service_name).then(service => {
// Cache primary service before attempting to access characteristic
this.cache[primary_service_name] = {'cachedService': service};
return service.getCharacteristic(characteristic_name);
}).then(characteristic => {
// Cache characteristic before returning
this.cache[primary_service_name][characteristic_name] = {'cachedCharacteristic': characteristic};
return characteristic;
}).catch(err => {
return errorHandler('returnCharacteristic_error', err, characteristic_name);
});
}
}
if (this.cache[primary_service_name] && this.cache[primary_service_name][characteristic_name] && this.cache[primary_service_name][characteristic_name].cachedCharacteristic) {
return this.cache[primary_service_name][characteristic_name].cachedCharacteristic;
} else if (this.cache[primary_service_name] && this.cache[primary_service_name].cachedService) {
this.cache[primary_service_name].cachedService.getCharacteristic(characteristic_name)
.then(characteristic => {
this.cache[primary_service_name][characteristic_name] = { cachedCharacteristic: characteristic };
return characteristic;
}).catch(err => { return errorHandler('_returnCharacteristic_error', err, characteristic_name); });
} else {
return this.apiServer.getPrimaryService(primary_service_name)
.then(service => {
this.cache[primary_service_name] = { 'cachedService': service };
return service.getCharacteristic(characteristic_name);
}).then(characteristic => {
this.cache[primary_service_name][characteristic_name] = { cachedCharacteristic: characteristic };
return characteristic;
}).catch(err => {
return errorHandler('_returnCharacteristic_error', err, characteristic_name);
});
}
}
}

@@ -9,17 +9,17 @@ /** errorHandler - Consolodates error message configuration and logic

function errorHandler(errorKey, nativeError, alternate) {
// Object mapping error codes (keys) to error messages (values)
const errorMessages = {
add_characteristic_exists_error: `Characteristic ${alternateParam} already exists.`,
characteristic_error: `Characteristic ${alternateParam} not found. Add ${alternateParam} to device using addCharacteristic or try another characteristic.`,
connect_gatt: `Error. Could not connect to GATT. Device might be out of range. Also check to see if filters are vaild.`,
connect_server: `Error. Could not connect to server on device.`,
connect_service: `Error. Could not find service.`,
connect_gatt: `Could not connect to GATT. Device might be out of range. Also check to see if filters are vaild.`,
connect_server: `Could not connect to server on device.`,
connect_service: `Could not find service.`,
disconnect_timeout: `Timed out. Could not disconnect.`,
disconnect_error: `Error. Could not disconnect from device.`,
improper_characteristic_format: `Error. ${alternateParam} is not a properly formatted characteristic.`,
improper_properties_format: `Error. ${alternateParam} is not a properly formatted properties array.`,
improper_service_format: `Error. ${alternateParam} is not a properly formatted service.`,
disconnect_error: `Could not disconnect from device.`,
improper_characteristic_format: `${alternateParam} is not a properly formatted characteristic.`,
improper_properties_format: `${alternateParam} is not a properly formatted properties array.`,
improper_service_format: `${alternateParam} is not a properly formatted service.`,
issue_disconnecting: `Issue disconnecting with device.`,
new_characteristic_missing_params: `Error. ${alternateParam} is not a fully supported characteristic. Please provide an associated primary service and at least one property.`,
no_device: `Error. No instance of device found.`,
new_characteristic_missing_params: `${alternateParam} is not a fully supported characteristic. Please provide an associated primary service and at least one property.`,
no_device: `No instance of device found.`,
no_filters: `No filters found on instance of Device. For more information, please visit http://sabertooth.io/#method-newdevice`,

@@ -30,22 +30,18 @@ no_read_property: `No read property on characteristic: ${alternateParam}.`,

parsing_not_supported: `Parsing not supported for characterstic: ${alternateParam}.`,
postValue_error: `Error. Could not post value to device.`,
read_error: `Error. Cannot read value on the characteristic.`,
returnCharacteristic_error: `Error accessing characteristic ${alternateParam}.`,
start_notifications_error: `Error. Not able to read stream of data from characteristic: ${alternateParam}.`,
start_notifications_no_notify: `Error. No notify property found on this characteristic: ${alternateParam}.`,
read_error: `Cannot read value on the characteristic.`,
_returnCharacteristic_error: `Error accessing characteristic ${alternateParam}.`,
start_notifications_error: `Not able to read stream of data from characteristic: ${alternateParam}.`,
start_notifications_no_notify: `No notify property found on this characteristic: ${alternateParam}.`,
stop_notifications_not_notifying: `Notifications not established for characteristic: ${alternateParam} or you have not started notifications.`,
stop_notifications_error: `Issue stopping notifications for characteristic: ${alternateParam} or you have not started notifications.`,
user_cancelled: `User cancelled the permission request.`,
uuid_error: `Error. Invalid UUID. For more information on proper formatting of UUIDs, visit https://webbluetoothcg.github.io/web-bluetooth/#uuids`,
write_error: `Error. Could not change value of characteristic: ${alternateParam}.`,
write_permissions: `Error. ${alternateParam} characteristic does not have a write property.`
uuid_error: `Invalid UUID. For more information on proper formatting of UUIDs, visit https://webbluetoothcg.github.io/web-bluetooth/#uuids`,
write_error: `Could not change value of characteristic: ${alternateParam}.`,
write_permissions: `${alternateParam} characteristic does not have a write property.`
}
if(nativeError) {
throw new Error(`${errorMessages[errorKey]} ${nativeError}`);
}
else {
throw new Error(errorMessages[errorKey]);
}
throw new Error(errorMessages[errorKey]);
return false;
}
module.exports = { errorHandler };
{
"name": "web-bluetooth",
"version": "0.0.11",
"version": "0.0.12",
"description": "A configurable application framework for integrating bluetooth functionality with client-side javascript. Currently in Alpha.",

@@ -48,3 +48,5 @@ "keywords": [

"eslint-config-airbnb": "^9.0.1",
"eslint-plugin-import": "^1.8.1",
"eslint-plugin-jsx-a11y": "^1.2.2",
"eslint-plugin-react": "^5.1.1",
"mocha": "^2.4.5",

@@ -51,0 +53,0 @@ "sinon": "^1.17.4"

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