@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,26 +1,20 @@
1
- //
2
- // ble_manager.h
3
- // noble-winrt-native
4
- //
5
- // Created by Georg Vienna on 03.09.18.
6
- //
7
-
8
1
  #pragma once
9
2
 
10
3
  #include <winrt/Windows.Devices.Bluetooth.Advertisement.h>
11
4
  #include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
12
5
 
13
- #include "callbacks.h"
6
+ #include "Emit.h"
7
+ #include "notify_map.h"
14
8
  #include "peripheral_winrt.h"
15
9
  #include "radio_watcher.h"
16
- #include "notify_map.h"
17
10
 
18
11
  using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
19
12
  using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
20
13
  using winrt::Windows::Foundation::AsyncStatus;
14
+ using winrt::Windows::Foundation::IAsyncOperation;
15
+ using winrt::Windows::Foundation::IInspectable;
21
16
 
22
- class BLEManager
23
- {
17
+ class BLEManager {
24
18
  public:
25
19
  // clang-format off
26
20
  BLEManager(const Napi::Value& receiver, const Napi::Function& callback);
@@ -28,6 +22,7 @@ public:
28
22
  void StopScan();
29
23
  bool Connect(const std::string& uuid);
30
24
  bool Disconnect(const std::string& uuid);
25
+ bool CancelConnect(const std::string& uuid);
31
26
  bool UpdateRSSI(const std::string& uuid);
32
27
  bool DiscoverServices(const std::string& uuid, const std::vector<winrt::guid>& serviceUUIDs);
33
28
  bool DiscoverIncludedServices(const std::string& uuid, const winrt::guid& serviceUuid, const std::vector<winrt::guid>& serviceUUIDs);
@@ -44,7 +39,7 @@ public:
44
39
 
45
40
  private:
46
41
  // clang-format off
47
- void OnRadio(Radio& radio);
42
+ void OnRadio(Radio& radio, const AdapterCapabilities& capabilities);
48
43
  void OnScanResult(BluetoothLEAdvertisementWatcher watcher, const BluetoothLEAdvertisementReceivedEventArgs& args);
49
44
  void OnScanStopped(BluetoothLEAdvertisementWatcher watcher, const BluetoothLEAdvertisementWatcherStoppedEventArgs& args);
50
45
  void OnConnected(IAsyncOperation<BluetoothLEDevice> asyncOp, AsyncStatus status, std::string uuid);
@@ -62,16 +57,19 @@ private:
62
57
  void OnReadHandle(IAsyncOperation<GattReadResult> asyncOp, AsyncStatus status, std::string uuid, int handle);
63
58
  void OnWriteHandle(IAsyncOperation<GattWriteResult> asyncOp, AsyncStatus status, std::string uuid, int handle);
64
59
  // clang-format on
60
+
61
+ bool mAllowDuplicates;
65
62
 
66
63
  Emit mEmit;
67
64
  RadioWatcher mWatcher;
68
65
  AdapterState mRadioState;
69
66
  BluetoothLEAdvertisementWatcher mAdvertismentWatcher;
67
+
70
68
  winrt::event_revoker<IBluetoothLEAdvertisementWatcher> mReceivedRevoker;
71
69
  winrt::event_revoker<IBluetoothLEAdvertisementWatcher> mStoppedRevoker;
72
- bool mAllowDuplicates;
73
70
 
74
71
  std::unordered_map<std::string, PeripheralWinrt> mDeviceMap;
72
+ std::vector<winrt::guid> mScanServiceUUIDs;
75
73
  std::set<std::string> mAdvertismentMap;
76
74
  NotifyMap mNotifyMap;
77
75
  };
@@ -1,9 +1,3 @@
1
- //
2
- // napi_objc.mm
3
- // noble-mac-native
4
- //
5
- // Created by Georg Vienna on 30.08.18.
6
- //
7
1
  #include "napi_winrt.h"
8
2
 
9
3
  #include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
@@ -21,7 +15,7 @@ winrt::guid napiToUuid(Napi::String string)
21
15
  str.insert(18, "-");
22
16
  str.insert(23, "-");
23
17
  }
