@stoprocent/noble 1.19.0 → 2.0.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.
Files changed (97) hide show
  1. package/README.md +393 -650
  2. package/examples/advertisement-discovery.js +57 -48
  3. package/examples/connect-address.js +59 -34
  4. package/examples/echo.js +59 -69
  5. package/examples/enter-exit.js +55 -49
  6. package/examples/multiple-bindings.js +53 -0
  7. package/examples/peripheral-explorer-async.js +39 -21
  8. package/examples/peripheral-explorer.ts +52 -0
  9. package/index.d.ts +249 -209
  10. package/index.js +4 -1
  11. package/jest.config.js +4 -0
  12. package/lib/characteristic.js +153 -127
  13. package/lib/{win/src/callbacks.h → common/include/Emit.h} +17 -14
  14. package/lib/common/include/Peripheral.h +31 -0
  15. package/lib/common/include/ThreadSafeCallback.h +95 -0
  16. package/lib/{win/src/callbacks.cc → common/src/Emit.cc} +111 -68
  17. package/lib/descriptor.js +57 -54
  18. package/lib/hci-socket/acl-stream.js +2 -4
  19. package/lib/hci-socket/bindings.js +96 -73
  20. package/lib/hci-socket/gap.js +2 -3
  21. package/lib/hci-socket/gatt.js +2 -5
  22. package/lib/hci-socket/hci.js +19 -7
  23. package/lib/hci-socket/signaling.js +2 -3
  24. package/lib/hci-socket/smp.js +2 -3
  25. package/lib/hci-socket/vs.js +1 -0
  26. package/lib/mac/binding.gyp +5 -7
  27. package/lib/mac/bindings.js +1 -3
  28. package/lib/mac/src/ble_manager.h +1 -8
  29. package/lib/mac/src/ble_manager.mm +87 -44
  30. package/lib/mac/src/napi_objc.h +1 -0
  31. package/lib/mac/src/napi_objc.mm +0 -6
  32. package/lib/mac/src/noble_mac.h +5 -3
  33. package/lib/mac/src/noble_mac.mm +99 -57
  34. package/lib/mac/src/objc_cpp.h +3 -2
  35. package/lib/mac/src/objc_cpp.mm +0 -6
  36. package/lib/noble.js +579 -488
  37. package/lib/peripheral.js +171 -174
  38. package/lib/resolve-bindings.js +37 -30
  39. package/lib/service.js +58 -55
  40. package/lib/win/binding.gyp +4 -11
  41. package/lib/win/bindings.js +1 -3
  42. package/lib/win/src/ble_manager.cc +291 -166
  43. package/lib/win/src/ble_manager.h +11 -13
  44. package/lib/win/src/napi_winrt.cc +1 -7
  45. package/lib/win/src/napi_winrt.h +1 -1
  46. package/lib/win/src/noble_winrt.cc +88 -61
  47. package/lib/win/src/noble_winrt.h +5 -3
  48. package/lib/win/src/notify_map.cc +0 -7
  49. package/lib/win/src/notify_map.h +1 -8
  50. package/lib/win/src/peripheral_winrt.cc +29 -11
  51. package/lib/win/src/peripheral_winrt.h +1 -1
  52. package/lib/win/src/radio_watcher.cc +79 -69
  53. package/lib/win/src/radio_watcher.h +30 -11
  54. package/lib/win/src/winrt_cpp.cc +1 -1
  55. package/lib/win/src/winrt_cpp.h +3 -0
  56. package/package.json +14 -17
  57. package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
  58. package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
  59. package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
  60. package/test/lib/characteristic.test.js +202 -322
  61. package/test/lib/descriptor.test.js +62 -95
  62. package/test/lib/hci-socket/acl-stream.test.js +112 -108
  63. package/test/lib/hci-socket/bindings.test.js +576 -365
  64. package/test/lib/hci-socket/hci.test.js +442 -473
  65. package/test/lib/hci-socket/signaling.test.js +45 -48
  66. package/test/lib/hci-socket/smp.test.js +144 -142
  67. package/test/lib/hci-socket/vs.test.js +193 -18
  68. package/test/lib/peripheral.test.js +492 -322
  69. package/test/lib/resolve-bindings.test.js +207 -82
  70. package/test/lib/service.test.js +79 -88
  71. package/test/noble.test.js +381 -1085
  72. package/.editorconfig +0 -11
  73. package/.nycrc.json +0 -4
  74. package/codecov.yml +0 -5
  75. package/examples/cache-gatt-discovery.js +0 -198
  76. package/examples/cache-gatt-reconnect.js +0 -164
  77. package/examples/ext-advertisement-discovery.js +0 -65
  78. package/examples/peripheral-explorer.js +0 -225
  79. package/examples/pizza/central.js +0 -194
  80. package/examples/pizza/pizza.js +0 -60
  81. package/examples/test/test.custom.js +0 -131
  82. package/examples/uart-bind-params.js +0 -28
  83. package/lib/distributed/bindings.js +0 -326
  84. package/lib/mac/src/callbacks.cc +0 -222
  85. package/lib/mac/src/callbacks.h +0 -84
  86. package/lib/mac/src/peripheral.h +0 -23
  87. package/lib/resolve-bindings-web.js +0 -9
  88. package/lib/webbluetooth/bindings.js +0 -368
  89. package/lib/websocket/bindings.js +0 -321
  90. package/lib/win/src/peripheral.h +0 -23
  91. package/test/lib/distributed/bindings.test.js +0 -918
  92. package/test/lib/webbluetooth/bindings.test.js +0 -190
  93. package/test/lib/websocket/bindings.test.js +0 -456
  94. package/test/mocha.setup.js +0 -0
  95. package/with-bindings.js +0 -5
  96. package/with-custom-binding.js +0 -6
  97. package/ws-slave.js +0 -404
