@stoprocent/bleno 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jshintrc +5 -0
- package/LICENSE +20 -0
- package/README.md +409 -0
- package/binding.gyp +17 -0
- package/examples/battery-service/README.md +14 -0
- package/examples/battery-service/battery-level-characteristic.js +45 -0
- package/examples/battery-service/battery-service.js +16 -0
- package/examples/battery-service/main.js +28 -0
- package/examples/battery-service/package-lock.json +1314 -0
- package/examples/battery-service/package.json +20 -0
- package/examples/blink1/README.md +44 -0
- package/examples/blink1/blink1-fade-rgb-characteristic.js +42 -0
- package/examples/blink1/blink1-rgb-characteristic.js +38 -0
- package/examples/blink1/blink1-service.js +19 -0
- package/examples/blink1/device-information-service.js +19 -0
- package/examples/blink1/hardware-revision-characteristic.js +32 -0
- package/examples/blink1/main.js +32 -0
- package/examples/blink1/serial-number-characteristic.js +21 -0
- package/examples/echo/characteristic.js +45 -0
- package/examples/echo/main.js +33 -0
- package/examples/pizza/README.md +16 -0
- package/examples/pizza/peripheral.js +57 -0
- package/examples/pizza/pizza-bake-characteristic.js +40 -0
- package/examples/pizza/pizza-crust-characteristic.js +52 -0
- package/examples/pizza/pizza-service.js +20 -0
- package/examples/pizza/pizza-toppings-characteristic.js +41 -0
- package/examples/pizza/pizza.js +58 -0
- package/examples/uart/main.js +23 -0
- package/index.d.ts +153 -0
- package/index.js +1 -0
- package/lib/bleno.js +231 -0
- package/lib/characteristic.js +91 -0
- package/lib/descriptor.js +17 -0
- package/lib/hci-socket/acl-stream.js +37 -0
- package/lib/hci-socket/bindings.js +219 -0
- package/lib/hci-socket/crypto.js +74 -0
- package/lib/hci-socket/gap.js +212 -0
- package/lib/hci-socket/gatt.js +1028 -0
- package/lib/hci-socket/hci-status.json +67 -0
- package/lib/hci-socket/hci.js +796 -0
- package/lib/hci-socket/mgmt.js +89 -0
- package/lib/hci-socket/smp.js +160 -0
- package/lib/hci-socket/vs.js +156 -0
- package/lib/mac/binding.gyp +39 -0
- package/lib/mac/bindings.js +12 -0
- package/lib/mac/src/ble_peripheral_manager.h +32 -0
- package/lib/mac/src/ble_peripheral_manager.mm +241 -0
- package/lib/mac/src/bleno_mac.h +26 -0
- package/lib/mac/src/bleno_mac.mm +167 -0
- package/lib/mac/src/callbacks.h +76 -0
- package/lib/mac/src/callbacks.mm +124 -0
- package/lib/mac/src/napi_objc.h +30 -0
- package/lib/mac/src/napi_objc.mm +286 -0
- package/lib/mac/src/noble_mac.h +34 -0
- package/lib/mac/src/noble_mac.mm +260 -0
- package/lib/mac/src/objc_cpp.h +27 -0
- package/lib/mac/src/objc_cpp.mm +144 -0
- package/lib/mac/src/peripheral.h +23 -0
- package/lib/primary-service.js +19 -0
- package/lib/resolve-bindings.js +19 -0
- package/lib/uuid-util.js +7 -0
- package/package.json +77 -0
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/test/characteristic.test.js +174 -0
- package/test/descriptor.test.js +46 -0
- package/test/mocha.setup.js +0 -0
- package/with-bindings.js +5 -0
- package/with-custom-binding.js +6 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
//
|
|
2
|
+
// objc_cpp.mm
|
|
3
|
+
// bleno-mac-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Georg Vienna on 30.08.18.
|
|
6
|
+
//
|
|
7
|
+
#include "objc_cpp.h"
|
|
8
|
+
|
|
9
|
+
#if defined(MAC_OS_X_VERSION_10_13)
|
|
10
|
+
//#pragma clang diagnostic push
|
|
11
|
+
//#pragma clang diagnostic ignored "-Wunguarded-availability"
|
|
12
|
+
//std::string stateToString(CBManagerState state)
|
|
13
|
+
//{
|
|
14
|
+
// switch(state) {
|
|
15
|
+
// case CBManagerStatePoweredOff:
|
|
16
|
+
// return "poweredOff";
|
|
17
|
+
// case CBManagerStatePoweredOn:
|
|
18
|
+
// return "poweredOn";
|
|
19
|
+
// case CBManagerStateResetting:
|
|
20
|
+
// return "resetting";
|
|
21
|
+
// case CBManagerStateUnauthorized:
|
|
22
|
+
// return "unauthorized";
|
|
23
|
+
// case CBManagerStateUnknown:
|
|
24
|
+
// return "unknown";
|
|
25
|
+
// case CBManagerStateUnsupported:
|
|
26
|
+
// return "unsupported";
|
|
27
|
+
// }
|
|
28
|
+
// return "unknown";
|
|
29
|
+
//}
|
|
30
|
+
//#pragma clang diagnostic pop
|
|
31
|
+
|
|
32
|
+
// In the 10.13 SDK, CBPeripheral became a subclass of CBPeer, which defines
|
|
33
|
+
// -[CBPeer identifier] as partially available. Pretend it still exists on
|
|
34
|
+
// CBPeripheral. At runtime the implementation on CBPeer will be invoked.
|
|
35
|
+
@interface CBPeripheral (HighSierraSDK)
|
|
36
|
+
@property(readonly, nonatomic) NSUUID* identifier;
|
|
37
|
+
@end
|
|
38
|
+
#else
|
|
39
|
+
std::string stateToString(CBCentralManagerState state)
|
|
40
|
+
{
|
|
41
|
+
switch(state) {
|
|
42
|
+
case CBCentralManagerStatePoweredOff:
|
|
43
|
+
return "poweredOff";
|
|
44
|
+
case CBCentralManagerStatePoweredOn:
|
|
45
|
+
return "poweredOn";
|
|
46
|
+
case CBCentralManagerStateResetting:
|
|
47
|
+
return "resetting";
|
|
48
|
+
case CBCentralManagerStateUnauthorized:
|
|
49
|
+
return "unauthorized";
|
|
50
|
+
case CBCentralManagerStateUnknown:
|
|
51
|
+
return "unknown";
|
|
52
|
+
case CBCentralManagerStateUnsupported:
|
|
53
|
+
return "unsupported";
|
|
54
|
+
}
|
|
55
|
+
return "unknown";
|
|
56
|
+
}
|
|
57
|
+
#endif
|
|
58
|
+
|
|
59
|
+
std::string StringFromCBPeripheralState(CBManagerState state) {
|
|
60
|
+
switch(state) {
|
|
61
|
+
case CBManagerStatePoweredOff:
|
|
62
|
+
return "poweredOff";
|
|
63
|
+
case CBManagerStatePoweredOn:
|
|
64
|
+
return "poweredOn";
|
|
65
|
+
case CBManagerStateUnauthorized:
|
|
66
|
+
return "unauthorized";
|
|
67
|
+
case CBManagerStateUnsupported:
|
|
68
|
+
return "unsupported";
|
|
69
|
+
case CBManagerStateResetting:
|
|
70
|
+
return "resetting";
|
|
71
|
+
case CBManagerStateUnknown:
|
|
72
|
+
default:
|
|
73
|
+
return "unknown";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
NSString* getNSUuid(CBPeripheral* peripheral) {
|
|
78
|
+
return peripheral.identifier.UUIDString;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
std::string getUuid(CBPeripheral* peripheral) {
|
|
82
|
+
return std::string([peripheral.identifier.UUIDString UTF8String]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
std::string getAddress(std::string uuid, AddressType* addressType) {
|
|
86
|
+
NSString* deviceUuid = [[NSString alloc] initWithCString:uuid.c_str() encoding:NSASCIIStringEncoding];
|
|
87
|
+
IF(NSDictionary*, plist, [NSDictionary dictionaryWithContentsOfFile:@"/Library/Preferences/com.apple.Bluetooth.plist"]) {
|
|
88
|
+
IF(NSDictionary*, cache, [plist objectForKey:@"CoreBluetoothCache"]) {
|
|
89
|
+
IF(NSDictionary*, entry, [cache objectForKey:deviceUuid]) {
|
|
90
|
+
IF(NSNumber*, type, [entry objectForKey:@"DeviceAddressType"]) {
|
|
91
|
+
*addressType = [type boolValue] ? RANDOM : PUBLIC;
|
|
92
|
+
}
|
|
93
|
+
IF(NSString*, address, [entry objectForKey:@"DeviceAddress"]) {
|
|
94
|
+
return [address UTF8String];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
std::vector<std::string> getServices(NSArray<CBService*>* services) {
|
|
103
|
+
std::vector<std::string> result;
|
|
104
|
+
if(services) {
|
|
105
|
+
for (CBService* service in services) {
|
|
106
|
+
result.push_back([[service.UUID UUIDString] UTF8String]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#define TEST_PROP(type, str) if((characteristic.properties & type) == type) { properties.push_back(str); }
|
|
113
|
+
|
|
114
|
+
std::vector<std::pair<std::string, std::vector<std::string>>> getCharacteristics(NSArray<CBCharacteristic*>* characteristics) {
|
|
115
|
+
std::vector<std::pair<std::string, std::vector<std::string>>> result;
|
|
116
|
+
if(characteristics) {
|
|
117
|
+
for (CBCharacteristic* characteristic in characteristics) {
|
|
118
|
+
auto uuid = [[characteristic.UUID UUIDString] UTF8String];
|
|
119
|
+
auto properties = std::vector<std::string>();
|
|
120
|
+
TEST_PROP(CBCharacteristicPropertyBroadcast, "broadcast");
|
|
121
|
+
TEST_PROP(CBCharacteristicPropertyRead, "read");
|
|
122
|
+
TEST_PROP(CBCharacteristicPropertyWriteWithoutResponse, "writeWithoutResponse");
|
|
123
|
+
TEST_PROP(CBCharacteristicPropertyWrite, "write");
|
|
124
|
+
TEST_PROP(CBCharacteristicPropertyNotify, "notify");
|
|
125
|
+
TEST_PROP(CBCharacteristicPropertyIndicate, "indicate");
|
|
126
|
+
TEST_PROP(CBCharacteristicPropertyAuthenticatedSignedWrites, "authenticatedSignedWrites");
|
|
127
|
+
TEST_PROP(CBCharacteristicPropertyExtendedProperties, "extendedProperties");
|
|
128
|
+
TEST_PROP(CBCharacteristicPropertyNotifyEncryptionRequired, "notifyEncryptionRequired");
|
|
129
|
+
TEST_PROP(CBCharacteristicPropertyIndicateEncryptionRequired, "indicateEncryptionRequired");
|
|
130
|
+
result.push_back(std::make_pair(uuid, properties));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
std::vector<std::string> getDescriptors(NSArray<CBDescriptor*>* descriptors) {
|
|
137
|
+
std::vector<std::string> result;
|
|
138
|
+
if(descriptors) {
|
|
139
|
+
for (CBDescriptor* descriptor in descriptors) {
|
|
140
|
+
result.push_back([[descriptor.UUID UUIDString] UTF8String]);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
using Data = std::vector<uint8_t>;
|
|
4
|
+
|
|
5
|
+
enum AddressType {
|
|
6
|
+
PUBLIC,
|
|
7
|
+
RANDOM,
|
|
8
|
+
UNKNOWN,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
class Peripheral {
|
|
12
|
+
public:
|
|
13
|
+
Peripheral() : address("unknown"), addressType(UNKNOWN), connectable(false) {
|
|
14
|
+
}
|
|
15
|
+
std::string address;
|
|
16
|
+
AddressType addressType;
|
|
17
|
+
bool connectable;
|
|
18
|
+
std::string name;
|
|
19
|
+
int txPowerLevel;
|
|
20
|
+
Data manufacturerData;
|
|
21
|
+
std::vector<std::pair<std::string, Data>> serviceData;
|
|
22
|
+
std::vector<std::string> serviceUuids;
|
|
23
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { EventEmitter } = require('events');
|
|
2
|
+
const UuidUtil = require('./uuid-util');
|
|
3
|
+
|
|
4
|
+
class PrimaryService extends EventEmitter {
|
|
5
|
+
constructor (options) {
|
|
6
|
+
super();
|
|
7
|
+
this.uuid = UuidUtil.removeDashes(options.uuid);
|
|
8
|
+
this.characteristics = options.characteristics || [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
toString () {
|
|
12
|
+
return JSON.stringify({
|
|
13
|
+
uuid: this.uuid,
|
|
14
|
+
characteristics: this.characteristics
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = PrimaryService;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
|
|
3
|
+
module.exports = function (options = {}) {
|
|
4
|
+
const platform = os.platform();
|
|
5
|
+
|
|
6
|
+
if (
|
|
7
|
+
platform === 'linux' ||
|
|
8
|
+
platform === 'freebsd' ||
|
|
9
|
+
platform === 'win32' ||
|
|
10
|
+
platform === 'android' ||
|
|
11
|
+
process.env.BLUETOOTH_HCI_SOCKET_UART_PORT ||
|
|
12
|
+
process.env.BLUETOOTH_HCI_SOCKET_FORCE_UART) {
|
|
13
|
+
return new (require('./hci-socket/bindings'))(options);
|
|
14
|
+
} else if (platform === 'darwin') {
|
|
15
|
+
return new (require('./mac/bindings'))(options);
|
|
16
|
+
} else {
|
|
17
|
+
throw new Error('Unsupported platform ' + platform);
|
|
18
|
+
}
|
|
19
|
+
};
|
package/lib/uuid-util.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stoprocent/bleno",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "A Node.js module for implementing BLE (Bluetooth Low Energy) peripherals",
|
|
5
|
+
"main": "./index.js",
|
|
6
|
+
"types": "./index.d.ts",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=14"
|
|
9
|
+
},
|
|
10
|
+
"os": [
|
|
11
|
+
"darwin",
|
|
12
|
+
"linux",
|
|
13
|
+
"android",
|
|
14
|
+
"freebsd",
|
|
15
|
+
"win32"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"install": "node-gyp-build",
|
|
19
|
+
"lint": "eslint \"**/*.js\"",
|
|
20
|
+
"lint-fix": "eslint \"**/*.js\" --fix",
|
|
21
|
+
"prebuildify": "prebuildify --napi --target 14.0.0 --force --strip --verbose",
|
|
22
|
+
"prebuildify-cross": "prebuildify-cross --napi --target 14.0.0 --force --strip --verbose",
|
|
23
|
+
"semantic-release": "semantic-release",
|
|
24
|
+
"pretest": "npm run rebuild",
|
|
25
|
+
"rebuild": "node-gyp rebuild",
|
|
26
|
+
"coverage": "nyc npm test && nyc report --reporter=text-lcov > .nyc_output/lcov.info",
|
|
27
|
+
"test": "cross-env NODE_ENV=test mocha --recursive \"test/*.test.js\" \"test/**/*.test.js\" --exit"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/stoprocent/bleno"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"BLE",
|
|
35
|
+
"Bluetooth",
|
|
36
|
+
"Bluetooth Low Energy",
|
|
37
|
+
"Bluetooth Smart",
|
|
38
|
+
"peripheral"
|
|
39
|
+
],
|
|
40
|
+
"author": "Sandeep Mistry <sandeep.mistry@gmail.com>",
|
|
41
|
+
"maintainers": [
|
|
42
|
+
"Marek Serafin <marek@serafin.email>"
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"readmeFilename": "README.md",
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@semantic-release/exec": "^6.0.3",
|
|
48
|
+
"cross-env": "^7.0.3",
|
|
49
|
+
"jshint": "~2.13.6",
|
|
50
|
+
"eslint": "^8.31.0",
|
|
51
|
+
"eslint-config-semistandard": "^17.0.0",
|
|
52
|
+
"eslint-config-standard": "^17.0.0",
|
|
53
|
+
"eslint-plugin-import": "^2.26.0",
|
|
54
|
+
"eslint-plugin-n": "^15.6.0",
|
|
55
|
+
"eslint-plugin-promise": "^6.1.1",
|
|
56
|
+
"mocha": "~10.2.0",
|
|
57
|
+
"node-blink1": "~0.5.1",
|
|
58
|
+
"nyc": "^15.1.0",
|
|
59
|
+
"prebuildify": "^5.0.1",
|
|
60
|
+
"prebuildify-cross": "5.0.0",
|
|
61
|
+
"should": "~13.2.3"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"debug": "^4.3.4",
|
|
65
|
+
"napi-thread-safe-callback": "^0.0.6",
|
|
66
|
+
"node-addon-api": "^4.3.0",
|
|
67
|
+
"node-gyp-build": "^4.5.0"
|
|
68
|
+
},
|
|
69
|
+
"optionalDependencies": {
|
|
70
|
+
"@stoprocent/bluetooth-hci-socket": "^1.1.3",
|
|
71
|
+
"bplist-parser": "0.3.2",
|
|
72
|
+
"xpc-connect": "^3.0.0"
|
|
73
|
+
},
|
|
74
|
+
"publishConfig": {
|
|
75
|
+
"access": "public"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/* jshint mocha: true */
|
|
2
|
+
|
|
3
|
+
const should = require('should');
|
|
4
|
+
|
|
5
|
+
const Characteristic = require('../lib/characteristic');
|
|
6
|
+
|
|
7
|
+
describe('Characteristic', function () {
|
|
8
|
+
const mockUuid = 'mockuuid';
|
|
9
|
+
const mockProperties = ['property1', 'property2', 'property3'];
|
|
10
|
+
const mockSecure = ['secure1', 'secure2', 'secure3'];
|
|
11
|
+
const mockValue = Buffer.from('mock value');
|
|
12
|
+
const mockDescriptors = [{}, {}, {}];
|
|
13
|
+
|
|
14
|
+
const mockOnReadRequest = function () {};
|
|
15
|
+
const mockOnWriteRequest = function () {};
|
|
16
|
+
const mockOnSubscribe = function () {};
|
|
17
|
+
const mockOnUnsubscribe = function () {};
|
|
18
|
+
const mockOnNotify = function () {};
|
|
19
|
+
const mockOnIndicate = function () {};
|
|
20
|
+
|
|
21
|
+
const mockMaxValueSize = 20;
|
|
22
|
+
const mockUpdateValueCallback = function () {};
|
|
23
|
+
|
|
24
|
+
it('should create with uuid option', function () {
|
|
25
|
+
const characteristic = new Characteristic({
|
|
26
|
+
uuid: mockUuid
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
characteristic.uuid.should.equal(mockUuid);
|
|
30
|
+
|
|
31
|
+
Array.isArray(characteristic.properties).should.equal(true);
|
|
32
|
+
characteristic.properties.length.should.equal(0);
|
|
33
|
+
|
|
34
|
+
Array.isArray(characteristic.secure).should.equal(true);
|
|
35
|
+
characteristic.secure.length.should.equal(0);
|
|
36
|
+
|
|
37
|
+
should(characteristic.value).equal(null);
|
|
38
|
+
|
|
39
|
+
Array.isArray(characteristic.descriptors).should.equal(true);
|
|
40
|
+
characteristic.descriptors.length.should.equal(0);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should create with properties option', function () {
|
|
44
|
+
const characteristic = new Characteristic({
|
|
45
|
+
properties: mockProperties
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
characteristic.properties.should.equal(mockProperties);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should create with secure option', function () {
|
|
52
|
+
const characteristic = new Characteristic({
|
|
53
|
+
secure: mockSecure
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
characteristic.secure.should.equal(mockSecure);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should create with value option', function () {
|
|
60
|
+
const characteristic = new Characteristic({
|
|
61
|
+
properties: ['read'],
|
|
62
|
+
value: mockValue
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
characteristic.value.should.equal(mockValue);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should not create with value option and non-read properties', function () {
|
|
69
|
+
(function () {
|
|
70
|
+
// eslint-disable-next-line no-unused-vars
|
|
71
|
+
const characteristic = new Characteristic({
|
|
72
|
+
properties: ['write'],
|
|
73
|
+
value: mockValue
|
|
74
|
+
});
|
|
75
|
+
}).should.throw();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should create with descriptors option', function () {
|
|
79
|
+
const characteristic = new Characteristic({
|
|
80
|
+
descriptors: mockDescriptors
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
characteristic.descriptors.should.equal(mockDescriptors);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should create with onReadRequest option', function () {
|
|
87
|
+
const characteristic = new Characteristic({
|
|
88
|
+
onReadRequest: mockOnReadRequest
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
characteristic.onReadRequest.should.equal(mockOnReadRequest);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should create with onWriteRequest option', function () {
|
|
95
|
+
const characteristic = new Characteristic({
|
|
96
|
+
onWriteRequest: mockOnWriteRequest
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
characteristic.onWriteRequest.should.equal(mockOnWriteRequest);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should create with onSubscribe option', function () {
|
|
103
|
+
const characteristic = new Characteristic({
|
|
104
|
+
onSubscribe: mockOnSubscribe
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
characteristic.onSubscribe.should.equal(mockOnSubscribe);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should create with onUnsubscribe option', function () {
|
|
111
|
+
const characteristic = new Characteristic({
|
|
112
|
+
onUnsubscribe: mockOnUnsubscribe
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
characteristic.onUnsubscribe.should.equal(mockOnUnsubscribe);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should create with onNotify option', function () {
|
|
119
|
+
const characteristic = new Characteristic({
|
|
120
|
+
onNotify: mockOnNotify
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
characteristic.onNotify.should.equal(mockOnNotify);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should create with onIndicate option', function () {
|
|
127
|
+
const characteristic = new Characteristic({
|
|
128
|
+
onIndicate: mockOnIndicate
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
characteristic.onIndicate.should.equal(mockOnIndicate);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should toString', function () {
|
|
135
|
+
const characteristic = new Characteristic({
|
|
136
|
+
uuid: mockUuid
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
characteristic.toString().should.equal('{"uuid":"mockuuid","properties":[],"secure":[],"value":null,"descriptors":[]}');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should handle read request', function (done) {
|
|
143
|
+
const characteristic = new Characteristic({});
|
|
144
|
+
|
|
145
|
+
characteristic.emit('readRequest', 0, function (result, data) {
|
|
146
|
+
result.should.equal(0x0e);
|
|
147
|
+
should(data).equal(null);
|
|
148
|
+
|
|
149
|
+
done();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should handle write request', function (done) {
|
|
154
|
+
const characteristic = new Characteristic({});
|
|
155
|
+
|
|
156
|
+
characteristic.emit('writeRequest', Buffer.alloc(0), 0, false, function (result) {
|
|
157
|
+
result.should.equal(0x0e);
|
|
158
|
+
|
|
159
|
+
done();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should handle unsubscribe', function () {
|
|
164
|
+
const characteristic = new Characteristic({});
|
|
165
|
+
|
|
166
|
+
characteristic.maxValueSize = mockMaxValueSize;
|
|
167
|
+
characteristic.updateValueCallback = mockUpdateValueCallback;
|
|
168
|
+
|
|
169
|
+
characteristic.emit('unsubscribe');
|
|
170
|
+
|
|
171
|
+
should(characteristic.maxValueSize).equal(null);
|
|
172
|
+
should(characteristic.updateValueCallback).equal(null);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* jshint mocha: true */
|
|
2
|
+
const Descriptor = require('../lib/descriptor');
|
|
3
|
+
|
|
4
|
+
describe('Descriptor', function () {
|
|
5
|
+
const mockUuid = 'mockuuid';
|
|
6
|
+
const mockValue = Buffer.from('mock value');
|
|
7
|
+
|
|
8
|
+
it('should create with uuid option', function () {
|
|
9
|
+
const descriptor = new Descriptor({
|
|
10
|
+
uuid: mockUuid
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
descriptor.uuid.should.equal(mockUuid);
|
|
14
|
+
|
|
15
|
+
Buffer.isBuffer(descriptor.value).should.equal(true);
|
|
16
|
+
descriptor.value.length.should.equal(0);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should create with value option', function () {
|
|
20
|
+
const descriptor = new Descriptor({
|
|
21
|
+
value: mockValue
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
descriptor.value.should.equal(mockValue);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('toString', function () {
|
|
28
|
+
it('should hex buffer value', function () {
|
|
29
|
+
const descriptor = new Descriptor({
|
|
30
|
+
uuid: mockUuid,
|
|
31
|
+
value: mockValue
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
descriptor.toString().should.equal('{"uuid":"mockuuid","value":"6d6f636b2076616c7565"}');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should leave non-buffer value alone', function () {
|
|
38
|
+
const descriptor = new Descriptor({
|
|
39
|
+
uuid: mockUuid,
|
|
40
|
+
value: 'mock value'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
descriptor.toString().should.equal('{"uuid":"mockuuid","value":"mock value"}');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
File without changes
|
package/with-bindings.js
ADDED