24
- if (str.size() == 4)
18
+ if (str.size() == 4 || str.size() == 8)
25
19
  {
26
20
  int id = std::stoi(str, 0, 16);
27
21
  return BluetoothUuidHelper::FromShortId(id);
@@ -2,7 +2,7 @@
2
2
 
3
3
  #include <napi.h>
4
4
  #include "winrt/base.h"
5
- #include "peripheral.h"
5
+ #include "Peripheral.h"
6
6
 
7
7
  std::vector<winrt::guid> getUuidArray(const Napi::Value& value);
8
8
  bool getBool(const Napi::Value& value, bool def);
@@ -1,12 +1,6 @@
1
- //
2
- // noble_winrt.cc
3
- // noble-winrt-native
4
- //
5
- // Created by Georg Vienna on 03.09.18.
6
- //
7
1
  #include "noble_winrt.h"
8
-
9
2
  #include "napi_winrt.h"
3
+ #include "winrt_cpp.h"
10
4
 
11
5
  #define THROW(msg) \
12
6
  Napi::TypeError::New(info.Env(), msg).ThrowAsJavaScriptException(); \
@@ -48,18 +42,26 @@
48
42
  #define CHECK_MANAGER() \
49
43
  if (!manager) \
50
44
  { \
51
- THROW("BLEManager has already been cleaned up"); \
45
+ THROW(__FUNCTION__ ": BLEManager has already been cleaned up"); \
52
46
  }
53
47
 
54
48
  NobleWinrt::NobleWinrt(const Napi::CallbackInfo& info) : ObjectWrap(info)
55
49
  {
56
50
  }
57
51
 
58
- Napi::Value NobleWinrt::Init(const Napi::CallbackInfo& info)
52
+ Napi::Value NobleWinrt::Start(const Napi::CallbackInfo& info)
59
53
  {
60
54
  Napi::Function emit = info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();
61
55
  manager = new BLEManager(info.This(), emit);
62
- return Napi::Value();
56
+ return info.Env().Undefined();
57
+ }
58
+
59
+ Napi::Value NobleWinrt::Stop(const Napi::CallbackInfo& info)
60
+ {
61
+ CHECK_MANAGER()
62
+ delete manager;
63
+ manager = nullptr;
64
+ return info.Env().Undefined();
63
65
  }
64
66
 
65
67
  // startScanning(serviceUuids, allowDuplicates)
@@ -70,7 +72,7 @@ Napi::Value NobleWinrt::Scan(const Napi::CallbackInfo& info)
70
72
  // default value false
71
73
  auto duplicates = getBool(info[1], false);
72
74
  manager->Scan(vector, duplicates);
73
- return Napi::Value();
75
+ return info.Env().Undefined();
74
76
  }
75
77
 
76
78
  // stopScanning()
@@ -78,7 +80,7 @@ Napi::Value NobleWinrt::StopScan(const Napi::CallbackInfo& info)
78
80
  {
79
81
  CHECK_MANAGER()
80
82
  manager->StopScan();
81
- return Napi::Value();
83
+ return info.Env().Undefined();
82
84
  }
83
85
 
84
86
  // connect(deviceUuid)
@@ -88,7 +90,7 @@ Napi::Value NobleWinrt::Connect(const Napi::CallbackInfo& info)
88
90
  ARG1(String)
89
91
  auto uuid = info[0].As<Napi::String>().Utf8Value();
90
92
  manager->Connect(uuid);
91
- return Napi::Value();
93
+ return info.Env().Undefined();
92
94
  }
93
95
 
94
96
  // disconnect(deviceUuid)
@@ -98,7 +100,17 @@ Napi::Value NobleWinrt::Disconnect(const Napi::CallbackInfo& info)
98
100
  ARG1(String)
99
101
  auto uuid = info[0].As<Napi::String>().Utf8Value();
