@stoprocent/noble 2.1.7 → 2.3.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/examples/peripheral-explorer-async.js +9 -2
- package/lib/common/include/Emit.h +1 -0
- package/lib/common/src/Emit.cc +8 -0
- package/lib/mac/src/ble_manager.h +2 -0
- package/lib/mac/src/ble_manager.mm +18 -0
- package/lib/win/src/ble_manager.cc +46 -0
- package/lib/win/src/ble_manager.h +2 -0
- package/lib/win/src/peripheral_winrt.cc +4 -0
- package/lib/win/src/peripheral_winrt.h +4 -0
- package/package.json +1 -1
- package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
- package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
- package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
|
@@ -13,6 +13,7 @@ try {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const starTime = Date.now();
|
|
16
|
+
let cancelConnectTimeout;
|
|
16
17
|
|
|
17
18
|
let peripheral;
|
|
18
19
|
async function main () {
|
|
@@ -20,12 +21,13 @@ async function main () {
|
|
|
20
21
|
await noble.waitForPoweredOnAsync();
|
|
21
22
|
|
|
22
23
|
// Cancel the connection after 5 seconds if it is still connecting
|
|
23
|
-
setTimeout(() => {
|
|
24
|
+
cancelConnectTimeout = setTimeout(() => {
|
|
24
25
|
noble.cancelConnect(peripheralIdOrAddress);
|
|
25
26
|
}, 5000);
|
|
26
27
|
|
|
27
28
|
if (directConnect === '1') {
|
|
28
29
|
peripheral = await noble.connectAsync(peripheralIdOrAddress, { addressType });
|
|
30
|
+
clearTimeout(cancelConnectTimeout);
|
|
29
31
|
await explore(peripheral);
|
|
30
32
|
} else {
|
|
31
33
|
await noble.startScanningAsync([], false);
|
|
@@ -92,13 +94,18 @@ const explore = async (peripheral) => {
|
|
|
92
94
|
console.log('noble stopped');
|
|
93
95
|
});
|
|
94
96
|
|
|
97
|
+
peripheral.on('mtu', (mtu) => {
|
|
98
|
+
console.log('MTU Updated: ', mtu);
|
|
99
|
+
});
|
|
100
|
+
|
|
95
101
|
if (peripheral.state !== 'connected') {
|
|
96
102
|
await peripheral.connectAsync();
|
|
103
|
+
clearTimeout(cancelConnectTimeout);
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
const rssi = await peripheral.updateRssiAsync();
|
|
100
107
|
console.log('RSSI', rssi);
|
|
101
|
-
|
|
108
|
+
|
|
102
109
|
const services = await peripheral.discoverServicesAsync([]);
|
|
103
110
|
|
|
104
111
|
for (const service of services) {
|
|
@@ -18,6 +18,7 @@ public:
|
|
|
18
18
|
void Scan(const std::string& uuid, int rssi, const Peripheral& peripheral);
|
|
19
19
|
void Connected(const std::string& uuid, const std::string& error = "");
|
|
20
20
|
void Disconnected(const std::string& uuid);
|
|
21
|
+
void MTU(const std::string& uuid, int mtu);
|
|
21
22
|
void RSSI(const std::string& uuid, int rssi, const std::string& error = "");
|
|
22
23
|
void ServicesDiscovered(const std::string& uuid, const std::vector<std::string>& serviceUuids, const std::string& error = "");
|
|
23
24
|
void IncludedServicesDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector<std::string>& serviceUuids, const std::string& error = "");
|
package/lib/common/src/Emit.cc
CHANGED
|
@@ -162,6 +162,14 @@ void Emit::Disconnected(const std::string& uuid)
|
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
void Emit::MTU(const std::string& uuid, int mtu)
|
|
166
|
+
{
|
|
167
|
+
mCallback->call([uuid, mtu](Napi::Env env, std::vector<napi_value>& args) {
|
|
168
|
+
// emit('onMtu', deviceUuid, mtu);
|
|
169
|
+
args = { _s("onMtu"), _u(uuid), _n(mtu) };
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
165
173
|
void Emit::RSSI(const std::string& uuid, int rssi, const std::string& error)
|
|
166
174
|
{
|
|
167
175
|
mCallback->call([uuid, rssi, error](Napi::Env env, std::vector<napi_value>& args) {
|
|
@@ -14,8 +14,10 @@
|
|
|
14
14
|
@property (assign) CBManagerState lastState;
|
|
15
15
|
@property dispatch_queue_t dispatchQueue;
|
|
16
16
|
@property NSMutableDictionary *peripherals;
|
|
17
|
+
@property NSMutableDictionary *mtus;
|
|
17
18
|
@property NSMutableSet *discovered;
|
|
18
19
|
|
|
20
|
+
|
|
19
21
|
- (instancetype)init: (const Napi::Value&) receiver with: (const Napi::Function&) callback;
|
|
20
22
|
- (void)scan: (NSArray<NSString*> *)serviceUUIDs allowDuplicates: (BOOL)allowDuplicates;
|
|
21
23
|
- (void)stopScan;
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
#import <Foundation/Foundation.h>
|
|
6
6
|
|
|
7
|
+
@interface BLEManager ()
|
|
8
|
+
- (void)updateMtuForPeripheral:(CBPeripheral*) peripheral;
|
|
9
|
+
@end
|
|
10
|
+
|
|
7
11
|
@implementation BLEManager
|
|
8
12
|
|
|
9
13
|
- (instancetype)init: (const Napi::Value&) receiver with: (const Napi::Function&) callback
|
|
@@ -16,10 +20,20 @@
|
|
|
16
20
|
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:self.dispatchQueue];
|
|
17
21
|
self.discovered = [NSMutableSet set];
|
|
18
22
|
self.peripherals = [NSMutableDictionary dictionaryWithCapacity:10];
|
|
23
|
+
self.mtus = [NSMutableDictionary dictionaryWithCapacity:10];
|
|
19
24
|
}
|
|
20
25
|
return self;
|
|
21
26
|
}
|
|
22
27
|
|
|
28
|
+
- (void)updateMtuForPeripheral:(CBPeripheral*) peripheral {
|
|
29
|
+
NSUInteger mtu = [peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse];
|
|
30
|
+
NSNumber *mtuNumber = [self.mtus objectForKey: peripheral.identifier];
|
|
31
|
+
if (!mtuNumber || [mtuNumber unsignedIntegerValue] != mtu) {
|
|
32
|
+
emit.MTU(getUuid(peripheral), mtu);
|
|
33
|
+
[self.mtus setObject:[NSNumber numberWithInt:mtu] forKey: peripheral.identifier];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
23
37
|
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
|
|
24
38
|
{
|
|
25
39
|
if (central.state != self.lastState && self.lastState == CBManagerStatePoweredOff && central.state == CBManagerStatePoweredOn) {
|
|
@@ -154,6 +168,8 @@
|
|
|
154
168
|
|
|
155
169
|
std::string uuid = getUuid(peripheral);
|
|
156
170
|
emit.Connected(uuid, "");
|
|
171
|
+
[self updateMtuForPeripheral:peripheral];
|
|
172
|
+
|
|
157
173
|
}
|
|
158
174
|
|
|
159
175
|
- (void) centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
|
|
@@ -213,6 +229,7 @@
|
|
|
213
229
|
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
|
|
214
230
|
std::string uuid = getUuid(peripheral);
|
|
215
231
|
std::vector<std::string> services = getServices(peripheral.services);
|
|
232
|
+
[self updateMtuForPeripheral:peripheral];
|
|
216
233
|
emit.ServicesDiscovered(uuid, services, error ? error.localizedDescription.UTF8String : "");
|
|
217
234
|
}
|
|
218
235
|
|
|
@@ -263,6 +280,7 @@
|
|
|
263
280
|
std::string uuid = getUuid(peripheral);
|
|
264
281
|
std::string serviceUuid = std::string([service.UUID.UUIDString UTF8String]);
|
|
265
282
|
auto characteristics = getCharacteristics(service.characteristics);
|
|
283
|
+
[self updateMtuForPeripheral:peripheral];
|
|
266
284
|
emit.CharacteristicsDiscovered(uuid, serviceUuid, characteristics, error ? error.localizedDescription.UTF8String : "");
|
|
267
285
|
}
|
|
268
286
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <winrt/Windows.Storage.Streams.h>
|
|
6
6
|
#include <winrt/Windows.Security.Cryptography.h>
|
|
7
7
|
#include <winrt/Windows.Devices.Bluetooth.h>
|
|
8
|
+
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
using winrt::Windows::Devices::Bluetooth::BluetoothCacheMode;
|
|
@@ -17,6 +18,7 @@ using winrt::Windows::Storage::Streams::IBuffer;
|
|
|
17
18
|
using winrt::Windows::Storage::Streams::ByteOrder;
|
|
18
19
|
using winrt::Windows::Security::Cryptography::CryptographicBuffer;
|
|
19
20
|
using winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementBytePattern;
|
|
21
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattSession;
|
|
20
22
|
|
|
21
23
|
template <typename T> auto inFilter(std::vector<T> filter, T object)
|
|
22
24
|
{
|
|
@@ -324,6 +326,10 @@ void BLEManager::OnConnected(IAsyncOperation<BluetoothLEDevice> asyncOp, AsyncSt
|
|
|
324
326
|
peripheral.device = device;
|
|
325
327
|
peripheral.connectionToken = token;
|
|
326
328
|
mEmit.Connected(uuid);
|
|
329
|
+
|
|
330
|
+
// Get GATT session to access the MTU
|
|
331
|
+
auto completed = bind2(this, &BLEManager::OnGattSessionCreated, uuid);
|
|
332
|
+
GattSession::FromDeviceIdAsync(device.BluetoothDeviceId()).Completed(completed);
|
|
327
333
|
}
|
|
328
334
|
else
|
|
329
335
|
{
|
|
@@ -336,6 +342,46 @@ void BLEManager::OnConnected(IAsyncOperation<BluetoothLEDevice> asyncOp, AsyncSt
|
|
|
336
342
|
}
|
|
337
343
|
}
|
|
338
344
|
|
|
345
|
+
void BLEManager::OnGattSessionCreated(IAsyncOperation<GattSession> asyncOp, AsyncStatus status, const std::string uuid)
|
|
346
|
+
{
|
|
347
|
+
if (status == AsyncStatus::Completed)
|
|
348
|
+
{
|
|
349
|
+
auto session = asyncOp.GetResults();
|
|
350
|
+
if (session)
|
|
351
|
+
{
|
|
352
|
+
// MaxPduSize is equivalent to the MTU-3 (MTU minus ATT header)
|
|
353
|
+
// MTU = MaxPduSize + 3
|
|
354
|
+
int mtu = session.MaxPduSize();
|
|
355
|
+
mEmit.MTU(uuid, mtu);
|
|
356
|
+
|
|
357
|
+
// Subscribe to MTU changes
|
|
358
|
+
auto onPduSizeChanged = bind2(this, &BLEManager::OnMaxPduSizeChanged, uuid);
|
|
359
|
+
|
|
360
|
+
// Store both the session and the event token in the peripheral
|
|
361
|
+
PeripheralWinrt& peripheral = mDeviceMap[uuid];
|
|
362
|
+
peripheral.gattSession = session;
|
|
363
|
+
auto token = session.MaxPduSizeChanged(onPduSizeChanged);
|
|
364
|
+
peripheral.maxPduSizeChangedToken = token;
|
|
365
|
+
}
|
|
366
|
+
else
|
|
367
|
+
{
|
|
368
|
+
LOGE("Failed to get GattSession for device %s", uuid.c_str());
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
else
|
|
372
|
+
{
|
|
373
|
+
LOGE("Failed to create GattSession: %s", asyncStatusToString(status).c_str());
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Add this new method to handle the MaxPduSizeChanged event
|
|
378
|
+
void BLEManager::OnMaxPduSizeChanged(GattSession session, winrt::Windows::Foundation::IInspectable object, const std::string uuid)
|
|
379
|
+
{
|
|
380
|
+
// Update MTU value when it changes
|
|
381
|
+
int mtu = session.MaxPduSize();
|
|
382
|
+
mEmit.MTU(uuid, mtu);
|
|
383
|
+
}
|
|
384
|
+
|
|
339
385
|
bool BLEManager::Disconnect(const std::string& uuid)
|
|
340
386
|
{
|
|
341
387
|
CHECK_DEVICE();
|
|
@@ -44,6 +44,8 @@ private:
|
|
|
44
44
|
void OnScanStopped(BluetoothLEAdvertisementWatcher watcher, const BluetoothLEAdvertisementWatcherStoppedEventArgs& args);
|
|
45
45
|
void OnConnected(IAsyncOperation<BluetoothLEDevice> asyncOp, AsyncStatus status, std::string uuid);
|
|
46
46
|
void OnConnectionStatusChanged(BluetoothLEDevice device, winrt::Windows::Foundation::IInspectable inspectable);
|
|
47
|
+
void OnGattSessionCreated(IAsyncOperation<GattSession> asyncOp, AsyncStatus status, std::string uuid);
|
|
48
|
+
void OnMaxPduSizeChanged(GattSession session, winrt::Windows::Foundation::IInspectable object, std::string uuid);
|
|
47
49
|
void OnServicesDiscovered(IAsyncOperation<GattDeviceServicesResult> asyncOp, AsyncStatus status, std::string uuid, std::vector<winrt::guid> serviceUUIDs);
|
|
48
50
|
void OnIncludedServicesDiscovered(IAsyncOperation<GattDeviceServicesResult> asyncOp, AsyncStatus status, std::string uuid, std::string serviceId, std::vector<winrt::guid> serviceUUIDs);
|
|
49
51
|
void OnCharacteristicsDiscovered(IAsyncOperation<GattCharacteristicsResult> asyncOp, AsyncStatus status, std::string uuid, std::string serviceId, std::vector<winrt::guid> characteristicUUIDs);
|
|
@@ -163,6 +163,10 @@ void PeripheralWinrt::Update(const int rssiValue, const BluetoothLEAdvertisement
|
|
|
163
163
|
void PeripheralWinrt::Disconnect()
|
|
164
164
|
{
|
|
165
165
|
cachedServices.clear();
|
|
166
|
+
if (gattSession.has_value() && maxPduSizeChangedToken)
|
|
167
|
+
{
|
|
168
|
+
gattSession->MaxPduSizeChanged(maxPduSizeChangedToken);
|
|
169
|
+
}
|
|
166
170
|
if (device.has_value() && connectionToken)
|
|
167
171
|
{
|
|
168
172
|
device->Close();
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
#define WIN32_LEAN_AND_MEAN
|
|
5
5
|
#include <Windows.h>
|
|
6
6
|
#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>
|
|
7
|
+
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
|
|
7
8
|
|
|
8
9
|
using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
|
|
9
10
|
using winrt::Windows::Devices::Bluetooth::BluetoothLEDevice;
|
|
10
11
|
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristic;
|
|
11
12
|
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDescriptor;
|
|
12
13
|
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceService;
|
|
14
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattSession;
|
|
13
15
|
|
|
14
16
|
#include "winrt/Windows.Devices.Bluetooth.h"
|
|
15
17
|
|
|
@@ -68,6 +70,8 @@ public:
|
|
|
68
70
|
uint64_t bluetoothAddress;
|
|
69
71
|
std::optional<BluetoothLEDevice> device;
|
|
70
72
|
winrt::event_token connectionToken;
|
|
73
|
+
std::optional<GattSession> gattSession;
|
|
74
|
+
winrt::event_token maxPduSizeChangedToken;
|
|
71
75
|
|
|
72
76
|
private:
|
|
73
77
|
void GetServiceFromDevice(winrt::guid serviceUuid,
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|