@stoprocent/bleno 0.8.6 → 0.10.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/README.md +197 -30
- package/examples/echo/async.js +47 -0
- package/examples/echo/characteristic.js +15 -17
- package/examples/echo/main.js +19 -1
- package/examples/uart/main.js +3 -2
- package/examples/with-bindings/main.js +35 -0
- package/index.d.ts +166 -121
- package/index.js +5 -1
- package/lib/bleno.js +108 -17
- package/lib/characteristic.js +27 -10
- package/lib/common/include/ThreadSafeCallback.h +95 -0
- package/lib/hci-socket/acl-stream.js +3 -3
- package/lib/hci-socket/bindings.js +36 -29
- package/lib/hci-socket/gatt.js +177 -105
- package/lib/hci-socket/hci.js +5 -3
- package/lib/hci-socket/mgmt.js +1 -1
- package/lib/hci-socket/smp.js +5 -4
- package/lib/mac/binding.gyp +2 -6
- package/lib/mac/bindings.js +2 -3
- package/lib/mac/src/ble_peripheral_manager.h +3 -7
- package/lib/mac/src/ble_peripheral_manager.mm +101 -171
- package/lib/mac/src/bleno_mac.h +0 -1
- package/lib/mac/src/bleno_mac.mm +21 -33
- package/lib/mac/src/callbacks.h +12 -48
- package/lib/mac/src/callbacks.mm +35 -45
- package/lib/mac/src/napi_objc.mm +9 -30
- package/lib/mac/src/objc_cpp.h +2 -2
- package/lib/mac/src/objc_cpp.mm +3 -37
- package/lib/resolve-bindings.js +27 -6
- package/package.json +7 -10
- package/prebuilds/darwin-x64+arm64/@stoprocent+bleno.node +0 -0
- package/prebuilds/win32-ia32/@stoprocent+bleno.node +0 -0
- package/prebuilds/win32-x64/@stoprocent+bleno.node +0 -0
- package/test/characteristic.test.js +158 -11
- package/examples/battery-service/README.md +0 -14
- package/examples/blink1/README.md +0 -44
- package/examples/pizza/README.md +0 -16
- package/lib/mac/src/noble_mac.h +0 -34
- package/lib/mac/src/noble_mac.mm +0 -267
- package/lib/mac/src/peripheral.h +0 -23
- package/with-bindings.js +0 -5
- package/with-custom-binding.js +0 -6
package/lib/hci-socket/smp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { EventEmitter } = require('events');
|
|
2
2
|
const crypto = require('./crypto');
|
|
3
|
-
const
|
|
3
|
+
const Mgmt = require('./mgmt');
|
|
4
4
|
|
|
5
5
|
const SMP_CID = 0x0006;
|
|
6
6
|
|
|
@@ -17,9 +17,10 @@ const SMP_UNSPECIFIED = 0x08;
|
|
|
17
17
|
class Smp extends EventEmitter {
|
|
18
18
|
constructor (aclStream, localAddressType, localAddress, remoteAddressType, remoteAddress) {
|
|
19
19
|
super();
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
this._aclStream = aclStream;
|
|
22
|
-
|
|
22
|
+
this._mgmt = new Mgmt();
|
|
23
|
+
|
|
23
24
|
this._iat = Buffer.from([(remoteAddressType === 'random') ? 0x01 : 0x00]);
|
|
24
25
|
this._ia = Buffer.from(remoteAddress.split(':').reverse().join(''), 'hex');
|
|
25
26
|
this._rat = Buffer.from([(localAddressType === 'random') ? 0x01 : 0x00]);
|
|
@@ -132,7 +133,7 @@ class Smp extends EventEmitter {
|
|
|
132
133
|
this._random = Buffer.from('0000000000000000', 'hex');
|
|
133
134
|
this._stk = crypto.s1(this._tk, this._r, r);
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
this._mgmt.addLongTermKey(this._ia, this._iat, 0, 0, this._diversifier, this._random, this._stk);
|
|
136
137
|
|
|
137
138
|
this.write(Buffer.concat([
|
|
138
139
|
Buffer.from([SMP_PAIRING_RANDOM]),
|
package/lib/mac/binding.gyp
CHANGED
|
@@ -6,15 +6,11 @@
|
|
|
6
6
|
{
|
|
7
7
|
'target_name': 'binding',
|
|
8
8
|
'sources': [
|
|
9
|
-
'src
|
|
10
|
-
'src/napi_objc.mm',
|
|
11
|
-
'src/ble_peripheral_manager.mm',
|
|
12
|
-
'src/objc_cpp.mm',
|
|
13
|
-
'src/callbacks.mm'
|
|
9
|
+
"<!@(node -p \"require('fs').readdirSync('src').filter(f=>new RegExp('.*\\\\.(c|cc|cpp|mm)$').test(f)).map(f=>'src/'+f).join(' ')\")",
|
|
14
10
|
],
|
|
15
11
|
'include_dirs': [
|
|
16
12
|
"<!(node -p \"require('node-addon-api').include_dir\")",
|
|
17
|
-
"
|
|
13
|
+
"../common/include"
|
|
18
14
|
],
|
|
19
15
|
'cflags!': [ '-fno-exceptions' ],
|
|
20
16
|
'cflags_cc!': [ '-fno-exceptions' ],
|
package/lib/mac/bindings.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
const util = require('util');
|
|
1
|
+
const { EventEmitter } = require('events');
|
|
3
2
|
|
|
4
3
|
const { resolve } = require('path');
|
|
5
4
|
const dir = resolve(__dirname, '..', '..');
|
|
@@ -7,6 +6,6 @@ const binding = require('node-gyp-build')(dir);
|
|
|
7
6
|
|
|
8
7
|
const { BlenoMac } = binding;
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
Object.setPrototypeOf(BlenoMac.prototype, EventEmitter.prototype);
|
|
11
10
|
|
|
12
11
|
module.exports = BlenoMac;
|
|
@@ -7,11 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
#import "callbacks.h"
|
|
10
|
+
#include <map>
|
|
11
|
+
#include "callbacks.h"
|
|
13
12
|
|
|
14
|
-
#import <
|
|
13
|
+
#import <CoreBluetooth/CoreBluetooth.h>
|
|
15
14
|
|
|
16
15
|
@interface BLEPeripheralManager : NSObject {
|
|
17
16
|
@public Emit emit;
|
|
@@ -19,11 +18,8 @@
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
- (nonnull instancetype)init NS_DESIGNATED_INITIALIZER;
|
|
22
|
-
|
|
23
21
|
- (void)start;
|
|
24
22
|
- (void)startAdvertising:(NSString * _Nonnull)name serviceUUIDs:(NSArray<CBUUID *> * _Nonnull)serviceUUIDs;
|
|
25
|
-
- (void)startAdvertisingIBeacon:(NSData * _Nullable)data;
|
|
26
|
-
- (void)startAdvertisingWithEIRData:(NSData * _Nullable)data;
|
|
27
23
|
- (void)stopAdvertising;
|
|
28
24
|
- (void)setServices:(NSArray<CBMutableService *> * _Nonnull)services;
|
|
29
25
|
- (void)disconnect;
|
|
@@ -11,256 +11,186 @@
|
|
|
11
11
|
#include "objc_cpp.h"
|
|
12
12
|
|
|
13
13
|
@interface BLEPeripheralManager () <CBPeripheralManagerDelegate>
|
|
14
|
-
|
|
15
|
-
@property (nonatomic, strong) dispatch_queue_t queue;
|
|
14
|
+
@property (nonatomic, strong) dispatch_queue_t processingQueue;
|
|
16
15
|
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *pendingNotifications;
|
|
17
16
|
@property (nonatomic, strong) CBPeripheralManager *peripheralManager;
|
|
18
|
-
|
|
19
17
|
@end
|
|
20
18
|
|
|
21
19
|
@implementation BLEPeripheralManager
|
|
22
20
|
|
|
23
|
-
- (instancetype)init
|
|
21
|
+
- (instancetype)init
|
|
22
|
+
{
|
|
24
23
|
if (self = [super init]) {
|
|
25
|
-
|
|
26
|
-
self.queue = dispatch_queue_create("CBqueue", DISPATCH_QUEUE_SERIAL);
|
|
24
|
+
self.processingQueue = dispatch_queue_create("com.bleno.processing.queue", DISPATCH_QUEUE_SERIAL);
|
|
27
25
|
self.pendingNotifications = [NSMutableArray array];
|
|
28
26
|
}
|
|
29
27
|
return self;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
- (void)
|
|
30
|
+
- (void)dealloc
|
|
31
|
+
{
|
|
32
|
+
self.peripheralManager.delegate = nil;
|
|
33
|
+
[self.pendingNotifications removeAllObjects];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#pragma mark - Notification Management
|
|
37
|
+
|
|
38
|
+
- (void)addNotification:(NSData *)data
|
|
39
|
+
characteristic:(CBMutableCharacteristic *)characteristic
|
|
40
|
+
central:(CBCentral *)central
|
|
41
|
+
{
|
|
42
|
+
// All operations are now done on the same serial queue.
|
|
43
|
+
dispatch_async(self.processingQueue, ^{
|
|
44
|
+
NSDictionary *notification = @{
|
|
45
|
+
@"data": data,
|
|
46
|
+
@"characteristic": characteristic,
|
|
47
|
+
@"central": central
|
|
48
|
+
};
|
|
49
|
+
[self.pendingNotifications addObject:notification];
|
|
50
|
+
[self processNotificationQueue];
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)processNotificationQueue
|
|
55
|
+
{
|
|
56
|
+
// Since this runs on the serial queue, no additional synchronization is needed.
|
|
33
57
|
while (self.pendingNotifications.count > 0) {
|
|
34
58
|
NSDictionary *notification = self.pendingNotifications.firstObject;
|
|
35
59
|
NSData *data = notification[@"data"];
|
|
36
60
|
CBMutableCharacteristic *characteristic = notification[@"characteristic"];
|
|
37
61
|
CBCentral *central = notification[@"central"];
|
|
38
|
-
|
|
62
|
+
|
|
39
63
|
BOOL success = [self.peripheralManager updateValue:data
|
|
40
64
|
forCharacteristic:characteristic
|
|
41
65
|
onSubscribedCentrals:@[central]];
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
66
|
+
if (success) {
|
|
67
|
+
[self.pendingNotifications removeObjectAtIndex:0];
|
|
68
|
+
} else {
|
|
69
|
+
// Stop processing if updateValue fails; will retry on next callback.
|
|
70
|
+
break;
|
|
45
71
|
}
|
|
46
|
-
|
|
47
|
-
// Remove the successfully sent notification
|
|
48
|
-
[self.pendingNotifications removeObjectAtIndex:0];
|
|
49
72
|
}
|
|
50
73
|
}
|
|
51
74
|
|
|
52
75
|
#pragma mark - API
|
|
53
76
|
|
|
54
|
-
- (void)start
|
|
77
|
+
- (void)start
|
|
78
|
+
{
|
|
55
79
|
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self
|
|
56
|
-
|
|
80
|
+
queue:self.processingQueue];
|
|
57
81
|
}
|
|
58
82
|
|
|
59
|
-
- (void)startAdvertising:(nonnull NSString *)name serviceUUIDs:(nonnull NSArray<CBUUID *> *)serviceUUIDs
|
|
60
|
-
|
|
83
|
+
- (void)startAdvertising:(nonnull NSString *)name serviceUUIDs:(nonnull NSArray<CBUUID *> *)serviceUUIDs
|
|
84
|
+
{
|
|
61
85
|
if (self.peripheralManager.isAdvertising) {
|
|
62
86
|
return;
|
|
63
87
|
}
|
|
64
88
|
|
|
65
|
-
[self.peripheralManager startAdvertising
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
- (void)startAdvertisingIBeacon:(NSData *)data {
|
|
72
|
-
// NSLog(@"startAdvertisingIBeacon:%@", data);
|
|
89
|
+
[self.peripheralManager startAdvertising: @{
|
|
90
|
+
CBAdvertisementDataLocalNameKey: name,
|
|
91
|
+
CBAdvertisementDataServiceUUIDsKey: serviceUUIDs,
|
|
92
|
+
}];
|
|
73
93
|
}
|
|
74
94
|
|
|
75
|
-
- (void)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (self.peripheralManager.isAdvertising) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
- (void)stopAdvertising {
|
|
84
|
-
// NSLog(@"stopAdvertising");
|
|
85
|
-
|
|
95
|
+
- (void)stopAdvertising
|
|
96
|
+
{
|
|
86
97
|
[self.peripheralManager stopAdvertising];
|
|
87
98
|
}
|
|
88
99
|
|
|
89
|
-
- (void)setServices:(NSArray<CBMutableService *> *)services
|
|
100
|
+
- (void)setServices:(NSArray<CBMutableService *> *)services
|
|
101
|
+
{
|
|
90
102
|
for (CBMutableService *service in services) {
|
|
91
103
|
[self.peripheralManager addService:service];
|
|
92
104
|
}
|
|
93
105
|
}
|
|
94
106
|
|
|
95
|
-
- (void)disconnect
|
|
96
|
-
|
|
107
|
+
- (void)disconnect
|
|
108
|
+
{
|
|
97
109
|
|
|
98
|
-
// throw new Error('disconnect is not supported on OS X!');
|
|
99
110
|
}
|
|
100
111
|
|
|
101
|
-
- (void)updateRssi
|
|
102
|
-
|
|
112
|
+
- (void)updateRssi
|
|
113
|
+
{
|
|
114
|
+
|
|
103
115
|
}
|
|
104
116
|
|
|
105
117
|
#pragma mark - CBPeripheralManagerDelegate
|
|
106
118
|
|
|
107
|
-
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
switch(peripheral.state) {
|
|
111
|
-
case CBManagerStatePoweredOff:
|
|
112
|
-
string = @"CoreBluetooth BLE hardware is powered off.";
|
|
113
|
-
break;
|
|
114
|
-
|
|
115
|
-
case CBManagerStatePoweredOn:
|
|
116
|
-
string = @"CoreBluetooth BLE hardware is powered on and ready.";
|
|
117
|
-
break;
|
|
118
|
-
|
|
119
|
-
case CBManagerStateUnauthorized:
|
|
120
|
-
string = @"CoreBluetooth BLE state is unauthorized.";
|
|
121
|
-
break;
|
|
122
|
-
|
|
123
|
-
case CBManagerStateUnknown:
|
|
124
|
-
string = @"CoreBluetooth BLE state is unknown.";
|
|
125
|
-
break;
|
|
126
|
-
|
|
127
|
-
case CBManagerStateUnsupported:
|
|
128
|
-
string = @"CoreBluetooth BLE hardware is unsupported on this platform.";
|
|
129
|
-
break;
|
|
130
|
-
|
|
131
|
-
default:
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// NSLog(@"%@", string);
|
|
136
|
-
|
|
119
|
+
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
|
|
120
|
+
{
|
|
137
121
|
auto state = StringFromCBPeripheralState(peripheral.state);
|
|
138
122
|
emit.StateChange(state);
|
|
139
123
|
}
|
|
140
124
|
|
|
141
|
-
- (void)
|
|
142
|
-
|
|
125
|
+
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
|
|
126
|
+
error:(nullable NSError *)error
|
|
127
|
+
{
|
|
128
|
+
emit.AdvertisingStart(error);
|
|
143
129
|
}
|
|
144
130
|
|
|
145
|
-
- (void)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
emit.AdvertisingStart();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(nullable NSError *)error {
|
|
155
|
-
// NSLog(@"peripheralManagerDidAddService: %@ %@", service, error);
|
|
156
|
-
if (error) {
|
|
157
|
-
// NSLog(@"Error publishing service: %@", [error localizedDescription]);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
emit.ServicesSet();
|
|
131
|
+
- (void)peripheralManager:(CBPeripheralManager *)peripheral
|
|
132
|
+
didAddService:(CBService *)service
|
|
133
|
+
error:(nullable NSError *)error
|
|
134
|
+
{
|
|
135
|
+
emit.ServicesSet(error);
|
|
161
136
|
}
|
|
162
137
|
|
|
163
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBMutableCharacteristic *)characteristic
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
CBUUID *uuid = characteristic.UUID;
|
|
167
|
-
|
|
138
|
+
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBMutableCharacteristic *)characteristic
|
|
139
|
+
{
|
|
168
140
|
for (auto it = emitters.begin(); it != emitters.end(); ++it) {
|
|
169
|
-
if ([it->first isEqual:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
dispatch_async(self.queue, ^{
|
|
175
|
-
NSDictionary *notification = @{
|
|
176
|
-
@"data": data,
|
|
177
|
-
@"characteristic": characteristic,
|
|
178
|
-
@"central": central
|
|
179
|
-
};
|
|
180
|
-
[self.pendingNotifications addObject:notification];
|
|
181
|
-
[self sendNotifications];
|
|
182
|
-
});
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
it->second.Subscribe(central.maximumUpdateValueLength, cb);
|
|
186
|
-
}
|
|
141
|
+
if ([it->first isEqual:characteristic.UUID] == NO) { continue; }
|
|
142
|
+
auto cb = [weakSelf = self, characteristic, central](NSData *data) {
|
|
143
|
+
[weakSelf addNotification:data characteristic:characteristic central:central];
|
|
144
|
+
};
|
|
145
|
+
it->second.Subscribe(central.identifier, (uint16_t)central.maximumUpdateValueLength, cb);
|
|
187
146
|
}
|
|
188
147
|
}
|
|
189
148
|
|
|
190
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
CBUUID *uuid = characteristic.UUID;
|
|
194
|
-
|
|
149
|
+
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
|
|
150
|
+
{
|
|
195
151
|
for (auto it = emitters.begin(); it != emitters.end(); ++it) {
|
|
196
|
-
if ([it->first isEqual:
|
|
197
|
-
|
|
198
|
-
}
|
|
152
|
+
if ([it->first isEqual:characteristic.UUID] == NO) { continue; }
|
|
153
|
+
it->second.Unsubscribe(central.identifier);
|
|
199
154
|
}
|
|
200
155
|
}
|
|
201
156
|
|
|
202
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
CBCharacteristic *characteristic = request.characteristic;
|
|
206
|
-
CBUUID *uuid = characteristic.UUID;
|
|
207
|
-
|
|
157
|
+
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request
|
|
158
|
+
{
|
|
208
159
|
for (auto it = emitters.begin(); it != emitters.end(); ++it) {
|
|
209
|
-
if ([it->first isEqual:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
it->second.ReadRequest(request.offset, cb);
|
|
218
|
-
}
|
|
160
|
+
if ([it->first isEqual:request.characteristic.UUID] == NO) { continue; }
|
|
161
|
+
auto cb = [peripheral, request](int result, NSData *data) {
|
|
162
|
+
request.value = data;
|
|
163
|
+
[peripheral respondToRequest:request withResult:(CBATTError)result];
|
|
164
|
+
};
|
|
165
|
+
it->second.ReadRequest(request.central.identifier, (uint16_t)request.offset, cb);
|
|
219
166
|
}
|
|
220
167
|
}
|
|
221
168
|
|
|
222
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests
|
|
169
|
+
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests
|
|
170
|
+
{
|
|
223
171
|
for (CBATTRequest *request in requests) {
|
|
224
|
-
// NSLog(@"didReceiveWriteRequest: %@ %@", request.central, request.characteristic.UUID);
|
|
225
|
-
|
|
226
172
|
CBCharacteristic *characteristic = request.characteristic;
|
|
227
|
-
CBUUID *uuid = characteristic.UUID;
|
|
228
|
-
|
|
229
173
|
for (auto it = emitters.begin(); it != emitters.end(); ++it) {
|
|
230
|
-
if ([it->first isEqual:
|
|
231
|
-
|
|
174
|
+
if ([it->first isEqual:characteristic.UUID] == NO) { continue; }
|
|
175
|
+
bool sendResponse = (request.characteristic.properties & CBCharacteristicPropertyWrite) == CBCharacteristicPropertyWrite;
|
|
232
176
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
};
|
|
177
|
+
auto cb = [peripheral, request, sendResponse](int result) {
|
|
178
|
+
if (!sendResponse) { return; }
|
|
179
|
+
[peripheral respondToRequest:request withResult:(CBATTError)result];
|
|
180
|
+
};
|
|
239
181
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
182
|
+
it->second.WriteRequest(request.central.identifier,
|
|
183
|
+
request.value,
|
|
184
|
+
(uint16_t)request.offset,
|
|
185
|
+
!sendResponse,
|
|
186
|
+
cb);
|
|
245
187
|
}
|
|
246
188
|
}
|
|
247
189
|
}
|
|
248
190
|
|
|
249
|
-
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral
|
|
250
|
-
|
|
251
|
-
[self
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral didPublishL2CAPChannel:(CBL2CAPPSM)PSM error:(nullable NSError *)error {
|
|
255
|
-
// NSLog(@"didPublishL2CAPChannel");
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral didUnpublishL2CAPChannel:(CBL2CAPPSM)PSM error:(nullable NSError *)error {
|
|
259
|
-
// NSLog(@"didUnpublishL2CAPChannel");
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
- (void)peripheralManager:(CBPeripheralManager *)peripheral didOpenL2CAPChannel:(nullable CBL2CAPChannel *)channel error:(nullable NSError *)error {
|
|
263
|
-
// NSLog(@"didOpenL2CAPChannel");
|
|
191
|
+
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral
|
|
192
|
+
{
|
|
193
|
+
[self processNotificationQueue];
|
|
264
194
|
}
|
|
265
195
|
|
|
266
196
|
@end
|
package/lib/mac/src/bleno_mac.h
CHANGED
package/lib/mac/src/bleno_mac.mm
CHANGED
|
@@ -42,30 +42,24 @@ if(!peripheralManager) { \
|
|
|
42
42
|
THROW("BLEManager has already been cleaned up"); \
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
BlenoMac::BlenoMac(const Napi::CallbackInfo& info) : ObjectWrap(info) {
|
|
46
|
-
}
|
|
45
|
+
BlenoMac::BlenoMac(const Napi::CallbackInfo& info) : ObjectWrap(info) {}
|
|
47
46
|
|
|
48
47
|
Napi::Value BlenoMac::Init(const Napi::CallbackInfo& info) {
|
|
49
|
-
// NSLog(@"BlenoMac::Init");
|
|
50
|
-
|
|
51
48
|
Napi::Function emit = info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();
|
|
52
49
|
peripheralManager = [BLEPeripheralManager new];
|
|
53
50
|
peripheralManager->emit.Wrap(info.This(), emit);
|
|
54
51
|
[peripheralManager start];
|
|
55
|
-
return
|
|
52
|
+
return info.Env().Undefined();
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
Napi::Value BlenoMac::CleanUp(const Napi::CallbackInfo& info) {
|
|
59
56
|
CHECK_MANAGER()
|
|
60
57
|
CFRelease((__bridge CFTypeRef)peripheralManager);
|
|
61
58
|
peripheralManager = nil;
|
|
62
|
-
return
|
|
59
|
+
return info.Env().Undefined();
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
// startAdvertising(name, undashedServiceUuids)
|
|
66
62
|
Napi::Value BlenoMac::StartAdvertising(const Napi::CallbackInfo& info) {
|
|
67
|
-
// NSLog(@"BlenoMac::StartAdvertising");
|
|
68
|
-
|
|
69
63
|
CHECK_MANAGER();
|
|
70
64
|
ARG2(String, Array);
|
|
71
65
|
|
|
@@ -75,34 +69,35 @@ Napi::Value BlenoMac::StartAdvertising(const Napi::CallbackInfo& info) {
|
|
|
75
69
|
[peripheralManager startAdvertising:name
|
|
76
70
|
serviceUUIDs:array];
|
|
77
71
|
|
|
78
|
-
return
|
|
72
|
+
return info.Env().Undefined();
|
|
79
73
|
}
|
|
80
74
|
|
|
81
|
-
// startAdvertisingIBeacon(iBeaconData)
|
|
82
75
|
Napi::Value BlenoMac::StartAdvertisingIBeacon(const Napi::CallbackInfo& info) {
|
|
83
|
-
|
|
76
|
+
NSError *error = [NSError errorWithDomain:CBErrorDomain code:CBErrorUnknown userInfo:@{
|
|
77
|
+
NSLocalizedDescriptionKey: @"Function not implemented"
|
|
78
|
+
}];
|
|
79
|
+
peripheralManager->emit.AdvertisingStart(error);
|
|
84
80
|
|
|
85
|
-
return
|
|
81
|
+
return info.Env().Undefined();
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
// startAdvertisingWithEIRData(advertisementData, scanData)
|
|
89
84
|
Napi::Value BlenoMac::StartAdvertisingWithEIRData(const Napi::CallbackInfo& info) {
|
|
90
|
-
|
|
85
|
+
NSError *error = [NSError errorWithDomain:CBErrorDomain code:CBErrorUnknown userInfo:@{
|
|
86
|
+
NSLocalizedDescriptionKey: @"Function not implemented"
|
|
87
|
+
}];
|
|
88
|
+
peripheralManager->emit.AdvertisingStart(error);
|
|
91
89
|
|
|
92
|
-
return
|
|
90
|
+
return info.Env().Undefined();
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
// stopAdvertising()
|
|
96
93
|
Napi::Value BlenoMac::StopAdvertising(const Napi::CallbackInfo& info) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
CHECK_MANAGER();
|
|
95
|
+
[peripheralManager stopAdvertising];
|
|
96
|
+
peripheralManager->emit.AdvertisingStop();
|
|
97
|
+
return info.Env().Undefined();
|
|
100
98
|
}
|
|
101
99
|
|
|
102
|
-
// setServices(services)
|
|
103
100
|
Napi::Value BlenoMac::SetServices(const Napi::CallbackInfo& info) {
|
|
104
|
-
// NSLog(@"BlenoMac::SetServices");
|
|
105
|
-
|
|
106
101
|
CHECK_MANAGER();
|
|
107
102
|
ARG1(Array);
|
|
108
103
|
|
|
@@ -126,28 +121,21 @@ Napi::Value BlenoMac::SetServices(const Napi::CallbackInfo& info) {
|
|
|
126
121
|
|
|
127
122
|
peripheralManager->emitters = emitters;
|
|
128
123
|
|
|
129
|
-
return
|
|
124
|
+
return info.Env().Undefined();
|
|
130
125
|
}
|
|
131
126
|
|
|
132
|
-
// disconnect()
|
|
133
127
|
Napi::Value BlenoMac::Disconnect(const Napi::CallbackInfo& info) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return Napi::Value();
|
|
128
|
+
return info.Env().Undefined();
|
|
137
129
|
}
|
|
138
130
|
|
|
139
|
-
// updateRssi()
|
|
140
131
|
Napi::Value BlenoMac::UpdateRssi(const Napi::CallbackInfo& info) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return Napi::Value();
|
|
132
|
+
return info.Env().Undefined();
|
|
144
133
|
}
|
|
145
134
|
|
|
146
135
|
Napi::Function BlenoMac::GetClass(Napi::Env env) {
|
|
147
136
|
return DefineClass(env, "BlenoMac", {
|
|
148
137
|
BlenoMac::InstanceMethod("init", &BlenoMac::Init),
|
|
149
138
|
BlenoMac::InstanceMethod("cleanUp", &BlenoMac::CleanUp),
|
|
150
|
-
|
|
151
139
|
BlenoMac::InstanceMethod("startAdvertising", &BlenoMac::StartAdvertising),
|
|
152
140
|
BlenoMac::InstanceMethod("startAdvertisingIBeacon", &BlenoMac::StartAdvertisingIBeacon),
|
|
153
141
|
BlenoMac::InstanceMethod("startAdvertisingWithEIRData", &BlenoMac::StartAdvertisingWithEIRData),
|
package/lib/mac/src/callbacks.h
CHANGED
|
@@ -1,38 +1,20 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <napi.h>
|
|
4
|
-
#include "peripheral.h"
|
|
5
4
|
|
|
6
5
|
#import <Foundation/Foundation.h>
|
|
7
6
|
|
|
8
7
|
class ThreadSafeCallback;
|
|
8
|
+
using Data = std::vector<uint8_t>;
|
|
9
9
|
|
|
10
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
10
11
|
class Emit {
|
|
11
12
|
public:
|
|
12
13
|
void Wrap(const Napi::Value& receiver, const Napi::Function& callback);
|
|
13
|
-
|
|
14
|
-
void
|
|
15
|
-
void ServicesSet();
|
|
16
|
-
|
|
14
|
+
void AdvertisingStart(NSError * _Nullable error);
|
|
15
|
+
void AdvertisingStop();
|
|
16
|
+
void ServicesSet(NSError * _Nullable error);
|
|
17
17
|
void StateChange(const std::string& state);
|
|
18
|
-
|
|
19
|
-
// void RadioState(const std::string& status);
|
|
20
|
-
// void ScanState(bool start);
|
|
21
|
-
// void Scan(const std::string& uuid, int rssi, const Peripheral& peripheral);
|
|
22
|
-
// void Connected(const std::string& uuid, const std::string& error = "");
|
|
23
|
-
// void Disconnected(const std::string& uuid);
|
|
24
|
-
// void RSSI(const std::string& uuid, int rssi);
|
|
25
|
-
// void ServicesDiscovered(const std::string& uuid, const std::vector<std::string>& serviceUuids);
|
|
26
|
-
// void IncludedServicesDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector<std::string>& serviceUuids);
|
|
27
|
-
// void CharacteristicsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector<std::pair<std::string, std::vector<std::string>>>& characteristics);
|
|
28
|
-
// void Read(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const Data& data, bool isNotification);
|
|
29
|
-
// void Write(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid);
|
|
30
|
-
// void Notify(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, bool state);
|
|
31
|
-
// void DescriptorsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::vector<std::string>& descriptorUuids);
|
|
32
|
-
// void ReadValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid, const Data& data);
|
|
33
|
-
// void WriteValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid);
|
|
34
|
-
// void ReadHandle(const std::string& uuid, int descriptorHandle, const std::vector<uint8_t>& data);
|
|
35
|
-
// void WriteHandle(const std::string& uuid, int descriptorHandle);
|
|
36
18
|
protected:
|
|
37
19
|
std::shared_ptr<ThreadSafeCallback> mCallback;
|
|
38
20
|
};
|
|
@@ -40,31 +22,12 @@ protected:
|
|
|
40
22
|
class EmitCharacteristic {
|
|
41
23
|
public:
|
|
42
24
|
void Wrap(const Napi::Value& receiver, const Napi::Function& callback);
|
|
43
|
-
|
|
44
|
-
void
|
|
45
|
-
void
|
|
46
|
-
void
|
|
47
|
-
void
|
|
48
|
-
void
|
|
49
|
-
void Indicate();
|
|
50
|
-
|
|
51
|
-
// void RadioState(const std::string& status);
|
|
52
|
-
// void ScanState(bool start);
|
|
53
|
-
// void Scan(const std::string& uuid, int rssi, const Peripheral& peripheral);
|
|
54
|
-
// void Connected(const std::string& uuid, const std::string& error = "");
|
|
55
|
-
// void Disconnected(const std::string& uuid);
|
|
56
|
-
// void RSSI(const std::string& uuid, int rssi);
|
|
57
|
-
// void ServicesDiscovered(const std::string& uuid, const std::vector<std::string>& serviceUuids);
|
|
58
|
-
// void IncludedServicesDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector<std::string>& serviceUuids);
|
|
59
|
-
// void CharacteristicsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector<std::pair<std::string, std::vector<std::string>>>& characteristics);
|
|
60
|
-
// void Read(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const Data& data, bool isNotification);
|
|
61
|
-
// void Write(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid);
|
|
62
|
-
// void Notify(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, bool state);
|
|
63
|
-
// void DescriptorsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::vector<std::string>& descriptorUuids);
|
|
64
|
-
// void ReadValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid, const Data& data);
|
|
65
|
-
// void WriteValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid);
|
|
66
|
-
// void ReadHandle(const std::string& uuid, int descriptorHandle, const std::vector<uint8_t>& data);
|
|
67
|
-
// void WriteHandle(const std::string& uuid, int descriptorHandle);
|
|
25
|
+
void ReadRequest(NSUUID *handle, uint16_t offset, std::function<void (uint16_t, NSData *)> completion);
|
|
26
|
+
void WriteRequest(NSUUID *handle, NSData *data, uint16_t offset, bool ignoreResponse, std::function<void (uint16_t)> completion);
|
|
27
|
+
void Subscribe(NSUUID *handle, uint16_t maxValueSize, std::function<void (NSData *)> completion);
|
|
28
|
+
void Unsubscribe(NSUUID *handle);
|
|
29
|
+
void Notify(NSUUID *handle);
|
|
30
|
+
void Indicate(NSUUID *handle);
|
|
68
31
|
protected:
|
|
69
32
|
std::shared_ptr<ThreadSafeCallback> mCallback;
|
|
70
33
|
|
|
@@ -74,3 +37,4 @@ private:
|
|
|
74
37
|
|
|
75
38
|
Napi::Buffer<uint8_t> toBufferFromNSData(Napi::Env& env, const NSData *data);
|
|
76
39
|
Napi::Buffer<uint8_t> toBuffer(Napi::Env& env, const Data& data);
|
|
40
|
+
NS_ASSUME_NONNULL_END
|