100
102
  manager->Disconnect(uuid);
101
- return Napi::Value();
103
+ return info.Env().Undefined();
104
+ }
105
+
106
+ // cancelConnect(deviceUuid)
107
+ Napi::Value NobleWinrt::CancelConnect(const Napi::CallbackInfo& info)
108
+ {
109
+ CHECK_MANAGER()
110
+ ARG1(String)
111
+ auto uuid = info[0].As<Napi::String>().Utf8Value();
112
+ manager->CancelConnect(uuid);
113
+ return info.Env().Undefined();
102
114
  }
103
115
 
104
116
  // updateRssi(deviceUuid)
@@ -108,7 +120,7 @@ Napi::Value NobleWinrt::UpdateRSSI(const Napi::CallbackInfo& info)
108
120
  ARG1(String)
109
121
  auto uuid = info[0].As<Napi::String>().Utf8Value();
110
122
  manager->UpdateRSSI(uuid);
111
- return Napi::Value();
123
+ return info.Env().Undefined();
112
124
  }
113
125
 
114
126
  // discoverServices(deviceUuid, uuids)
@@ -119,7 +131,7 @@ Napi::Value NobleWinrt::DiscoverServices(const Napi::CallbackInfo& info)
119
131
  auto uuid = info[0].As<Napi::String>().Utf8Value();
120
132
  std::vector<winrt::guid> uuids = getUuidArray(info[1]);
121
133
  manager->DiscoverServices(uuid, uuids);
122
- return Napi::Value();
134
+ return info.Env().Undefined();
123
135
  }
124
136
 
125
137
  // discoverIncludedServices(deviceUuid, serviceUuid, serviceUuids)
@@ -131,7 +143,7 @@ Napi::Value NobleWinrt::DiscoverIncludedServices(const Napi::CallbackInfo& info)
131
143
  auto service = napiToUuid(info[1].As<Napi::String>());
132
144
  std::vector<winrt::guid> uuids = getUuidArray(info[2]);
133
145
  manager->DiscoverIncludedServices(uuid, service, uuids);
134
- return Napi::Value();
146
+ return info.Env().Undefined();
135
147
  }
136
148
 
137
149
  // discoverCharacteristics(deviceUuid, serviceUuid, characteristicUuids)
@@ -143,7 +155,7 @@ Napi::Value NobleWinrt::DiscoverCharacteristics(const Napi::CallbackInfo& info)
143
155
  auto service = napiToUuid(info[1].As<Napi::String>());
144
156
  std::vector<winrt::guid> characteristics = getUuidArray(info[2]);
145
157
  manager->DiscoverCharacteristics(uuid, service, characteristics);
146
- return Napi::Value();
158
+ return info.Env().Undefined();
147
159
  }
148
160
 
149
161
  // read(deviceUuid, serviceUuid, characteristicUuid)
@@ -155,7 +167,7 @@ Napi::Value NobleWinrt::Read(const Napi::CallbackInfo& info)
155
167
  auto service = napiToUuid(info[1].As<Napi::String>());
156
168
  auto characteristic = napiToUuid(info[2].As<Napi::String>());
157
169
  manager->Read(uuid, service, characteristic);
158
- return Napi::Value();
170
+ return info.Env().Undefined();
159
171
  }
160
172
 
161
173
  // write(deviceUuid, serviceUuid, characteristicUuid, data, withoutResponse)
@@ -169,7 +181,7 @@ Napi::Value NobleWinrt::Write(const Napi::CallbackInfo& info)
169
181
  auto data = napiToData(info[3].As<Napi::Buffer<unsigned char>>());
170
182
  auto withoutResponse = info[4].As<Napi::Boolean>().Value();
171
183
  manager->Write(uuid, service, characteristic, data, withoutResponse);
172
- return Napi::Value();
184
+ return info.Env().Undefined();
173
185
  }
174
186
 
175
187
  // notify(deviceUuid, serviceUuid, characteristicUuid, notify)
