@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,286 @@
|
|
|
1
|
+
//
|
|
2
|
+
// napi_objc.mm
|
|
3
|
+
// bleno-mac-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Georg Vienna on 30.08.18.
|
|
6
|
+
//
|
|
7
|
+
#include "napi_objc.h"
|
|
8
|
+
|
|
9
|
+
NSString *napiToString(Napi::String string) {
|
|
10
|
+
std::string str = string.Utf8Value();
|
|
11
|
+
return [NSString stringWithUTF8String:str.c_str()];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
NSString* napiToUuidString(Napi::String string) {
|
|
15
|
+
std::string str = string.Utf8Value();
|
|
16
|
+
NSMutableString * uuid = [[NSMutableString alloc] initWithCString:str.c_str() encoding:NSASCIIStringEncoding];
|
|
17
|
+
if([uuid length] == 32) {
|
|
18
|
+
[uuid insertString: @"-" atIndex: 8];
|
|
19
|
+
[uuid insertString: @"-" atIndex: 13];
|
|
20
|
+
[uuid insertString: @"-" atIndex: 18];
|
|
21
|
+
[uuid insertString: @"-" atIndex: 23];
|
|
22
|
+
}
|
|
23
|
+
return [uuid uppercaseString];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
NSArray* napiToUuidArray(Napi::Array array) {
|
|
27
|
+
NSMutableArray* serviceUuids = [NSMutableArray arrayWithCapacity:array.Length()];
|
|
28
|
+
for(size_t i = 0; i < array.Length(); i++) {
|
|
29
|
+
Napi::Value val = array[i];
|
|
30
|
+
[serviceUuids addObject:napiToUuidString(val.As<Napi::String>())];
|
|
31
|
+
}
|
|
32
|
+
return serviceUuids;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
NSData* napiToData(Napi::Buffer<Byte> buffer) {
|
|
36
|
+
return [NSData dataWithBytes:buffer.Data() length:buffer.Length()];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
NSNumber* napiToNumber(Napi::Number number) {
|
|
40
|
+
return [NSNumber numberWithInt:number.Int64Value()];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
NSArray<CBMutableService *> *napiArrayToCBMutableServices(Napi::Array array) {
|
|
44
|
+
NSLog(@"napiArrayToCBMutableServices");
|
|
45
|
+
|
|
46
|
+
NSMutableArray *services = [NSMutableArray array];
|
|
47
|
+
|
|
48
|
+
for (size_t i = 0; i < array.Length(); i++) {
|
|
49
|
+
Napi::Value v = array[i];
|
|
50
|
+
Napi::Object obj = v.As<Napi::Object>();
|
|
51
|
+
|
|
52
|
+
[services addObject:napiToCBMutableService(obj)];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return [services copy];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
CBMutableService *napiToCBMutableService(Napi::Object obj) {
|
|
59
|
+
NSLog(@"napiToCBMutableService");
|
|
60
|
+
|
|
61
|
+
NSString *uuid = napiToUuidString(obj.Get("uuid").ToString());
|
|
62
|
+
|
|
63
|
+
NSLog(@"napiArrayToCBMutableService: uuid:%@", uuid);
|
|
64
|
+
|
|
65
|
+
CBMutableService *service = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:uuid]
|
|
66
|
+
primary:YES];
|
|
67
|
+
|
|
68
|
+
service.characteristics = napiArrayToCBMutableCharacteristics(obj.Get("characteristics").As<Napi::Array>());
|
|
69
|
+
|
|
70
|
+
return service;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
NSArray<CBMutableCharacteristic *> *napiArrayToCBMutableCharacteristics(Napi::Array array) {
|
|
76
|
+
NSLog(@"napiArrayToCBMutableCharacteristics");
|
|
77
|
+
|
|
78
|
+
NSMutableArray *characteristics = [NSMutableArray array];
|
|
79
|
+
|
|
80
|
+
for (size_t i = 0; i < array.Length(); i++) {
|
|
81
|
+
Napi::Value v = array[i];
|
|
82
|
+
Napi::Object obj = v.As<Napi::Object>();
|
|
83
|
+
|
|
84
|
+
[characteristics addObject:napiToCBMutableCharacteristic(obj)];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return [characteristics copy];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
CBMutableCharacteristic *napiToCBMutableCharacteristic(Napi::Object obj) {
|
|
91
|
+
NSLog(@"napiToCBMutableCharacteristic");
|
|
92
|
+
|
|
93
|
+
NSString *uuid = napiToUuidString(obj.Get("uuid").ToString());
|
|
94
|
+
NSLog(@"napiToCBMutableCharacteristic: cUUID:%@", uuid);
|
|
95
|
+
|
|
96
|
+
NSData *value = obj.Get("value").IsBuffer() ? napiToData(obj.Get("value").As<Napi::Buffer<Byte>>()) : nil;
|
|
97
|
+
NSLog(@"napiToCBMutableCharacteristic: value:%@", value);
|
|
98
|
+
|
|
99
|
+
auto properties = obj.Get("properties").As<Napi::Array>();
|
|
100
|
+
auto secure = obj.Get("secure").As<Napi::Array>();
|
|
101
|
+
|
|
102
|
+
auto descriptors = obj.Get("descriptors").As<Napi::Array>();
|
|
103
|
+
|
|
104
|
+
CBMutableCharacteristic *characteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:uuid]
|
|
105
|
+
properties:napiToCBCharacteristicProperties(properties, secure)
|
|
106
|
+
value:value
|
|
107
|
+
permissions:napiToCBAttributePermissions(properties, secure)];
|
|
108
|
+
|
|
109
|
+
characteristic.descriptors = napiArrayToCBDescriptors(descriptors);
|
|
110
|
+
|
|
111
|
+
return characteristic;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
CBCharacteristicProperties napiToCBCharacteristicProperties(Napi::Array properties, Napi::Array secure) {
|
|
115
|
+
NSLog(@"napiToCBCharacteristicProperties");
|
|
116
|
+
|
|
117
|
+
NSArray<NSString *> *p = napiToStringArray(properties);
|
|
118
|
+
NSArray<NSString *> *s = napiToStringArray(secure);
|
|
119
|
+
|
|
120
|
+
CBCharacteristicProperties ret = 0;
|
|
121
|
+
|
|
122
|
+
if ([p containsObject:@"read"]) {
|
|
123
|
+
ret |= CBCharacteristicPropertyRead;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if ([p containsObject:@"write"]) {
|
|
127
|
+
ret |= CBCharacteristicPropertyWrite;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if ([p containsObject:@"writeWithoutResponse"]) {
|
|
131
|
+
ret |= CBCharacteristicPropertyWriteWithoutResponse;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if ([p containsObject:@"notify"]) {
|
|
135
|
+
if ([s containsObject:@"notify"]) {
|
|
136
|
+
ret |= CBCharacteristicPropertyNotifyEncryptionRequired;
|
|
137
|
+
} else {
|
|
138
|
+
ret |= CBCharacteristicPropertyNotify;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if ([p containsObject:@"indicate"]) {
|
|
143
|
+
if ([s containsObject:@"indicate"]) {
|
|
144
|
+
ret |= CBCharacteristicPropertyIndicateEncryptionRequired;
|
|
145
|
+
} else {
|
|
146
|
+
ret |= CBCharacteristicPropertyIndicate;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return ret;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
CBAttributePermissions napiToCBAttributePermissions(Napi::Array properties, Napi::Array secure) {
|
|
154
|
+
NSLog(@"napiToCBAttributePermissions");
|
|
155
|
+
|
|
156
|
+
NSArray<NSString *> *p = napiToStringArray(properties);
|
|
157
|
+
NSArray<NSString *> *s = napiToStringArray(secure);
|
|
158
|
+
|
|
159
|
+
CBAttributePermissions ret = 0;
|
|
160
|
+
|
|
161
|
+
if ([p containsObject:@"read"]) {
|
|
162
|
+
if ([s containsObject:@"read"]) {
|
|
163
|
+
ret |= CBAttributePermissionsReadEncryptionRequired;
|
|
164
|
+
} else {
|
|
165
|
+
ret |= CBAttributePermissionsReadable;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if ([p containsObject:@"write"]) {
|
|
170
|
+
if ([s containsObject:@"write"]) {
|
|
171
|
+
ret |= CBAttributePermissionsWriteEncryptionRequired;
|
|
172
|
+
} else {
|
|
173
|
+
ret |= CBAttributePermissionsWriteable;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if ([p containsObject:@"writeWithoutResponse"]) {
|
|
178
|
+
if ([s containsObject:@"writeWithoutResponse"]) {
|
|
179
|
+
ret |= CBAttributePermissionsWriteEncryptionRequired;
|
|
180
|
+
} else {
|
|
181
|
+
ret |= CBAttributePermissionsWriteable;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return ret;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
NSArray<CBDescriptor *> *napiArrayToCBDescriptors(Napi::Array array) {
|
|
189
|
+
NSLog(@"napiArrayToCBDescriptors");
|
|
190
|
+
|
|
191
|
+
NSMutableArray *descriptors = [NSMutableArray array];
|
|
192
|
+
|
|
193
|
+
for (size_t i = 0; i < array.Length(); i++) {
|
|
194
|
+
Napi::Value v = array[i];
|
|
195
|
+
Napi::Object obj = v.As<Napi::Object>();
|
|
196
|
+
|
|
197
|
+
[descriptors addObject:napiToCBDescriptor(obj)];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return [descriptors copy];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
CBDescriptor *napiToCBDescriptor(Napi::Object obj) {
|
|
204
|
+
NSString *uuid = napiToUuidString(obj.Get("uuid").ToString());
|
|
205
|
+
NSString *value = napiToString(obj.Get("value").ToString());
|
|
206
|
+
|
|
207
|
+
NSLog(@"napiToCBDescriptor uuid:%@ value:%@", uuid, value);
|
|
208
|
+
|
|
209
|
+
return [[CBMutableDescriptor alloc] initWithType:[CBUUID UUIDWithString:uuid]
|
|
210
|
+
value:value];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
NSArray<NSString *> *napiToStringArray(Napi::Array array) {
|
|
214
|
+
NSMutableArray *ret = [NSMutableArray arrayWithCapacity:array.Length()];
|
|
215
|
+
|
|
216
|
+
for (size_t i = 0; i < array.Length(); i++) {
|
|
217
|
+
Napi::Value v = array[i];
|
|
218
|
+
Napi::String str = v.ToString();
|
|
219
|
+
|
|
220
|
+
[ret addObject:napiToString(str)];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return [ret copy];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
std::map<Napi::String, Napi::Object> napiArrayToUUIDEmitters(Napi::Array services) {
|
|
227
|
+
NSLog(@"napiArrayToUUIDEmitters");
|
|
228
|
+
|
|
229
|
+
std::map<Napi::String, Napi::Object> map;
|
|
230
|
+
|
|
231
|
+
for (size_t i = 0; i < services.Length(); i++) {
|
|
232
|
+
Napi::Value vS = services[i];
|
|
233
|
+
Napi::Object objS = vS.As<Napi::Object>();
|
|
234
|
+
|
|
235
|
+
Napi::String uuidS = objS.Get("uuid").ToString();
|
|
236
|
+
|
|
237
|
+
map[uuidS] = objS;
|
|
238
|
+
|
|
239
|
+
Napi::Array characteristics = objS.Get("characteristics").As<Napi::Array>();
|
|
240
|
+
for (size_t j = 0; j < characteristics.Length(); j++) {
|
|
241
|
+
Napi::Value vC = characteristics[j];
|
|
242
|
+
Napi::Object objC = vC.As<Napi::Object>();
|
|
243
|
+
|
|
244
|
+
Napi::String uuidC = objC.Get("uuid").ToString();
|
|
245
|
+
|
|
246
|
+
map[uuidC] = objC;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return map;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
NSArray* getUuidArray(const Napi::Value& value) {
|
|
254
|
+
if (value.IsArray()) {
|
|
255
|
+
return napiToUuidArray(value.As<Napi::Array>());
|
|
256
|
+
}
|
|
257
|
+
return nil;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
BOOL getBool(const Napi::Value& value, BOOL def) {
|
|
261
|
+
if (value.IsBoolean()) {
|
|
262
|
+
return value.As<Napi::Boolean>().Value();
|
|
263
|
+
}
|
|
264
|
+
return def;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
NSArray* napiToCBUuidArray(Napi::Array array) {
|
|
268
|
+
NSMutableArray* serviceUuids = [NSMutableArray arrayWithCapacity:array.Length()];
|
|
269
|
+
for(size_t i = 0; i < array.Length(); i++) {
|
|
270
|
+
Napi::Value val = array[i];
|
|
271
|
+
[serviceUuids addObject:napiToCBUuidString(val.As<Napi::String>())];
|
|
272
|
+
}
|
|
273
|
+
return serviceUuids;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
CBUUID* napiToCBUuidString(Napi::String string) {
|
|
277
|
+
NSString* uuidString = napiToUuidString(string);
|
|
278
|
+
return [CBUUID UUIDWithString:uuidString];
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
NSArray* getCBUuidArray(const Napi::Value& value) {
|
|
282
|
+
if (value.IsArray()) {
|
|
283
|
+
return napiToCBUuidArray(value.As<Napi::Array>());
|
|
284
|
+
}
|
|
285
|
+
return nil;
|
|
286
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <napi.h>
|
|
4
|
+
|
|
5
|
+
#include "ble_manager.h"
|
|
6
|
+
|
|
7
|
+
class BlenoMac : public Napi::ObjectWrap<BlenoMac>
|
|
8
|
+
{
|
|
9
|
+
public:
|
|
10
|
+
BlenoMac(const Napi::CallbackInfo&);
|
|
11
|
+
Napi::Value Init(const Napi::CallbackInfo&);
|
|
12
|
+
Napi::Value CleanUp(const Napi::CallbackInfo&);
|
|
13
|
+
Napi::Value Scan(const Napi::CallbackInfo&);
|
|
14
|
+
Napi::Value StopScan(const Napi::CallbackInfo&);
|
|
15
|
+
Napi::Value Connect(const Napi::CallbackInfo&);
|
|
16
|
+
Napi::Value Disconnect(const Napi::CallbackInfo&);
|
|
17
|
+
Napi::Value UpdateRSSI(const Napi::CallbackInfo&);
|
|
18
|
+
Napi::Value DiscoverServices(const Napi::CallbackInfo&);
|
|
19
|
+
Napi::Value DiscoverIncludedServices(const Napi::CallbackInfo& info);
|
|
20
|
+
Napi::Value DiscoverCharacteristics(const Napi::CallbackInfo& info);
|
|
21
|
+
Napi::Value Read(const Napi::CallbackInfo& info);
|
|
22
|
+
Napi::Value Write(const Napi::CallbackInfo& info);
|
|
23
|
+
Napi::Value Notify(const Napi::CallbackInfo& info);
|
|
24
|
+
Napi::Value DiscoverDescriptors(const Napi::CallbackInfo& info);
|
|
25
|
+
Napi::Value ReadValue(const Napi::CallbackInfo& info);
|
|
26
|
+
Napi::Value WriteValue(const Napi::CallbackInfo& info);
|
|
27
|
+
Napi::Value ReadHandle(const Napi::CallbackInfo& info);
|
|
28
|
+
Napi::Value WriteHandle(const Napi::CallbackInfo& info);
|
|
29
|
+
|
|
30
|
+
static Napi::Function GetClass(Napi::Env);
|
|
31
|
+
|
|
32
|
+
private:
|
|
33
|
+
BLEManager* manager;
|
|
34
|
+
};
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
//
|
|
2
|
+
// bleno_mac.mm
|
|
3
|
+
// bleno-mac-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Georg Vienna on 28.08.18.
|
|
6
|
+
//
|
|
7
|
+
#include "bleno_mac.h"
|
|
8
|
+
|
|
9
|
+
#include "napi_objc.h"
|
|
10
|
+
|
|
11
|
+
#define THROW(msg) \
|
|
12
|
+
Napi::TypeError::New(info.Env(), msg).ThrowAsJavaScriptException(); \
|
|
13
|
+
return Napi::Value();
|
|
14
|
+
|
|
15
|
+
#define ARG1(type1) \
|
|
16
|
+
if (!info[0].Is##type1()) { \
|
|
17
|
+
THROW("There should be one argument: (" #type1 ")") \
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#define ARG2(type1, type2) \
|
|
21
|
+
if (!info[0].Is##type1() || !info[1].Is##type2()) { \
|
|
22
|
+
THROW("There should be 2 arguments: (" #type1 ", " #type2 ")"); \
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#define ARG3(type1, type2, type3) \
|
|
26
|
+
if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3()) { \
|
|
27
|
+
THROW("There should be 3 arguments: (" #type1 ", " #type2 ", " #type3 ")"); \
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#define ARG4(type1, type2, type3, type4) \
|
|
31
|
+
if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4()) { \
|
|
32
|
+
THROW("There should be 4 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ")"); \
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#define ARG5(type1, type2, type3, type4, type5) \
|
|
36
|
+
if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4() || !info[4].Is##type5()) { \
|
|
37
|
+
THROW("There should be 5 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ", " #type5 ")"); \
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#define CHECK_MANAGER() \
|
|
41
|
+
if(!manager) { \
|
|
42
|
+
THROW("BLEManager has already been cleaned up"); \
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
BlenoMac::BlenoMac(const Napi::CallbackInfo& info) : ObjectWrap(info) {
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Napi::Value BlenoMac::Init(const Napi::CallbackInfo& info) {
|
|
49
|
+
Napi::Function emit = info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();
|
|
50
|
+
manager = [[BLEManager alloc] init];
|
|
51
|
+
manager->emit.Wrap(info.This(), emit);
|
|
52
|
+
return Napi::Value();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// startScanning(serviceUuids, allowDuplicates)
|
|
56
|
+
Napi::Value BlenoMac::Scan(const Napi::CallbackInfo& info) {
|
|
57
|
+
CHECK_MANAGER()
|
|
58
|
+
NSArray* array = getUuidArray(info[0]);
|
|
59
|
+
// default value NO
|
|
60
|
+
auto duplicates = getBool(info[1], NO);
|
|
61
|
+
[manager scan:array allowDuplicates:duplicates];
|
|
62
|
+
return Napi::Value();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// stopScanning()
|
|
66
|
+
Napi::Value BlenoMac::StopScan(const Napi::CallbackInfo& info) {
|
|
67
|
+
CHECK_MANAGER()
|
|
68
|
+
[manager stopScan];
|
|
69
|
+
return Napi::Value();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// connect(deviceUuid)
|
|
73
|
+
Napi::Value BlenoMac::Connect(const Napi::CallbackInfo& info) {
|
|
74
|
+
CHECK_MANAGER()
|
|
75
|
+
ARG1(String)
|
|
76
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
77
|
+
[manager connect:uuid];
|
|
78
|
+
return Napi::Value();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// disconnect(deviceUuid)
|
|
82
|
+
Napi::Value BlenoMac::Disconnect(const Napi::CallbackInfo& info) {
|
|
83
|
+
CHECK_MANAGER()
|
|
84
|
+
ARG1(String)
|
|
85
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
86
|
+
[manager disconnect:uuid];
|
|
87
|
+
return Napi::Value();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// updateRssi(deviceUuid)
|
|
91
|
+
Napi::Value BlenoMac::UpdateRSSI(const Napi::CallbackInfo& info) {
|
|
92
|
+
CHECK_MANAGER()
|
|
93
|
+
ARG1(String)
|
|
94
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
95
|
+
[manager updateRSSI:uuid];
|
|
96
|
+
return Napi::Value();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// discoverServices(deviceUuid, uuids)
|
|
100
|
+
Napi::Value BlenoMac::DiscoverServices(const Napi::CallbackInfo& info) {
|
|
101
|
+
CHECK_MANAGER()
|
|
102
|
+
ARG1(String)
|
|
103
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
104
|
+
NSArray* array = getUuidArray(info[1]);
|
|
105
|
+
[manager discoverServices:uuid serviceUuids:array];
|
|
106
|
+
return Napi::Value();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// discoverIncludedServices(deviceUuid, serviceUuid, serviceUuids)
|
|
110
|
+
Napi::Value BlenoMac::DiscoverIncludedServices(const Napi::CallbackInfo& info) {
|
|
111
|
+
CHECK_MANAGER()
|
|
112
|
+
ARG2(String, String)
|
|
113
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
114
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
115
|
+
NSArray* serviceUuids = getUuidArray(info[2]);
|
|
116
|
+
[manager discoverIncludedServices:uuid forService:service services:serviceUuids];
|
|
117
|
+
return Napi::Value();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// discoverCharacteristics(deviceUuid, serviceUuid, characteristicUuids)
|
|
121
|
+
Napi::Value BlenoMac::DiscoverCharacteristics(const Napi::CallbackInfo& info) {
|
|
122
|
+
CHECK_MANAGER()
|
|
123
|
+
ARG2(String, String)
|
|
124
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
125
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
126
|
+
NSArray* characteristics = getUuidArray(info[2]);
|
|
127
|
+
[manager discoverCharacteristics:uuid forService:service characteristics:characteristics];
|
|
128
|
+
return Napi::Value();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// read(deviceUuid, serviceUuid, characteristicUuid)
|
|
132
|
+
Napi::Value BlenoMac::Read(const Napi::CallbackInfo& info) {
|
|
133
|
+
CHECK_MANAGER()
|
|
134
|
+
ARG3(String, String, String)
|
|
135
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
136
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
137
|
+
auto characteristic = napiToUuidString(info[2].As<Napi::String>());
|
|
138
|
+
[manager read:uuid service:service characteristic:characteristic];
|
|
139
|
+
return Napi::Value();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// write(deviceUuid, serviceUuid, characteristicUuid, data, withoutResponse)
|
|
143
|
+
Napi::Value BlenoMac::Write(const Napi::CallbackInfo& info) {
|
|
144
|
+
CHECK_MANAGER()
|
|
145
|
+
ARG5(String, String, String, Buffer, Boolean)
|
|
146
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
147
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
148
|
+
auto characteristic = napiToUuidString(info[2].As<Napi::String>());
|
|
149
|
+
auto data = napiToData(info[3].As<Napi::Buffer<Byte>>());
|
|
150
|
+
auto withoutResponse = info[4].As<Napi::Boolean>().Value();
|
|
151
|
+
[manager write:uuid service:service characteristic:characteristic data:data withoutResponse:withoutResponse];
|
|
152
|
+
return Napi::Value();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// notify(deviceUuid, serviceUuid, characteristicUuid, notify)
|
|
156
|
+
Napi::Value BlenoMac::Notify(const Napi::CallbackInfo& info) {
|
|
157
|
+
CHECK_MANAGER()
|
|
158
|
+
ARG4(String, String, String, Boolean)
|
|
159
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
160
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
161
|
+
auto characteristic = napiToUuidString(info[2].As<Napi::String>());
|
|
162
|
+
auto on = info[3].As<Napi::Boolean>().Value();
|
|
163
|
+
[manager notify:uuid service:service characteristic:characteristic on:on];
|
|
164
|
+
return Napi::Value();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// discoverDescriptors(deviceUuid, serviceUuid, characteristicUuid)
|
|
168
|
+
Napi::Value BlenoMac::DiscoverDescriptors(const Napi::CallbackInfo& info) {
|
|
169
|
+
CHECK_MANAGER()
|
|
170
|
+
ARG3(String, String, String)
|
|
171
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
172
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
173
|
+
auto characteristic = napiToUuidString(info[2].As<Napi::String>());
|
|
174
|
+
[manager discoverDescriptors:uuid service:service characteristic:characteristic];
|
|
175
|
+
return Napi::Value();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// readValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid)
|
|
179
|
+
Napi::Value BlenoMac::ReadValue(const Napi::CallbackInfo& info) {
|
|
180
|
+
CHECK_MANAGER()
|
|
181
|
+
ARG4(String, String, String, String)
|
|
182
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
183
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
184
|
+
auto characteristic = napiToUuidString(info[2].As<Napi::String>());
|
|
185
|
+
auto descriptor = napiToUuidString(info[3].As<Napi::String>());
|
|
186
|
+
[manager readValue:uuid service:service characteristic:characteristic descriptor:descriptor];
|
|
187
|
+
return Napi::Value();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// writeValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data)
|
|
191
|
+
Napi::Value BlenoMac::WriteValue(const Napi::CallbackInfo& info) {
|
|
192
|
+
CHECK_MANAGER()
|
|
193
|
+
ARG5(String, String, String, String, Buffer)
|
|
194
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
195
|
+
auto service = napiToUuidString(info[1].As<Napi::String>());
|
|
196
|
+
auto characteristic = napiToUuidString(info[2].As<Napi::String>());
|
|
197
|
+
auto descriptor = napiToUuidString(info[3].As<Napi::String>());
|
|
198
|
+
auto data = napiToData(info[4].As<Napi::Buffer<Byte>>());
|
|
199
|
+
[manager writeValue:uuid service:service characteristic:characteristic descriptor:descriptor data: data];
|
|
200
|
+
return Napi::Value();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// readHandle(deviceUuid, handle)
|
|
204
|
+
Napi::Value BlenoMac::ReadHandle(const Napi::CallbackInfo& info) {
|
|
205
|
+
CHECK_MANAGER()
|
|
206
|
+
ARG2(String, Number)
|
|
207
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
208
|
+
auto handle = napiToNumber(info[1].As<Napi::Number>());
|
|
209
|
+
[manager readHandle:uuid handle:handle];
|
|
210
|
+
return Napi::Value();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// writeHandle(deviceUuid, handle, data, (unused)withoutResponse)
|
|
214
|
+
Napi::Value BlenoMac::WriteHandle(const Napi::CallbackInfo& info) {
|
|
215
|
+
CHECK_MANAGER()
|
|
216
|
+
ARG3(String, Number, Buffer)
|
|
217
|
+
auto uuid = napiToUuidString(info[0].As<Napi::String>());
|
|
218
|
+
auto handle = napiToNumber(info[1].As<Napi::Number>());
|
|
219
|
+
auto data = napiToData(info[2].As<Napi::Buffer<Byte>>());
|
|
220
|
+
[manager writeHandle:uuid handle:handle data: data];
|
|
221
|
+
return Napi::Value();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
Napi::Value BlenoMac::CleanUp(const Napi::CallbackInfo& info) {
|
|
225
|
+
CHECK_MANAGER()
|
|
226
|
+
CFRelease((__bridge CFTypeRef)manager);
|
|
227
|
+
manager = nil;
|
|
228
|
+
return Napi::Value();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
Napi::Function BlenoMac::GetClass(Napi::Env env) {
|
|
232
|
+
return DefineClass(env, "BlenoMac", {
|
|
233
|
+
BlenoMac::InstanceMethod("init", &BlenoMac::Init),
|
|
234
|
+
BlenoMac::InstanceMethod("startScanning", &BlenoMac::Scan),
|
|
235
|
+
BlenoMac::InstanceMethod("stopScanning", &BlenoMac::StopScan),
|
|
236
|
+
BlenoMac::InstanceMethod("connect", &BlenoMac::Connect),
|
|
237
|
+
BlenoMac::InstanceMethod("disconnect", &BlenoMac::Disconnect),
|
|
238
|
+
BlenoMac::InstanceMethod("updateRssi", &BlenoMac::UpdateRSSI),
|
|
239
|
+
BlenoMac::InstanceMethod("discoverServices", &BlenoMac::DiscoverServices),
|
|
240
|
+
BlenoMac::InstanceMethod("discoverIncludedServices", &BlenoMac::DiscoverIncludedServices),
|
|
241
|
+
BlenoMac::InstanceMethod("discoverCharacteristics", &BlenoMac::DiscoverCharacteristics),
|
|
242
|
+
BlenoMac::InstanceMethod("read", &BlenoMac::Read),
|
|
243
|
+
BlenoMac::InstanceMethod("write", &BlenoMac::Write),
|
|
244
|
+
BlenoMac::InstanceMethod("notify", &BlenoMac::Notify),
|
|
245
|
+
BlenoMac::InstanceMethod("discoverDescriptors", &BlenoMac::DiscoverDescriptors),
|
|
246
|
+
BlenoMac::InstanceMethod("readValue", &BlenoMac::ReadValue),
|
|
247
|
+
BlenoMac::InstanceMethod("writeValue", &BlenoMac::WriteValue),
|
|
248
|
+
BlenoMac::InstanceMethod("readHandle", &BlenoMac::ReadValue),
|
|
249
|
+
BlenoMac::InstanceMethod("writeHandle", &BlenoMac::WriteValue),
|
|
250
|
+
BlenoMac::InstanceMethod("cleanUp", &BlenoMac::CleanUp),
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
255
|
+
Napi::String name = Napi::String::New(env, "BlenoMac");
|
|
256
|
+
exports.Set(name, BlenoMac::GetClass(env));
|
|
257
|
+
return exports;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
NODE_API_MODULE(addon, Init)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <vector>
|
|
5
|
+
#import <Foundation/Foundation.h>
|
|
6
|
+
#import <CoreBluetooth/CoreBluetooth.h>
|
|
7
|
+
#include "peripheral.h"
|
|
8
|
+
|
|
9
|
+
#define IF(type, var, code) type var = code; if(var)
|
|
10
|
+
|
|
11
|
+
#if defined(MAC_OS_X_VERSION_10_13)
|
|
12
|
+
#pragma clang diagnostic push
|
|
13
|
+
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
|
14
|
+
std::string stateToString(CBManagerState state);
|
|
15
|
+
#pragma clang diagnostic pop
|
|
16
|
+
#else
|
|
17
|
+
std::string stateToString(CBCentralManagerState state);
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
std::string StringFromCBPeripheralState(CBManagerState state);
|
|
21
|
+
|
|
22
|
+
NSString* getNSUuid(CBPeripheral* peripheral);
|
|
23
|
+
std::string getUuid(CBPeripheral* peripheral);
|
|
24
|
+
std::string getAddress(std::string uuid, AddressType* addressType);
|
|
25
|
+
std::vector<std::string> getServices(NSArray<CBService*>* services);
|
|
26
|
+
std::vector<std::pair<std::string, std::vector<std::string>>> getCharacteristics(NSArray<CBCharacteristic*>* characteristics);
|
|
27
|
+
std::vector<std::string> getDescriptors(NSArray<CBDescriptor*>* descriptors);
|