gatt-ip-js
Version:
GATT-IP library is A simple javascript protocol to connect any Bluetooth Smart (GATT) Device to the IP network
232 lines (212 loc) • 7.58 kB
JavaScript
var C = require('./constants').C;
var constantNames = {};
var InternalError = require('./../errors').InternalError;
var ApplicationError = require('./../errors').ApplicationError;
for (var name in C) {
//noinspection JSUnfilteredForInLoop
var code = C[name];
//noinspection JSUnfilteredForInLoop
if (name.indexOf('k') == 0) {
//noinspection JSUnfilteredForInLoop
name = name.substring(1, name.length);
constantNames[code] = name;
}
}
module.exports.isEmpty = function (obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop))
return false;
}
return JSON.stringify(obj) === JSON.stringify({});
};
module.exports.arrayAsHex = function (array, pretty) {
var ret = (pretty ? '0x' : '');
for (var i in array) {
//noinspection JSUnfilteredForInLoop
var value = (array[i] & 0xFF).toString(16);
if (value.length == 1) {
value = '0' + value;
}
ret += value;
}
return ret;
};
function recursiveToString(obj) {
var ret = '';
if (typeof obj == 'object') {
if (Array.isArray(obj)) {
var val = '';
for (var i in obj) {
if (0 != i) {
ret += ' ,';
}
ret += obj[i];
}
}
for (var name in obj) {
if (obj.hasOwnProperty(name)) {
var value = obj[name];
var constantName = constantNames[name];
if (!constantName) {
constantName = name;
}
if ('object' == typeof value) {
if (Array.isArray(value)) {
ret += ' ' + constantName + ':[' + recursiveToString(value) + ']';
} else {
ret += ' ' + constantName + ':{' + recursiveToString(value) + '}';
}
} else {
ret += ' ' + constantName + '=' + value;
}
}
}
}
return ret;
}
module.exports.toString = function (message) {
return recursiveToString(message.params).trim();
};
/**
* Just a meaningful name because the requireFields function can handle
*/
module.exports.requireAndAssignParameters = function (callDescription, object, fields, values) {
module.exports.requireFields(callDescription + " call parameters ", object, fields, values);
};
module.exports.requireBooleanValue = function (description, parameterName, value) {
if (typeof value != 'boolean') {
throw new ApplicationError(description + ' missing parameter ' + parameterName);
}
};
module.exports.requireHexValue = function (description, parameterName, value) {
if (typeof value != 'string') {
throw new ApplicationError(description + ' missing parameter ' + parameterName);
}
if (value.length > 0 && (value.length % 2 != 0 || !(/^[0-9a-fA-F]+$/.test(value)))) {
throw new ApplicationError(description + ' value ' + parameterName + ' is not a valid hex string');
}
};
module.exports.requireUUID = function (description, parameterName, value) {
if (typeof value != 'string') {
throw new ApplicationError(description + ' missing parameter ' + parameterName);
}
if (value.length < 4 ||!(/^[0-9A-F-]+$/.test(value))) {
throw new ApplicationError(description + ' value ' + parameterName + ' is not a valid UUID');
}
};
module.exports.requireHexValues = function (description, parameterNames, hexValues) {
var missingFields = [];
if (!Array.isArray(parameterNames) || !Array.isArray(hexValues)) {
throw new InternalError("Illegal use of requireHexValues");
}
for (var i = 0; i < parameterNames.length; i++) {
var pName = parameterNames[i];
var value = hexValues[i];
if (typeof value != 'string' || value.length < 2 || value.length % 2 != 0 || !/^#[0-9A-F]$/i.test(value)) {
missingFields.push(pName);
}
}
if (missingFields) {
throw new ApplicationError(description + ' missing parameters ' + missingFields);
}
};
module.exports.requireFields = function (description, object, fields, defaultsOrValues) {
var missingFields = [];
if (!defaultsOrValues) {
defaultsOrValues = {};
}
if (!object) {
throw new InternalError(description + 'Object is undefined');
}
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if (typeof object[field] == undefined) {
if (typeof defaultsOrValues[i] == undefined) {
missingFields.push(fields);
} else {
object[field] = defaultsOrValues[i];
}
}
}
if (missingFields.length) {
throw new InternalError(description + ' missing ' + missingFields);
}
};
module.exports.requireAndPopulateFieldsFromCookie = function (callDescription, cookie, message) {
if (!cookie) {
throw new ApplicationError('Error: "' + callDescription + ' is missing the cookie');
}
if (!cookie.original.id) {
throw new ApplicationError('Error: "' + callDescription + ' is missing the cookie ID');
}
if (!cookie.original.session_id) {
throw new ApplicationError('Error: "' + callDescription + ' is missing the cookie session ID');
}
if (!cookie.original.method) {
throw new ApplicationError('Error: "' + callDescription + ' is missing the cookie request');
}
message[C.kMessageId] = cookie.original.id;
message[C.kSessionId] = cookie.original.session_id;
message.result = cookie.result;
};
module.exports.populateParams = function (serviceTableObject, params) {
if (!params) {
params = {};
}
if (!serviceTableObject) {
throw new InternalError('populateParams: service object is undefined');
}
var p;
var s;
var c;
var d;
var remainingParts = 23132;
switch (serviceTableObject.type) {
case 'd':
remainingParts = 4;
d = serviceTableObject;
break;
case 'c':
remainingParts = 3;
c = serviceTableObject;
break;
case 's':
remainingParts = 2;
s = serviceTableObject;
break;
case 'p':
remainingParts = 1;
p = serviceTableObject;
break;
default:
throw new InternalError('type must be one of: "s", "c" or "d"');
break;
}
function storeField(field, obj) {
remainingParts--;
var uuid = obj.uuid;
if (!uuid) {
throw new InternalError('UUID for object of type "' + obj.type + '" is missing');
}
params[field] = uuid;
}
if (d) {
storeField(C.kDescriptorUUID, d);
c = d.characteristic();
}
if (c) {
storeField(C.kCharacteristicUUID, c);
s = c.service();
}
if (s) {
storeField(C.kServiceUUID, s);
p = c.peripheral();
}
if (p) {
storeField(C.kPeripheralUUID, p);
}
if (remainingParts != 0) {
throw new InternalError('Expected ' + remainingParts + ' more parts when constructing params of ' + serviceTableObject.type);
}
return params;
};