advlib-ble-services
Advanced tools
Comparing version 1.5.1 to 1.6.0
@@ -34,2 +34,4 @@ /** | ||
switch(uuid) { | ||
case '2a07': | ||
case '2a19': | ||
case '2a37': | ||
@@ -40,6 +42,9 @@ case '2a67': | ||
case '2a6e': | ||
case '2a6f': | ||
case '2aa1': | ||
case '2aa2': | ||
case '2aee': | ||
case '2af9': | ||
case '2afb': | ||
case '2b18': | ||
case '2b8c': | ||
@@ -50,2 +55,3 @@ case '2bcf': | ||
case '2bd2': | ||
case '2be4': | ||
case '2be7': | ||
@@ -52,0 +58,0 @@ return gatt.process(data, uuid); |
147
lib/gatt.js
/** | ||
* Copyright reelyActive 2015-2023 | ||
* Copyright reelyActive 2015-2024 | ||
* We believe in an open Internet of Things | ||
@@ -12,2 +12,6 @@ */ | ||
const TX_POWER_LEVEL_STRUCT_LENGTH = 1; | ||
const TX_POWER_LEVEL_MIN_VALUE = -100; | ||
const TX_POWER_LEVEL_MAX_VALUE = 20; | ||
const BATTERY_LEVEL_STRUCT_LENGTH = 1; | ||
const HRM_MIN_STRUCT_LENGTH = 2; | ||
@@ -26,7 +30,11 @@ const HRM_MAX_STRUCT_LENGTH = 21; // Assumes 8 RR-intervals (could be higher?) | ||
const TEMPERATURE_MIN_VALUE = -273.15; | ||
const HUMIDITY_STRUCT_LENGTH = 2; | ||
const MFD3D_STRUCT_LENGTH = 6; | ||
const LANGUAGE_STRUCT_LENGTH = 2; // Assumes ISO 639-1 two-character codes only | ||
const ELECTRIC_CURRENT_STRUCT_LENGTH = 2; | ||
const GENERIC_LEVEL_STRUCT_LENGTH = 2; | ||
const ILLUMINANCE_STRUCT_LENGTH = 3; | ||
const ILLUMINANCE_UNKNOWN_VALUE = 167772.15; | ||
const VOLTAGE_STRUCT_LENGTH = 2; | ||
const VOLTAGE_MAX_VALUE = 1022; | ||
const CO2_CONCENTRATION_STRUCT_LENGTH = 2; | ||
@@ -38,2 +46,4 @@ const CO2_CONCENTRATION_UNKNOWN_VALUE = 0xffff; | ||
const NO2_CONCENTRATION_STRUCT_LENGTH = 2; | ||
const NOISE_STRUCT_LENGTH = 1; | ||
const NOISE_MAX_VALUE = 253; | ||
const VOC_CONCENTRATION_STRUCT_LENGTH = 2; | ||
@@ -57,2 +67,6 @@ const VOC_CONCENTRATION_UNKNOWN_VALUE = 0xffff; | ||
switch(uuid) { | ||
case '2a07': | ||
return processTxPowerLevel(buf); | ||
case '2a19': | ||
return processBatteryLevel(buf); | ||
case '2a37': | ||
@@ -68,2 +82,4 @@ return processHeartRateMeasurement(buf); | ||
return processTemperature(buf); | ||
case '2a6f': | ||
return processHumidity(buf); | ||
case '2aa1': | ||
@@ -73,2 +89,4 @@ return processMagneticFluxDensity3D(buf); | ||
return processLanguage(buf); | ||
case '2aee': | ||
return processElectricCurrent(buf); | ||
case '2af9': | ||
@@ -78,2 +96,4 @@ return processGenericLevel(buf); | ||
return processIlluminance(buf); | ||
case '2b18': | ||
return processVoltage(buf); | ||
case '2b8c': | ||
@@ -89,2 +109,4 @@ return processCarbonDioxideConcentration(buf); | ||
return processNitrogenDioxideConcentration(buf); | ||
case '2be4': | ||
return processNoise(buf); | ||
case '2be7': | ||
@@ -99,2 +121,45 @@ return processVolatileOrganicCompoundsConcentration(buf); | ||
/** | ||
* Process tx power level data. | ||
* @param {Object} data The raw service data as a Buffer. | ||
* @return {Object} The processed tx power level data as JSON. | ||
*/ | ||
function processTxPowerLevel(data) { | ||
let isInvalidLength = (data.length !== TX_POWER_LEVEL_STRUCT_LENGTH); | ||
if(isInvalidLength) { | ||
return null; | ||
} | ||
let txPower = data.readInt8(); | ||
if((txPower < TX_POWER_LEVEL_MIN_VALUE) || | ||
(txPower > TX_POWER_LEVEL_MAX_VALUE)) { | ||
return null; | ||
} | ||
return { txPower: txPower }; | ||
} | ||
/** | ||
* Process battery level data. | ||
* @param {Object} data The raw service data as a Buffer. | ||
* @return {Object} The processed battery level data as JSON. | ||
*/ | ||
function processBatteryLevel(data) { | ||
let isInvalidLength = (data.length !== BATTERY_LEVEL_STRUCT_LENGTH); | ||
if(isInvalidLength) { | ||
return null; | ||
} | ||
let batteryPercentage = data.readUInt8(); | ||
if(batteryPercentage > 100) { | ||
return null; | ||
} | ||
return { batteryPercentage: batteryPercentage }; | ||
} | ||
/** | ||
* Process heart rate measurement data. | ||
@@ -265,2 +330,23 @@ * @param {Object} data The raw service data as a Buffer. | ||
/** | ||
* Process humidity data. | ||
* @param {Object} data The raw service data as a Buffer. | ||
* @return {Object} The processed humidity data as JSON. | ||
*/ | ||
function processHumidity(data) { | ||
let isInvalidLength = (data.length !== HUMIDITY_STRUCT_LENGTH); | ||
if(isInvalidLength) { | ||
return null; | ||
} | ||
let relativeHumidity = data.readUInt16LE() / 100; | ||
if(relativeHumidity > 100) { | ||
return null; | ||
} | ||
return { relativeHumidity: relativeHumidity }; | ||
} | ||
/** | ||
* Process 3-dimensional magnetic flux density data. | ||
@@ -305,2 +391,19 @@ * @param {Object} data The raw service data as a Buffer. | ||
/** | ||
* Process electric current data. | ||
* @param {Object} data The raw service data as a Buffer. | ||
* @return {Object} The processed electric current data as JSON. | ||
*/ | ||
function processElectricCurrent(data) { | ||
let isInvalidLength = (data.length !== ELECTRIC_CURRENT_STRUCT_LENGTH); | ||
if(isInvalidLength) { | ||
return null; | ||
} | ||
let amperage = data.readUIntLE(0, 2) / 100; | ||
return { amperage: amperage }; | ||
} | ||
/** | ||
* Process generic level data. | ||
@@ -344,2 +447,23 @@ * @param {Object} data The raw service data as a Buffer. | ||
/** | ||
* Process voltage data. | ||
* @param {Object} data The raw service data as a Buffer. | ||
* @return {Object} The processed voltage data as JSON. | ||
*/ | ||
function processVoltage(data) { | ||
let isInvalidLength = (data.length !== VOLTAGE_STRUCT_LENGTH); | ||
if(isInvalidLength) { | ||
return null; | ||
} | ||
let voltage = data.readUInt16LE() / 64; | ||
if(voltage > VOLTAGE_MAX_VALUE) { | ||
return null; | ||
} | ||
return { voltage: voltage }; | ||
} | ||
/** | ||
* Process carbon dioxide concentration data. | ||
@@ -455,2 +579,23 @@ * @param {Object} data The raw service data as a Buffer. | ||
/** | ||
* Process noise data. | ||
* @param {Object} data The raw service data as a Buffer. | ||
* @return {Object} The processed noise data as JSON. | ||
*/ | ||
function processNoise(data) { | ||
let isInvalidLength = (data.length !== NOISE_STRUCT_LENGTH); | ||
if(isInvalidLength) { | ||
return null; | ||
} | ||
let soundPressure = data.readUInt8(); | ||
if(soundPressure > NOISE_MAX_VALUE) { | ||
return null; | ||
} | ||
return { soundPressure: soundPressure }; | ||
} | ||
/** | ||
* Process volatile organic compounds concentration data. | ||
@@ -457,0 +602,0 @@ * @param {Object} data The raw service data as a Buffer. |
@@ -18,3 +18,3 @@ { | ||
], | ||
"version": "1.5.1", | ||
"version": "1.6.0", | ||
"engines": { | ||
@@ -21,0 +21,0 @@ "node": ">=6.0.0" |
@@ -8,3 +8,3 @@ advlib-ble-services | ||
__advlib-ble-services__ is a lightweight [Node.js package](https://www.npmjs.com/package/advlib-ble-services) with no dependencies. See also its sister library [advlib-ble-manufacturers](https://github.com/reelyactive/advlib-ble-manufacturers). | ||
__advlib-ble-services__ is a lightweight [Node.js package](https://www.npmjs.com/package/advlib-ble-services) with no dependencies. It is included in reelyActive's [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source IoT middleware. See also its sister library [advlib-ble-manufacturers](https://github.com/reelyactive/advlib-ble-manufacturers). | ||
@@ -44,2 +44,4 @@ | ||
|:-------------|:------------------------------|:----------------------------| | ||
| 0x2a07 | Tx Power Level | gatt.js | | ||
| 0x2a19 | Battery Level | gatt.js | | ||
| 0x2a37 | Heart Rate Measurement | gatt.js | | ||
@@ -50,6 +52,9 @@ | 0x2a67 | Location and Speed | gatt.js | | ||
| 0x2a6e | Temperature | gatt.js | | ||
| 0x2a6f | Humidity | gatt.js | | ||
| 0x2aa1 | Magnetic flux density 3D | gatt.js | | ||
| 0x2aa2 | Language | gatt.js | | ||
| 0x2aee | Electric Current | gatt.js | | ||
| 0x2af9 | Generic Level | gatt.js | | ||
| 0x2afb | Illuminance | gatt.js | | ||
| 0x2b18 | Voltage | gatt.js | | ||
| 0x2b8c | CO2 Concentration | gatt.js | | ||
@@ -60,2 +65,3 @@ | 0x2bcf | Ammonia Concentration | gatt.js | | ||
| 0x2bd2 | NO2 Concentration | gatt.js | | ||
| 0x2be4 | Noise | gatt.js | | ||
| 0x2be7 | VOC Concentration | gatt.js | | ||
@@ -62,0 +68,0 @@ | 0xfd6f | Exposure Notification | exposurenotification.js | |
/** | ||
* Copyright reelyActive 2021 | ||
* Copyright reelyActive 2021-2024 | ||
* We believe in an open Internet of Things | ||
@@ -13,2 +13,6 @@ */ | ||
const INPUT_UUID_INVALID = 'ffff'; | ||
const INPUT_DATA_TX_POWER_LEVEL = 'fc'; | ||
const INPUT_UUID_TX_POWER_LEVEL = '2a07'; | ||
const INPUT_DATA_BATTERY_LEVEL = '45'; | ||
const INPUT_UUID_BATTERY_LEVEL = '2a19'; | ||
const INPUT_DATA_HRM_MIN = '007b'; | ||
@@ -31,2 +35,4 @@ const INPUT_DATA_HRM_ALL = '1f7b00230100040002'; | ||
const INPUT_UUID_TEMPERATURE = '2a6e'; | ||
const INPUT_DATA_HUMIDITY = '391b'; | ||
const INPUT_UUID_HUMIDITY = '2a6f'; | ||
const INPUT_DATA_MFD3D_POSITIVE = 'f4010000e803'; | ||
@@ -37,2 +43,4 @@ const INPUT_DATA_MFD3D_NEGATIVE = '0cfeffff18fc'; | ||
const INPUT_UUID_LANGUAGE = '2aa2'; | ||
const INPUT_DATA_ELECTRIC_CURRENT = '3930'; | ||
const INPUT_UUID_ELECTRIC_CURRENT = '2aee'; | ||
const INPUT_DATA_GENERIC_LEVEL = '971f'; | ||
@@ -43,2 +51,4 @@ const INPUT_UUID_GENERIC_LEVEL = '2af9'; | ||
const INPUT_UUID_ILLUMINANCE = '2afb'; | ||
const INPUT_DATA_VOLTAGE = 'dc1e'; | ||
const INPUT_UUID_VOLTAGE = '2b18'; | ||
const INPUT_DATA_CO2_CONCENTRATION_UNKNOWN = 'ffff'; | ||
@@ -56,2 +66,4 @@ const INPUT_DATA_CO2_CONCENTRATION = 'de03'; | ||
const INPUT_DATA_VOC_CONCENTRATION_UNKNOWN = 'ffff'; | ||
const INPUT_DATA_NOISE = '7b'; | ||
const INPUT_UUID_NOISE = '2be4'; | ||
const INPUT_DATA_VOC_CONCENTRATION = 'de03'; | ||
@@ -63,2 +75,4 @@ const INPUT_UUID_VOC_CONCENTRATION = '2be7'; | ||
const EXPECTED_DATA_INVALID_INPUT = null; | ||
const EXPECTED_DATA_TX_POWER_LEVEL = { txPower: -4 }; | ||
const EXPECTED_DATA_BATTERY_LEVEL = { batteryPercentage: 69 }; | ||
const EXPECTED_DATA_HRM_MIN = { heartRate: 123 }; | ||
@@ -88,2 +102,3 @@ const EXPECTED_DATA_HRM_ALL = { | ||
const EXPECTED_DATA_TEMPERATURE_NEGATIVE = { temperature: -12.34 }; | ||
const EXPECTED_DATA_HUMIDITY = { relativeHumidity: 69.69 }; | ||
const EXPECTED_DATA_MFD3D_POSITIVE = { magneticField: [ 0.5, 0, 1 ] }; | ||
@@ -94,3 +109,5 @@ const EXPECTED_DATA_MFD3D_NEGATIVE = { magneticField: [ -0.5, -0.001, -1 ] }; | ||
const EXPECTED_DATA_LANGUAGE = { languages: [ 'fr' ] }; | ||
const EXPECTED_DATA_ELECTRIC_CURRENT = { amperage: 123.45 }; | ||
const EXPECTED_DATA_GENERIC_LEVEL = { levelPercentage: 12.339971007858397 }; | ||
const EXPECTED_DATA_VOLTAGE = { voltage: 123.4375 }; | ||
const EXPECTED_DATA_CO2_CONCENTRATION_UNKNOWN = null; | ||
@@ -104,2 +121,3 @@ const EXPECTED_DATA_CO2_CONCENTRATION = { carbonDioxideConcentration: 990 }; | ||
const EXPECTED_DATA_NO2_CONCENTRATION = { nitrogenDioxideConcentration: 666 }; | ||
const EXPECTED_DATA_NOISE = { soundPressure: 123 }; | ||
const EXPECTED_DATA_VOC_CONCENTRATION_UNKNOWN = null; | ||
@@ -125,2 +143,16 @@ const EXPECTED_DATA_VOC_CONCENTRATION = { | ||
// Test the process function with tx power level data | ||
it('should handle tx power level data as input', function() { | ||
assert.deepEqual(service.process(INPUT_DATA_TX_POWER_LEVEL, | ||
INPUT_UUID_TX_POWER_LEVEL), | ||
EXPECTED_DATA_TX_POWER_LEVEL); | ||
}); | ||
// Test the process function with battery level data | ||
it('should handle battery level data as input', function() { | ||
assert.deepEqual(service.process(INPUT_DATA_BATTERY_LEVEL, | ||
INPUT_UUID_BATTERY_LEVEL), | ||
EXPECTED_DATA_BATTERY_LEVEL); | ||
}); | ||
// Test the process function with minimal HRM data | ||
@@ -201,2 +233,8 @@ it('should handle minimal HRM data as input', function() { | ||
// Test the process function with humidity data | ||
it('should handle humidity data as input', function() { | ||
assert.deepEqual(service.process(INPUT_DATA_HUMIDITY, INPUT_UUID_HUMIDITY), | ||
EXPECTED_DATA_HUMIDITY); | ||
}); | ||
// Test the process function with positive magnetic flux density data | ||
@@ -220,2 +258,9 @@ it('should handle positive magnetic flux density data as input', function() { | ||
// Test the process function with electric current data | ||
it('should handle electric current data as input', function() { | ||
assert.deepEqual(service.process(INPUT_DATA_ELECTRIC_CURRENT, | ||
INPUT_UUID_ELECTRIC_CURRENT), | ||
EXPECTED_DATA_ELECTRIC_CURRENT); | ||
}); | ||
// Test the process function with generic level data | ||
@@ -240,2 +285,8 @@ it('should handle generic level data as input', function() { | ||
// Test the process function with voltage data | ||
it('should handle voltage data as input', function() { | ||
assert.deepEqual(service.process(INPUT_DATA_VOLTAGE, INPUT_UUID_VOLTAGE), | ||
EXPECTED_DATA_VOLTAGE); | ||
}); | ||
// Test the process function with unknown CO2 concentration data | ||
@@ -283,2 +334,8 @@ it('should handle unknown CO2 concentration data as input', function() { | ||
// Test the process function with noise data | ||
it('should handle noise data as input', function() { | ||
assert.deepEqual(service.process(INPUT_DATA_NOISE, INPUT_UUID_NOISE), | ||
EXPECTED_DATA_NOISE); | ||
}); | ||
// Test the process function with unknown VOC concentration data | ||
@@ -285,0 +342,0 @@ it('should handle unknown VOC concentration data as input', function() { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
94541
2115
125