@@ -182,7 +194,7 @@ Napi::Value NobleWinrt::Notify(const Napi::CallbackInfo& info)
182
194
  auto characteristic = napiToUuid(info[2].As<Napi::String>());
183
195
  auto on = info[3].As<Napi::Boolean>().Value();
184
196
  manager->Notify(uuid, service, characteristic, on);
185
- return Napi::Value();
197
+ return info.Env().Undefined();
186
198
  }
187
199
 
188
200
  // discoverDescriptors(deviceUuid, serviceUuid, characteristicUuid)
@@ -194,7 +206,7 @@ Napi::Value NobleWinrt::DiscoverDescriptors(const Napi::CallbackInfo& info)
194
206
  auto service = napiToUuid(info[1].As<Napi::String>());
195
207
  auto characteristic = napiToUuid(info[2].As<Napi::String>());
196
208
  manager->DiscoverDescriptors(uuid, service, characteristic);
197
- return Napi::Value();
209
+ return info.Env().Undefined();
198
210
  }
199
211
 
200
212
  // readValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid)
@@ -207,7 +219,7 @@ Napi::Value NobleWinrt::ReadValue(const Napi::CallbackInfo& info)
207
219
  auto characteristic = napiToUuid(info[2].As<Napi::String>());
208
220
  auto descriptor = napiToUuid(info[3].As<Napi::String>());
209
221
  manager->ReadValue(uuid, service, characteristic, descriptor);
210
- return Napi::Value();
222
+ return info.Env().Undefined();
211
223
  }
212
224
 
213
225
  // writeValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data)
@@ -221,7 +233,7 @@ Napi::Value NobleWinrt::WriteValue(const Napi::CallbackInfo& info)
221
233
  auto descriptor = napiToUuid(info[3].As<Napi::String>());
222
234
  auto data = napiToData(info[4].As<Napi::Buffer<unsigned char>>());
223
235
  manager->WriteValue(uuid, service, characteristic, descriptor, data);
224
- return Napi::Value();
236
+ return info.Env().Undefined();
225
237
  }
226
238
 
227
239
  // readHandle(deviceUuid, handle)
@@ -232,7 +244,7 @@ Napi::Value NobleWinrt::ReadHandle(const Napi::CallbackInfo& info)
232
244
  auto uuid = info[0].As<Napi::String>().Utf8Value();
233
245
  auto handle = napiToNumber(info[1].As<Napi::Number>());
234
246
  manager->ReadHandle(uuid, handle);
235
- return Napi::Value();
247
+ return info.Env().Undefined();
236
248
  }
237
249
 
238
250
  // writeHandle(deviceUuid, handle, data, (unused)withoutResponse)
@@ -244,26 +256,59 @@ Napi::Value NobleWinrt::WriteHandle(const Napi::CallbackInfo& info)
244
256
  auto handle = napiToNumber(info[1].As<Napi::Number>());
245
257
  auto data = napiToData(info[2].As<Napi::Buffer<unsigned char>>());
246
258
  manager->WriteHandle(uuid, handle, data);
247
- return Napi::Value();
259
+ return info.Env().Undefined();
248
260
  }
249
261
 
250
- Napi::Value NobleWinrt::CleanUp(const Napi::CallbackInfo& info)
262
+ // addressToId(address)
263
+ Napi::Value NobleWinrt::AddressToId(const Napi::CallbackInfo& info)
251
264
  {
252
- CHECK_MANAGER()
253
- delete manager;
254
- manager = nullptr;
255
- return Napi::Value();
265
+ ARG1(String)
266
+ try {
267
+ auto address = info[0].As<Napi::String>().Utf8Value();
268
+ std::string cleanUuid = address;
269
+ cleanUuid.erase(std::remove(cleanUuid.begin(), cleanUuid.end(), ':'), cleanUuid.end());
270
+
271
+ if (cleanUuid.length() != 12) {
272
+ return info.Env().Null();
273
+ }
274
+
275
+ if (cleanUuid.find_first_not_of("0123456789ABCDEFabcdef") != std::string::npos) {
276
+ return info.Env().Null();
277
+ }
278
+
279
+ return Napi::String::New(info.Env(), cleanUuid.c_str());
280
+ } catch (const std::exception& e) {
281
+ return info.Env().Null();
282
+ }
256
283
  }