@@ -1,326 +0,0 @@
1
- const events = require('events');
2
- const util = require('util');
3
-
4
- const WebSocketServer = require('ws').Server;
5
-
6
- const NobleBindings = function () {
7
- this._wss = new WebSocketServer({
8
- port: 0xB1e
9
- });
10
-
11
- this._startScanCommand = null;
12
- this._peripherals = {};
13
-
14
- this._wss.on('connection', this._onConnection.bind(this));
15
- this.on('close', this._onClose.bind(this));
16
- this.on('message', this._onMessage.bind(this));
17
-
18
- process.nextTick(() => {
19
- this.emit('stateChange', 'poweredOff');
20
- });
21
- };
22
-
23
- util.inherits(NobleBindings, events.EventEmitter);
24
-
25
- NobleBindings.prototype.init = function () {
26
- // no-op
27
- };
28
-
29
- NobleBindings.prototype._onConnection = function (ws) {
30
- const _this = this;
31
-
32
- if (this._wss.clients.length === 1) {
33
- this.emit('stateChange', 'poweredOn');
34
- } else if (this._startScanCommand) {
35
- this._sendCommand(ws, this._startScanCommand);
36
- }
37
-
38
- ws.on('close', () => {
39
- _this.emit('close', ws);
40
- });
41
-
42
- ws.on('message', data => {
43
- _this.emit('message', ws, JSON.parse(data));
44
- });
45
- };
46
-
47
- NobleBindings.prototype._onClose = function (ws) {
48
- if (this._wss.clients.length === 0) {
49
- this.emit('stateChange', 'poweredOff');
50
- }
51
- };
52
-
53
- NobleBindings.prototype._onMessage = function (ws, event) {
54
- let {
55
- type,
56
- peripheralUuid,
57
- address,
58
- addressType,
59
- connectable,
60
- advertisement,
61
- rssi,
62
- serviceUuids,
63
- serviceUuid,
64
- includedServiceUuids,
65
- characteristics,
66
- characteristicUuid,
67
- isNotification,
68
- state,
69
- descriptors,
70
- descriptorUuid,
71
- handle
72
- } = event;
73
- const data = event.data ? Buffer.from(event.data, 'hex') : null;
74
-
75
- if (type === 'discover') {
76
- advertisement = {
77
- localName: advertisement.localName,
78
- txPowerLevel: advertisement.txPowerLevel,
79
- serviceUuids: advertisement.serviceUuids,
80
- manufacturerData: (advertisement.manufacturerData ? Buffer.from(advertisement.manufacturerData, 'hex') : null),
81
- serviceData: (advertisement.serviceData ? Buffer.from(advertisement.serviceData, 'hex') : null)
82
- };
83
-
84
- // TODO: handle duplicate peripheralUuid's
85
- this._peripherals[peripheralUuid] = {
86
- uuid: peripheralUuid,
87
- address,
88
- advertisement,
89
- rssi,
90
- ws
91
- };
92
-
93
- this.emit('discover', peripheralUuid, address, addressType, connectable, advertisement, rssi);
94
- } else if (type === 'connect') {
95
- this.emit('connect', peripheralUuid);
96
- } else if (type === 'disconnect') {
97
- this.emit('disconnect', peripheralUuid);
98
- } else if (type === 'rssiUpdate') {
99
- this.emit('rssiUpdate', peripheralUuid, rssi);
100
- } else if (type === 'servicesDiscover') {
101
- this.emit('servicesDiscover', peripheralUuid, serviceUuids);
102
- } else if (type === 'includedServicesDiscover') {
103
- this.emit('includedServicesDiscover', peripheralUuid, serviceUuid, includedServiceUuids);
104
- } else if (type === 'characteristicsDiscover') {
105
- this.emit('characteristicsDiscover', peripheralUuid, serviceUuid, characteristics);
106
- } else if (type === 'read') {
107
- this.emit('read', peripheralUuid, serviceUuid, characteristicUuid, data, isNotification);
108
- } else if (type === 'write') {
109
- this.emit('write', peripheralUuid, serviceUuid, characteristicUuid);
110
- } else if (type === 'broadcast') {
111
- this.emit('broadcast', peripheralUuid, serviceUuid, characteristicUuid, state);
112
- } else if (type === 'notify') {
113
- this.emit('notify', peripheralUuid, serviceUuid, characteristicUuid, state);
114
- } else if (type === 'descriptorsDiscover') {
115
- this.emit('descriptorsDiscover', peripheralUuid, serviceUuid, characteristicUuid, descriptors);
116
- } else if (type === 'valueRead') {
117
- this.emit('valueRead', peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid, data);
118
- } else if (type === 'valueWrite') {
119
- this.emit('valueWrite', peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid);
120
- } else if (type === 'handleRead') {
121
- this.emit('handleRead', peripheralUuid, handle, data);
122
- } else if (type === 'handleWrite') {
123
- this.emit('handleWrite', peripheralUuid, handle);
124
- } else if (type === 'handleNotify') {
125
- this.emit('handleNotify', peripheralUuid, handle, data);
126
- }
127
- };
128
-
129
- NobleBindings.prototype._sendCommand = function (ws, command) {
130
- const clients = ws ? [ws] : this._wss.clients;
131
-
132
- const message = JSON.stringify(command);
133
-
134
- for (let i = 0; i < clients.length; i++) {
135
- clients[i].send(message);
136
- }
137
- };
138
-
139
- NobleBindings.prototype.startScanning = function (serviceUuids, allowDuplicates) {
140
- this._startScanCommand = {
141
- action: 'startScanning',
142
- serviceUuids,
143
- allowDuplicates
144
- };
145
-
146
- this._sendCommand(null, this._startScanCommand);
147
-
148
- this.emit('scanStart');
149
- };
150
-
151
- NobleBindings.prototype.stopScanning = function () {
152
- this._startScanCommand = null;
153
-
154
- this._sendCommand(null, {
155
- action: 'stopScanning'
156
- });
157
-
158
- this.emit('scanStop');
159
- };
160
-
161
- NobleBindings.prototype.connect = function (deviceUuid) {
162
- const peripheral = this._peripherals[deviceUuid];
163
-
164
- this._sendCommand(peripheral.ws, {
165
- action: 'connect',
166
- peripheralUuid: peripheral.uuid
167
- });
168
- };
169
-
170
- NobleBindings.prototype.disconnect = function (deviceUuid) {
171
- const peripheral = this._peripherals[deviceUuid];
172
-
173
- this._sendCommand(peripheral.ws, {
174
- action: 'disconnect',
175
- peripheralUuid: peripheral.uuid
176
- });
177
- };
178
-
179
- NobleBindings.prototype.updateRssi = function (deviceUuid) {
180
- const peripheral = this._peripherals[deviceUuid];
181
-
182
- this._sendCommand(peripheral.ws, {
183
- action: 'updateRssi',
184
- peripheralUuid: peripheral.uuid
185
- });
186
- };
187
-
188
- NobleBindings.prototype.discoverServices = function (deviceUuid, uuids) {
189
- const peripheral = this._peripherals[deviceUuid];
190
-
191
- this._sendCommand(peripheral.ws, {
192
- action: 'discoverServices',
193
- peripheralUuid: peripheral.uuid,
194
- uuids
195
- });
196
- };
197
-
198
- NobleBindings.prototype.discoverIncludedServices = function (deviceUuid, serviceUuid, serviceUuids) {
199
- const peripheral = this._peripherals[deviceUuid];
200
-
201
- this._sendCommand(peripheral.ws, {
202
- action: 'discoverIncludedServices',
203
- peripheralUuid: peripheral.uuid,
204
- serviceUuid,
205
- serviceUuids
206
- });
207
- };
208
-
209
- NobleBindings.prototype.discoverCharacteristics = function (deviceUuid, serviceUuid, characteristicUuids) {
210
- const peripheral = this._peripherals[deviceUuid];
211
-
212
- this._sendCommand(peripheral.ws, {
213
- action: 'discoverCharacteristics',
214
- peripheralUuid: peripheral.uuid,
215
- serviceUuid,
216
- characteristicUuids
217
- });
218
- };
219
-
220
- NobleBindings.prototype.read = function (deviceUuid, serviceUuid, characteristicUuid) {
221
- const peripheral = this._peripherals[deviceUuid];
222
-
223
- this._sendCommand(peripheral.ws, {
224
- action: 'read',
225
- peripheralUuid: peripheral.uuid,
226
- serviceUuid,
227
- characteristicUuid
228
- });
229
- };
230
-
231
- NobleBindings.prototype.write = function (deviceUuid, serviceUuid, characteristicUuid, data, withoutResponse) {
232
- const peripheral = this._peripherals[deviceUuid];
233
-
234
- this._sendCommand(peripheral.ws, {
235
- action: 'write',
236
- peripheralUuid: peripheral.uuid,
237
- serviceUuid,
238
- characteristicUuid,
239
- data: data.toString('hex'),
240
- withoutResponse
241
- });
242
- };
243
-
244
- NobleBindings.prototype.broadcast = function (deviceUuid, serviceUuid, characteristicUuid, broadcast) {
245
- const peripheral = this._peripherals[deviceUuid];
246
-
247
- this._sendCommand(peripheral.ws, {
248
- action: 'broadcast',
249
- peripheralUuid: peripheral.uuid,
250
- serviceUuid,
251
- characteristicUuid,
252
- broadcast
253
- });
254
- };
255
-
256
- NobleBindings.prototype.notify = function (deviceUuid, serviceUuid, characteristicUuid, notify) {
257
- const peripheral = this._peripherals[deviceUuid];
258
-
259
- this._sendCommand(peripheral.ws, {
260
- action: 'notify',
261
- peripheralUuid: peripheral.uuid,
262
- serviceUuid,
263
- characteristicUuid,
264
- notify
265
- });
266
- };
267
-
268
- NobleBindings.prototype.discoverDescriptors = function (deviceUuid, serviceUuid, characteristicUuid) {
269
- const peripheral = this._peripherals[deviceUuid];
270
-
271
- this._sendCommand(peripheral.ws, {
272
- action: 'discoverDescriptors',
273
- peripheralUuid: peripheral.uuid,
274
- serviceUuid,
275
- characteristicUuid
276
- });
277
- };
278
-
279
- NobleBindings.prototype.readValue = function (deviceUuid, serviceUuid, characteristicUuid, descriptorUuid) {
280
- const peripheral = this._peripherals[deviceUuid];
281
-
282
- this._sendCommand(peripheral.ws, {
283
- action: 'readValue',
284
- peripheralUuid: peripheral.uuid,
285
- serviceUuid,
286
- characteristicUuid,
287
- descriptorUuid
288
- });
289
- };
290
-
291
- NobleBindings.prototype.writeValue = function (deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data) {
292
- const peripheral = this._peripherals[deviceUuid];
293
-
294
- this._sendCommand(peripheral.ws, {
295
- action: 'writeValue',
296
- peripheralUuid: peripheral.uuid,
297
- serviceUuid,
298
- characteristicUuid,
299
- descriptorUuid,
300
- data: data.toString('hex')
301
- });
302
- };
303
-
304
- NobleBindings.prototype.readHandle = function (deviceUuid, handle) {
305
- const peripheral = this._peripherals[deviceUuid];
306
-
307
- this._sendCommand(peripheral.ws, {
308
- action: 'readHandle',
309
- peripheralUuid: peripheral.uuid,
310
- handle
311
- });
312
- };
313
-
314
- NobleBindings.prototype.writeHandle = function (deviceUuid, handle, data, withoutResponse) {
315
- const peripheral = this._peripherals[deviceUuid];
316
-
317
- this._sendCommand(peripheral.ws, {
318
- action: 'readHandle',
319
- peripheralUuid: peripheral.uuid,
320
- handle,
321
- data: data.toString('hex'),
322
- withoutResponse
323
- });
324
- };
325
-
326
- module.exports = NobleBindings;
@@ -1,222 +0,0 @@
1
- //
2
- // callbacks.cc
3
- // noble-mac-native
4
- //
5
- // Created by Georg Vienna on 30.08.18.
6
- //
7
- #include "callbacks.h"
8
-
9
- #define _s(val) Napi::String::New(env, val)
10
- #define _b(val) Napi::Boolean::New(env, val)
11
- #define _n(val) Napi::Number::New(env, val)
12
- #define _u(str) toUuid(env, str)
13
-
14
- Napi::String toUuid(Napi::Env& env, const std::string& uuid) {
15
- std::string str(uuid);
16
- str.erase(std::remove(str.begin(), str.end(), '-'), str.end());
17
- std::transform(str.begin(), str.end(), str.begin(), ::tolower);
18
- return _s(str);
19
- }
20
-
21
- Napi::String toAddressType(Napi::Env& env, const AddressType& type) {
22
- if(type == PUBLIC) {
23
- return _s("public");
24
- } else if (type == RANDOM) {
25
- return _s("random");
26
- }
27
- return _s("unknown");
28
- }
29
-
30
- Napi::Buffer<uint8_t> toBuffer(Napi::Env& env, const Data& data) {
31
- if (data.empty()) {
32
- return Napi::Buffer<uint8_t>::New(env, 0);
33
- }
34
- return Napi::Buffer<uint8_t>::Copy(env, &data[0], data.size());
35
- }
36
-
37
- Napi::Array toUuidArray(Napi::Env& env, const std::vector<std::string>& data) {
38
- if (data.empty()) {
39
- return Napi::Array::New(env);
40
- }
41
- auto arr = Napi::Array::New(env, data.size());
42
- for (size_t i = 0; i < data.size(); i++) {
43
- arr.Set(i, _u(data[i]));
44
- }
45
- return arr;
46
- }
47
-
48
- Napi::Array toArray(Napi::Env& env, const std::vector<std::string>& data) {
49
- if (data.empty()) {
50
- return Napi::Array::New(env);
51
- }
52
- auto arr = Napi::Array::New(env, data.size());
53
- for (size_t i = 0; i < data.size(); i++) {
54
- arr.Set(i, _s(data[i]));
55
- }
56
- return arr;
57
- }
58
-
59
- void Emit::Wrap(const Napi::Value& receiver, const Napi::Function& callback) {
60
- mCallback = std::make_shared<ThreadSafeCallback>(receiver, callback);
61
- }
62
-
63
- void Emit::RadioState(const std::string& state) {
64
- mCallback->call([state](Napi::Env env, std::vector<napi_value>& args) {
65
- // emit('stateChange', state);
66
- args = { _s("stateChange"), _s(state) };
67
- });
68
- }
69
-
70
- void Emit::ScanState(bool start) {
71
- mCallback->call([start](Napi::Env env, std::vector<napi_value>& args) {
72
- // emit('scanStart') emit('scanStop')
73
- args = { _s(start ? "scanStart" : "scanStop") };
74
- });
75
- }
76
-
77
- void Emit::Scan(const std::string& uuid, int rssi, const Peripheral& peripheral) {
78
- auto address = peripheral.address;
79
- auto addressType = peripheral.addressType;
80
- auto connectable = peripheral.connectable;
81
- auto name = peripheral.name;
82
- auto txPowerLevel = peripheral.txPowerLevel;
83
- auto manufacturerData = peripheral.manufacturerData;
84
- auto serviceData = peripheral.serviceData;
85
- auto serviceUuids = peripheral.serviceUuids;
86
- mCallback->call([uuid, rssi, address, addressType, connectable, name, txPowerLevel, manufacturerData, serviceData, serviceUuids](Napi::Env env, std::vector<napi_value>& args) {
87
- Napi::Object advertisment = Napi::Object::New(env);
88
- if (std::get<1>(name)) {
89
- advertisment.Set(_s("localName"), _s(std::get<0>(name)));
90
- }
91
-
92
- if (std::get<1>(txPowerLevel)) {
93
- advertisment.Set(_s("txPowerLevel"), std::get<0>(txPowerLevel));
94
- }
95
-
96
- if (std::get<1>(manufacturerData)) {
97
- advertisment.Set(_s("manufacturerData"), toBuffer(env, std::get<0>(manufacturerData)));
98
- }
99
-
100
- if (std::get<1>(serviceData)) {
101
- auto array = std::get<0>(serviceData).empty() ? Napi::Array::New(env) : Napi::Array::New(env, std::get<0>(serviceData).size());
102
- for (size_t i = 0; i < std::get<0>(serviceData).size(); i++) {
103
- Napi::Object data = Napi::Object::New(env);
104
- data.Set(_s("uuid"), _u(std::get<0>(serviceData)[i].first));
105
- data.Set(_s("data"), toBuffer(env, std::get<0>(serviceData)[i].second));
106
- array.Set(i, data);
107
- }
108
- advertisment.Set(_s("serviceData"), array);
109
- }
110
-
111
- if (std::get<1>(serviceUuids)) {
112
- advertisment.Set(_s("serviceUuids"), toUuidArray(env, std::get<0>(serviceUuids)));
113
- }
114
- // emit('discover', deviceUuid, address, addressType, connectable, advertisement, rssi);
115
- args = { _s("discover"), _u(uuid), _s(address), toAddressType(env, addressType), _b(connectable), advertisment, _n(rssi) };
116
- });
117
- }
118
-
119
- void Emit::Connected(const std::string& uuid, const std::string& error) {
120
- mCallback->call([uuid, error](Napi::Env env, std::vector<napi_value>& args) {
121
- // emit('connect', deviceUuid) error added here
122
- args = { _s("connect"), _u(uuid), error.empty() ? env.Null() : _s(error) };
123
- });
124
- }
125
-
126
- void Emit::Disconnected(const std::string& uuid) {
127
- mCallback->call([uuid](Napi::Env env, std::vector<napi_value>& args) {
128
- // emit('disconnect', deviceUuid);
129
- args = { _s("disconnect"), _u(uuid) };
130
- });
131
- }
132
-
133
- void Emit::RSSI(const std::string & uuid, int rssi) {
134
- mCallback->call([uuid, rssi](Napi::Env env, std::vector<napi_value>& args) {
135
- // emit('rssiUpdate', deviceUuid, rssi);
136
- args = { _s("rssiUpdate"), _u(uuid), _n(rssi) };
137
- });
138
- }
139
-
140
- void Emit::ServicesDiscovered(const std::string & uuid, const std::vector<std::string>& serviceUuids) {
141
- mCallback->call([uuid, serviceUuids](Napi::Env env, std::vector<napi_value>& args) {
142
- // emit('servicesDiscover', deviceUuid, serviceUuids)
143
- args = { _s("servicesDiscover"), _u(uuid), toUuidArray(env, serviceUuids) };
144
- });
145
- }
146
-
147
- void Emit::IncludedServicesDiscovered(const std::string & uuid, const std::string & serviceUuid, const std::vector<std::string>& serviceUuids) {
148
- mCallback->call([uuid, serviceUuid, serviceUuids](Napi::Env env, std::vector<napi_value>& args) {
149
- // emit('includedServicesDiscover', deviceUuid, serviceUuid, includedServiceUuids)
150
- args = { _s("includedServicesDiscover"), _u(uuid), _u(serviceUuid), toUuidArray(env, serviceUuids) };
151
- });
152
- }
153
-
154
- void Emit::CharacteristicsDiscovered(const std::string & uuid, const std::string & serviceUuid, const std::vector<std::pair<std::string, std::vector<std::string>>>& characteristics) {
155
- mCallback->call([uuid, serviceUuid, characteristics](Napi::Env env, std::vector<napi_value>& args) {
156
- auto arr = characteristics.empty() ? Napi::Array::New(env) : Napi::Array::New(env, characteristics.size());
157
- for (size_t i = 0; i < characteristics.size(); i++) {
158
- Napi::Object characteristic = Napi::Object::New(env);
159
- characteristic.Set(_s("uuid"), _u(characteristics[i].first));
160
- characteristic.Set(_s("properties"), toArray(env, characteristics[i].second));
161
- arr.Set(i, characteristic);
162
- }
163
- // emit('characteristicsDiscover', deviceUuid, serviceUuid, { uuid, properties: ['broadcast', 'read', ...]})
164
- args = { _s("characteristicsDiscover"), _u(uuid), _u(serviceUuid), arr };
165
- });
166
- }
167
-
168
- void Emit::Read(const std::string & uuid, const std::string & serviceUuid, const std::string & characteristicUuid, const Data& data, bool isNotification) {
169
- mCallback->call([uuid, serviceUuid, characteristicUuid, data, isNotification](Napi::Env env, std::vector<napi_value>& args) {
170
- // emit('read', deviceUuid, serviceUuid, characteristicsUuid, data, isNotification);
171
- args = { _s("read"), _u(uuid), _u(serviceUuid), _u(characteristicUuid), toBuffer(env, data), _b(isNotification) };
172
- });
173
- }
174
-
175
- void Emit::Write(const std::string & uuid, const std::string & serviceUuid, const std::string & characteristicUuid) {
176
- mCallback->call([uuid, serviceUuid, characteristicUuid](Napi::Env env, std::vector<napi_value>& args) {
177
- // emit('write', deviceUuid, servicesUuid, characteristicsUuid)
178
- args = { _s("write"), _u(uuid), _u(serviceUuid), _u(characteristicUuid) };
179
- });
180
- }
181
-
182
- void Emit::Notify(const std::string & uuid, const std::string & serviceUuid, const std::string & characteristicUuid, bool state) {
183
- mCallback->call([uuid, serviceUuid, characteristicUuid, state](Napi::Env env, std::vector<napi_value>& args) {
184
- // emit('notify', deviceUuid, servicesUuid, characteristicsUuid, state)
185
- args = { _s("notify"), _u(uuid), _u(serviceUuid), _u(characteristicUuid), _b(state) };
186
- });
187
- }
188
-
189
- void Emit::DescriptorsDiscovered(const std::string & uuid, const std::string & serviceUuid, const std::string & characteristicUuid, const std::vector<std::string>& descriptorUuids) {
190
- mCallback->call([uuid, serviceUuid, characteristicUuid, descriptorUuids](Napi::Env env, std::vector<napi_value>& args) {
191
- // emit('descriptorsDiscover', deviceUuid, servicesUuid, characteristicsUuid, descriptors: [uuids])
192
- args = { _s("descriptorsDiscover"), _u(uuid), _u(serviceUuid), _u(characteristicUuid), toUuidArray(env, descriptorUuids) };
193
- });
194
- }
195
-
196
- void Emit::ReadValue(const std::string & uuid, const std::string & serviceUuid, const std::string & characteristicUuid, const std::string& descriptorUuid, const Data& data) {
197
- mCallback->call([uuid, serviceUuid, characteristicUuid, descriptorUuid, data](Napi::Env env, std::vector<napi_value>& args) {
198
- // emit('valueRead', deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data)
199
- args = { _s("valueRead"), _u(uuid), _u(serviceUuid), _u(characteristicUuid), _u(descriptorUuid), toBuffer(env, data) };
200
- });
201
- }
202
-
203
- void Emit::WriteValue(const std::string & uuid, const std::string & serviceUuid, const std::string & characteristicUuid, const std::string& descriptorUuid) {
204
- mCallback->call([uuid, serviceUuid, characteristicUuid, descriptorUuid](Napi::Env env, std::vector<napi_value>& args) {
205
- // emit('valueWrite', deviceUuid, serviceUuid, characteristicUuid, descriptorUuid);
206
- args = { _s("valueWrite"), _u(uuid), _u(serviceUuid), _u(characteristicUuid), _u(descriptorUuid) };
207
- });
208
- }
209
-
210
- void Emit::ReadHandle(const std::string & uuid, int descriptorHandle, const Data& data) {
211
- mCallback->call([uuid, descriptorHandle, data](Napi::Env env, std::vector<napi_value>& args) {
212
- // emit('handleRead', deviceUuid, descriptorHandle, data);
213
- args = { _s("handleRead"), _u(uuid), _n(descriptorHandle), toBuffer(env, data) };
214
- });
215
- }
216
-
217
- void Emit::WriteHandle(const std::string & uuid, int descriptorHandle) {
218
- mCallback->call([uuid, descriptorHandle](Napi::Env env, std::vector<napi_value>& args) {
219
- // emit('handleWrite', deviceUuid, descriptorHandle);
220
- args = { _s("handleWrite"), _u(uuid), _n(descriptorHandle) };
221
- });
222
- }
@@ -1,84 +0,0 @@
1
- #pragma once
2
-
3
- #include <napi.h>
4
- #include "peripheral.h"
5
-
6
- class ThreadSafeCallback {
7
- using arg_vector_t = std::vector<napi_value>;
8
- using arg_func_t = std::function<void(napi_env, arg_vector_t &)>;
9
-
10
- static void callJsCallback(Napi::Env env,
11
- Napi::Function jsCallback,
12
- Napi::Reference<Napi::Value> *context,
13
- arg_func_t *argfn) {
14
- if (argfn != nullptr) {
15
- arg_vector_t args;
16
-
17
- (*argfn)(env, args);
18
- delete argfn;
19
-
20
- if (env != nullptr && jsCallback != nullptr)
21
- jsCallback.Call(context->Value(), args);
22
- }
23
- };
24
- using tsfn_t = Napi::TypedThreadSafeFunction<
25
- Napi::Reference<Napi::Value>, arg_func_t, callJsCallback>;
26
-
27
- public:
28
- ThreadSafeCallback(const Napi::Value &receiver,
29
- const Napi::Function &jsCallback) {
30
- if (!(receiver.IsObject() || receiver.IsFunction()))
31
- throw Napi::Error::New(jsCallback.Env(),
32
- "Callback receiver must be an object or function");
33
- if (!jsCallback.IsFunction())
34
- throw Napi::Error::New(jsCallback.Env(), "Callback must be a function");
35
-
36
- receiver_ = Napi::Persistent(receiver);
37
- tsfn_ = tsfn_t::New(jsCallback.Env(),
38
- jsCallback,
39
- "ThreadSafeCallback callback",
40
- 0, 1, &receiver_);
41
- }
42
- ~ThreadSafeCallback() {
43
- // No further interaction with the thread safe function allowed.
44
- tsfn_.Abort();
45
- }
46
- void call(arg_func_t arg_function) {
47
- arg_func_t *argfn = new arg_func_t(arg_function);
48
- if (tsfn_.BlockingCall(argfn) != napi_ok)
49
- delete argfn;
50
- };
51
-
52
- protected:
53
- ThreadSafeCallback(const ThreadSafeCallback &) = delete;
54
- ThreadSafeCallback& operator=(const ThreadSafeCallback &) = delete;
55
- ThreadSafeCallback& operator=(ThreadSafeCallback &&) = delete;
56
-
57
- private:
58
- Napi::Reference<Napi::Value> receiver_;
59
- tsfn_t tsfn_;
60
- };
61
-
62
- class Emit {
63
- public:
64
- void Wrap(const Napi::Value& receiver, const Napi::Function& callback);
65
- void RadioState(const std::string& status);
66
- void ScanState(bool start);
67
- void Scan(const std::string& uuid, int rssi, const Peripheral& peripheral);
68
- void Connected(const std::string& uuid, const std::string& error = "");
69
- void Disconnected(const std::string& uuid);
70
- void RSSI(const std::string& uuid, int rssi);
71
- void ServicesDiscovered(const std::string& uuid, const std::vector<std::string>& serviceUuids);
72
- void IncludedServicesDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector<std::string>& serviceUuids);
73
- void CharacteristicsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector<std::pair<std::string, std::vector<std::string>>>& characteristics);
74
- void Read(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const Data& data, bool isNotification);
75
- void Write(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid);
76
- void Notify(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, bool state);
77
- void DescriptorsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::vector<std::string>& descriptorUuids);
78
- void ReadValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid, const Data& data);
79
- void WriteValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid);
80
- void ReadHandle(const std::string& uuid, int descriptorHandle, const std::vector<uint8_t>& data);
81
- void WriteHandle(const std::string& uuid, int descriptorHandle);
82
- protected:
83
- std::shared_ptr<ThreadSafeCallback> mCallback;
84
- };
@@ -1,23 +0,0 @@
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::pair<std::string, bool> name;
19
- std::pair<int, bool> txPowerLevel;
20
- std::pair<Data, bool> manufacturerData;
21
- std::pair<std::vector<std::pair<std::string, Data>>, bool> serviceData;
22
- std::pair<std::vector<std::string>, bool> serviceUuids;
23
- };
@@ -1,9 +0,0 @@
1
- function resolveBindings (options) {
2
- if (navigator.bluetooth && !process.env.NOBLE_WEBSOCKET) {
3
- return new (require('./webbluetooth/bindings'))(options);
4
- }
5
-
6
- return new (require('./websocket/bindings'))(options);
7
- }
8
-
9
- module.exports = resolveBindings;