257
284
 
258
- Napi::Function NobleWinrt::GetClass(Napi::Env env)
259
- {
260
- // clang-format off
261
- return DefineClass(env, "NobleWinrt", {
262
- NobleWinrt::InstanceMethod("init", &NobleWinrt::Init),
285
+ #pragma comment(lib, "windowsapp")
286
+ Napi::Object NobleWinrt::Init(Napi::Env env, Napi::Object exports) {
287
+ Napi::HandleScope scope(env);
288
+
289
+ try
290
+ {
291
+ winrt::init_apartment();
292
+ }
293
+ catch (winrt::hresult_error hresult)
294
+ {
295
+ if (hresult.code() != RPC_E_CHANGED_MODE)
296
+ {
297
+ wprintf(L"Failed initializing apartment: %d %s", hresult.code().value,
298
+ hresult.message().c_str());
299
+ Napi::TypeError::New(env, "Failed initializing apartment").ThrowAsJavaScriptException();
300
+ return exports;
301
+ }
302
+ }
303
+
304
+ Napi::Function func = DefineClass(env, "NobleWinrt", {
305
+ NobleWinrt::InstanceMethod("start", &NobleWinrt::Start),
306
+ NobleWinrt::InstanceMethod("stop", &NobleWinrt::Stop),
263
307
  NobleWinrt::InstanceMethod("startScanning", &NobleWinrt::Scan),
264
308
  NobleWinrt::InstanceMethod("stopScanning", &NobleWinrt::StopScan),
265
309
  NobleWinrt::InstanceMethod("connect", &NobleWinrt::Connect),
266
310
  NobleWinrt::InstanceMethod("disconnect", &NobleWinrt::Disconnect),
311
+ NobleWinrt::InstanceMethod("cancelConnect", &NobleWinrt::CancelConnect),
267
312
  NobleWinrt::InstanceMethod("updateRssi", &NobleWinrt::UpdateRSSI),
268
313
  NobleWinrt::InstanceMethod("discoverServices", &NobleWinrt::DiscoverServices),
269
314
  NobleWinrt::InstanceMethod("discoverIncludedServices", &NobleWinrt::DiscoverIncludedServices),
@@ -276,33 +321,15 @@ Napi::Function NobleWinrt::GetClass(Napi::Env env)
276
321
  NobleWinrt::InstanceMethod("writeValue", &NobleWinrt::WriteValue),
277
322
  NobleWinrt::InstanceMethod("readHandle", &NobleWinrt::ReadHandle),
278
323
  NobleWinrt::InstanceMethod("writeHandle", &NobleWinrt::WriteHandle),
279
- NobleWinrt::InstanceMethod("cleanUp", &NobleWinrt::CleanUp),
280
- });
281
- // clang-format on
282
- }
324
+ NobleWinrt::InstanceMethod("addressToId", &NobleWinrt::AddressToId),
325
+ });
283
326
 
284
- #pragma comment(lib, "windowsapp")
327
+ Napi::FunctionReference* constructor = new Napi::FunctionReference();
328
+ *constructor = Napi::Persistent(func);
329
+ env.SetInstanceData(constructor);
285
330
 
286
- Napi::Object Init(Napi::Env env, Napi::Object exports)
287
- {
288
- try
289
- {
290
- winrt::init_apartment();
291
- }
292
- catch (winrt::hresult_error hresult)
293
- {
294
- // electron already initialized the COM library
295
- if (hresult.code() != RPC_E_CHANGED_MODE)
296
- {
297
- wprintf(L"Failed initializing apartment: %d %s", hresult.code().value,
298
- hresult.message().c_str());
299
- Napi::TypeError::New(env, "Failed initializing apartment").ThrowAsJavaScriptException();
300
- return exports;
301
- }
302
- }
303
- Napi::String name = Napi::String::New(env, "NobleWinrt");
304
- exports.Set(name, NobleWinrt::GetClass(env));
331
+ exports.Set("NobleWinrt", func);
305
332
  return exports;
306
333
  }
307
334
 
308
- NODE_API_MODULE(addon, Init)
335
+ NODE_API_NAMED_ADDON(addon, NobleWinrt);
@@ -8,12 +8,13 @@ class NobleWinrt : public Napi::ObjectWrap<NobleWinrt>
8
8
  {
9
9
  public:
10
10
  NobleWinrt(const Napi::CallbackInfo&);
11
- Napi::Value Init(const Napi::CallbackInfo&);
12
- Napi::Value CleanUp(const Napi::CallbackInfo&);
11
+ Napi::Value Start(const Napi::CallbackInfo&);
12
+ Napi::Value Stop(const Napi::CallbackInfo&);
13
13
  Napi::Value Scan(const Napi::CallbackInfo&);
14
14
  Napi::Value StopScan(const Napi::CallbackInfo&);
15
15
  Napi::Value Connect(const Napi::CallbackInfo&);
16
16
  Napi::Value Disconnect(const Napi::CallbackInfo&);
17
+ Napi::Value CancelConnect(const Napi::CallbackInfo&);
17
18
  Napi::Value UpdateRSSI(const Napi::CallbackInfo&);
18
19
  Napi::Value DiscoverServices(const Napi::CallbackInfo&);
19
20
  Napi::Value DiscoverIncludedServices(const Napi::CallbackInfo& info);
@@ -26,8 +27,9 @@ public:
26
27
  Napi::Value WriteValue(const Napi::CallbackInfo& info);
27
28
  Napi::Value ReadHandle(const Napi::CallbackInfo& info);
28
29
  Napi::Value WriteHandle(const Napi::CallbackInfo& info);
30
+ Napi::Value AddressToId(const Napi::CallbackInfo& info);
29
31
 
30
- static Napi::Function GetClass(Napi::Env);
32
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
31
33
 
32
34
  private:
33
35
  BLEManager* manager;
@@ -1,10 +1,3 @@
1
- //
2
- // notify_map.cc
3
- // noble-winrt-native
4
- //
5
- // Created by Georg Vienna on 07.09.18.
6
- //
7
-
8
1
  #include "notify_map.h"
9
2
 
10
3
  bool Key::operator==(const Key& other) const
@@ -1,14 +1,7 @@
1
- //
2
- // notify_map.h
3
- // noble-winrt-native
4
- //
5
- // Created by Georg Vienna on 07.09.18.
6
- //
7
-
8
1
  #pragma once
9
2
 
10
- #include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
11
3
  #include "winrt_guid.h"
4
+ #include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
12
5
 
13
6
  using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
14
7
 
@@ -70,9 +70,14 @@ void PeripheralWinrt::ProcessServiceData(const BluetoothLEAdvertisementDataSecti
70
70
  data.resize(d.Length() - uuidSize);
71
71
  dr.ReadBytes(data);
72
72
 
73
+ // Initialize serviceData if it doesn't exist
74
+ if (!serviceData.has_value()) {
75
+ serviceData = std::vector<std::pair<std::string, Data>>();
76
+ }
77
+
73
78
  // Find and update existing entry or add new one
74
79
  bool found = false;
75
- for (auto& pair : serviceData) {
80
+ for (auto& pair : serviceData.value()) {
76
81
  if (pair.first == uuidStr) {
77
82
  pair.second = data;
78
83
  found = true;
@@ -81,7 +86,7 @@ void PeripheralWinrt::ProcessServiceData(const BluetoothLEAdvertisementDataSecti
81
86
  }
82
87
 
83
88
  if (!found) {
84
- serviceData.push_back(std::make_pair(uuidStr, data));
89
+ serviceData.value().push_back(std::make_pair(uuidStr, data));
85
90
  }
86
91
 
87
92
  dr.Close();
@@ -90,16 +95,20 @@ void PeripheralWinrt::ProcessServiceData(const BluetoothLEAdvertisementDataSecti
90
95
  void PeripheralWinrt::Update(const int rssiValue, const BluetoothLEAdvertisement& advertisment,
91
96
  const BluetoothLEAdvertisementType& advertismentType)
92
97
  {
98
+ // Handle name
93
99
  std::string localName = ws2s(advertisment.LocalName().c_str());
94
100
  if (!localName.empty())
95
101
  {
96
- name = localName;
102
+ name = std::optional<std::string>(localName);
97
103
  }
98
104
 
99
105
  connectable = advertismentType == BluetoothLEAdvertisementType::ConnectableUndirected ||
100
106
  advertismentType == BluetoothLEAdvertisementType::ConnectableDirected;
101
107
 
102
- manufacturerData.clear();
108
+ // Reset optional values
109
+ manufacturerData = std::nullopt;
110
+ serviceData = std::nullopt;
111
+ serviceUuids = std::nullopt;
103
112
 
104
113
  for (auto ds : advertisment.DataSections())
105
114
  {
@@ -107,17 +116,20 @@ void PeripheralWinrt::Update(const int rssiValue, const BluetoothLEAdvertisement
107
116
  {
108
117
  auto d = ds.Data();
109
118
  auto dr = DataReader::FromBuffer(d);
110
- txPowerLevel = dr.ReadByte();
111
- if (txPowerLevel >= 128)
112
- txPowerLevel -= 256;
119
+ int power = dr.ReadByte();
120
+ if (power >= 128)
121
+ power -= 256;
122
+ txPowerLevel = std::optional<int>(power);
113
123
  dr.Close();
114
124
  }
115
125
  else if (ds.DataType() == BluetoothLEAdvertisementDataTypes::ManufacturerSpecificData())
116
126
  {
117
127
  auto d = ds.Data();
118
128
  auto dr = DataReader::FromBuffer(d);
119
- manufacturerData.resize(d.Length());
120
- dr.ReadBytes(manufacturerData);
129
+ Data mData;
130
+ mData.resize(d.Length());
131
+ dr.ReadBytes(mData);
132
+ manufacturerData = std::optional<Data>(mData);
121
133
  dr.Close();
122
134
  }
123
135
  else if (ds.DataType() == BluetoothLEAdvertisementDataTypes::ServiceData16BitUuids())
@@ -134,10 +146,15 @@ void PeripheralWinrt::Update(const int rssiValue, const BluetoothLEAdvertisement
134
146
  }
135
147
  }
136
148
 
137
- serviceUuids.clear();
149
+ // Handle service UUIDs
150
+ std::vector<std::string> uuids;
138
151
  for (auto uuid : advertisment.ServiceUuids())
139
152
  {
140
- serviceUuids.push_back(toStr(uuid));
153
+ uuids.push_back(toStr(uuid));
154
+ }
155
+ if (!uuids.empty())
156
+ {
157
+ serviceUuids = std::optional<std::vector<std::string>>(uuids);
141
158
  }
142
159
 
143
160
  rssi = rssiValue;
@@ -148,6 +165,7 @@ void PeripheralWinrt::Disconnect()
148
165
  cachedServices.clear();
149
166
  if (device.has_value() && connectionToken)
150
167
  {
168
+ device->Close();
151
169
  device->ConnectionStatusChanged(connectionToken);
152
170
  }
153
171
  device = std::nullopt;
@@ -16,7 +16,7 @@ using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceSer
16
16
  #include <string>
17
17
  #include <optional>
18
18
 
19
- #include "peripheral.h"
19
+ #include "Peripheral.h"
20
20
  #include "winrt_guid.h"
21
21
 
22
22
  class CachedCharacteristic