@stoprocent/noble 1.9.2-16
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/.editorconfig +11 -0
- package/.eslintrc.js +25 -0
- package/.github/FUNDING.yml +2 -0
- package/.github/workflows/fediverse-action.yml +16 -0
- package/.github/workflows/nodepackage.yml +77 -0
- package/.github/workflows/npm-publish.yml +26 -0
- package/.github/workflows/prebuild.yml +65 -0
- package/.nycrc.json +4 -0
- package/CHANGELOG.md +119 -0
- package/LICENSE +20 -0
- package/MAINTAINERS.md +1 -0
- package/README.md +833 -0
- package/assets/noble-logo.png +0 -0
- package/assets/noble-logo.svg +13 -0
- package/binding.gyp +19 -0
- package/codecov.yml +5 -0
- package/examples/advertisement-discovery.js +65 -0
- package/examples/cache-gatt-discovery.js +198 -0
- package/examples/cache-gatt-reconnect.js +164 -0
- package/examples/echo.js +104 -0
- package/examples/enter-exit.js +78 -0
- package/examples/peripheral-explorer-async.js +133 -0
- package/examples/peripheral-explorer.js +225 -0
- package/examples/pizza/README.md +15 -0
- package/examples/pizza/central.js +194 -0
- package/examples/pizza/pizza.js +60 -0
- package/index.d.ts +203 -0
- package/index.js +6 -0
- package/lib/characteristic.js +161 -0
- package/lib/characteristics.json +449 -0
- package/lib/descriptor.js +72 -0
- package/lib/descriptors.json +47 -0
- package/lib/distributed/bindings.js +326 -0
- package/lib/hci-socket/acl-stream.js +60 -0
- package/lib/hci-socket/bindings.js +788 -0
- package/lib/hci-socket/crypto.js +74 -0
- package/lib/hci-socket/gap.js +432 -0
- package/lib/hci-socket/gatt.js +809 -0
- package/lib/hci-socket/hci-status.json +71 -0
- package/lib/hci-socket/hci.js +1264 -0
- package/lib/hci-socket/signaling.js +76 -0
- package/lib/hci-socket/smp.js +140 -0
- package/lib/hci-uart/bindings.js +569 -0
- package/lib/hci-uart/hci-serial-parser.js +70 -0
- package/lib/hci-uart/hci.js +1336 -0
- package/lib/mac/binding.gyp +26 -0
- package/lib/mac/bindings.js +11 -0
- package/lib/mac/src/ble_manager.h +41 -0
- package/lib/mac/src/ble_manager.mm +435 -0
- package/lib/mac/src/callbacks.cc +222 -0
- package/lib/mac/src/callbacks.h +84 -0
- package/lib/mac/src/napi_objc.h +12 -0
- package/lib/mac/src/napi_objc.mm +50 -0
- package/lib/mac/src/noble_mac.h +34 -0
- package/lib/mac/src/noble_mac.mm +264 -0
- package/lib/mac/src/objc_cpp.h +26 -0
- package/lib/mac/src/objc_cpp.mm +126 -0
- package/lib/mac/src/peripheral.h +23 -0
- package/lib/manufacture.js +48 -0
- package/lib/noble.js +593 -0
- package/lib/peripheral.js +219 -0
- package/lib/resolve-bindings-web.js +9 -0
- package/lib/resolve-bindings.js +44 -0
- package/lib/service.js +72 -0
- package/lib/services.json +92 -0
- package/lib/webbluetooth/bindings.js +368 -0
- package/lib/websocket/bindings.js +321 -0
- package/lib/win/binding.gyp +23 -0
- package/lib/win/bindings.js +11 -0
- package/lib/win/src/ble_manager.cc +802 -0
- package/lib/win/src/ble_manager.h +77 -0
- package/lib/win/src/callbacks.cc +274 -0
- package/lib/win/src/callbacks.h +33 -0
- package/lib/win/src/napi_winrt.cc +76 -0
- package/lib/win/src/napi_winrt.h +12 -0
- package/lib/win/src/noble_winrt.cc +308 -0
- package/lib/win/src/noble_winrt.h +34 -0
- package/lib/win/src/notify_map.cc +62 -0
- package/lib/win/src/notify_map.h +50 -0
- package/lib/win/src/peripheral.h +23 -0
- package/lib/win/src/peripheral_winrt.cc +296 -0
- package/lib/win/src/peripheral_winrt.h +82 -0
- package/lib/win/src/radio_watcher.cc +125 -0
- package/lib/win/src/radio_watcher.h +61 -0
- package/lib/win/src/winrt_cpp.cc +82 -0
- package/lib/win/src/winrt_cpp.h +11 -0
- package/lib/win/src/winrt_guid.cc +12 -0
- package/lib/win/src/winrt_guid.h +13 -0
- package/misc/nrf52840dk.hex +6921 -0
- package/misc/prj.conf +43 -0
- package/package.json +96 -0
- package/test/lib/characteristic.test.js +791 -0
- package/test/lib/descriptor.test.js +249 -0
- package/test/lib/distributed/bindings.test.js +918 -0
- package/test/lib/hci-socket/acl-stream.test.js +188 -0
- package/test/lib/hci-socket/bindings.test.js +1756 -0
- package/test/lib/hci-socket/crypto.test.js +55 -0
- package/test/lib/hci-socket/gap.test.js +1089 -0
- package/test/lib/hci-socket/gatt.test.js +2392 -0
- package/test/lib/hci-socket/hci.test.js +1891 -0
- package/test/lib/hci-socket/signaling.test.js +94 -0
- package/test/lib/hci-socket/smp.test.js +268 -0
- package/test/lib/manufacture.test.js +77 -0
- package/test/lib/peripheral.test.js +623 -0
- package/test/lib/resolve-bindings.test.js +102 -0
- package/test/lib/service.test.js +195 -0
- package/test/lib/webbluetooth/bindings.test.js +190 -0
- package/test/lib/websocket/bindings.test.js +456 -0
- package/test/noble.test.js +1565 -0
- package/test.js +131 -0
- package/with-bindings.js +5 -0
- package/ws-slave.js +404 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
'targets': [
|
|
3
|
+
{
|
|
4
|
+
'target_name': 'binding',
|
|
5
|
+
'sources': [ 'src/noble_mac.mm', 'src/napi_objc.mm', 'src/ble_manager.mm', 'src/objc_cpp.mm', 'src/callbacks.cc' ],
|
|
6
|
+
'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],
|
|
7
|
+
'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],
|
|
8
|
+
'cflags!': [ '-fno-exceptions' ],
|
|
9
|
+
'cflags_cc!': [ '-fno-exceptions' ],
|
|
10
|
+
'xcode_settings': {
|
|
11
|
+
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
|
|
12
|
+
'CLANG_CXX_LIBRARY': 'libc++',
|
|
13
|
+
'MACOSX_DEPLOYMENT_TARGET': '10.7',
|
|
14
|
+
'OTHER_CFLAGS': [
|
|
15
|
+
'-fobjc-arc',
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
'link_settings': {
|
|
19
|
+
'libraries': [
|
|
20
|
+
'$(SDKROOT)/System/Library/Frameworks/CoreBluetooth.framework',
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
'product_dir': '../lib/mac/native',
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { EventEmitter } = require('events');
|
|
2
|
+
const { inherits } = require('util');
|
|
3
|
+
const { resolve } = require('path');
|
|
4
|
+
const dir = resolve(__dirname, '..', '..');
|
|
5
|
+
const binding = require('node-gyp-build')(dir);
|
|
6
|
+
|
|
7
|
+
const { NobleMac } = binding;
|
|
8
|
+
|
|
9
|
+
inherits(NobleMac, EventEmitter);
|
|
10
|
+
|
|
11
|
+
module.exports = NobleMac;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ble_manager.h
|
|
3
|
+
// noble-mac-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Georg Vienna on 28.08.18.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#import <Foundation/Foundation.h>
|
|
11
|
+
#import <CoreBluetooth/CoreBluetooth.h>
|
|
12
|
+
#include <dispatch/dispatch.h>
|
|
13
|
+
|
|
14
|
+
#include "callbacks.h"
|
|
15
|
+
|
|
16
|
+
@interface BLEManager : NSObject <CBCentralManagerDelegate, CBPeripheralDelegate> {
|
|
17
|
+
Emit emit;
|
|
18
|
+
bool pendingRead;
|
|
19
|
+
}
|
|
20
|
+
@property (strong) CBCentralManager *centralManager;
|
|
21
|
+
@property dispatch_queue_t dispatchQueue;
|
|
22
|
+
@property NSMutableDictionary *peripherals;
|
|
23
|
+
|
|
24
|
+
- (instancetype)init: (const Napi::Value&) receiver with: (const Napi::Function&) callback;
|
|
25
|
+
- (void)scan: (NSArray<NSString*> *)serviceUUIDs allowDuplicates: (BOOL)allowDuplicates;
|
|
26
|
+
- (void)stopScan;
|
|
27
|
+
- (BOOL)connect:(NSString*) uuid;
|
|
28
|
+
- (BOOL)disconnect:(NSString*) uuid;
|
|
29
|
+
- (BOOL)updateRSSI:(NSString*) uuid;
|
|
30
|
+
- (BOOL)discoverServices:(NSString*) uuid serviceUuids:(NSArray<NSString*>*) services;
|
|
31
|
+
- (BOOL)discoverIncludedServices:(NSString*) uuid forService:(NSString*) serviceUuid services:(NSArray<NSString*>*) serviceUuids;
|
|
32
|
+
- (BOOL)discoverCharacteristics:(NSString*) nsAddress forService:(NSString*) service characteristics:(NSArray<NSString*>*) characteristics;
|
|
33
|
+
- (BOOL)read:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid;
|
|
34
|
+
- (BOOL)write:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid data:(NSData*) data withoutResponse:(BOOL)withoutResponse;
|
|
35
|
+
- (BOOL)notify:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid on:(BOOL)on;
|
|
36
|
+
- (BOOL)discoverDescriptors:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid;
|
|
37
|
+
- (BOOL)readValue:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid descriptor:(NSString*) descriptorUuid;
|
|
38
|
+
- (BOOL)writeValue:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid descriptor:(NSString*) descriptorUuid data:(NSData*) data;
|
|
39
|
+
- (BOOL)readHandle:(NSString*) uuid handle:(NSNumber*) handle;
|
|
40
|
+
- (BOOL)writeHandle:(NSString*) uuid handle:(NSNumber*) handle data:(NSData*) data;
|
|
41
|
+
@end
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ble_manager.mm
|
|
3
|
+
// noble-mac-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Georg Vienna on 28.08.18.
|
|
6
|
+
//
|
|
7
|
+
#include "ble_manager.h"
|
|
8
|
+
|
|
9
|
+
#import <Foundation/Foundation.h>
|
|
10
|
+
|
|
11
|
+
#include "objc_cpp.h"
|
|
12
|
+
|
|
13
|
+
@implementation BLEManager
|
|
14
|
+
- (instancetype)init: (const Napi::Value&) receiver with: (const Napi::Function&) callback {
|
|
15
|
+
if (self = [super init]) {
|
|
16
|
+
pendingRead = false;
|
|
17
|
+
// wrap cb before creating the CentralManager as it may call didUpdateState immediately
|
|
18
|
+
self->emit.Wrap(receiver, callback);
|
|
19
|
+
self.dispatchQueue = dispatch_queue_create("CBqueue", 0);
|
|
20
|
+
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:self.dispatchQueue];
|
|
21
|
+
self.peripherals = [NSMutableDictionary dictionaryWithCapacity:10];
|
|
22
|
+
}
|
|
23
|
+
return self;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
|
|
27
|
+
auto state = stateToString(central.state);
|
|
28
|
+
emit.RadioState(state);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
- (void)scan: (NSArray<NSString*> *)serviceUUIDs allowDuplicates: (BOOL)allowDuplicates {
|
|
32
|
+
NSMutableArray* advServicesUuid = [NSMutableArray arrayWithCapacity:[serviceUUIDs count]];
|
|
33
|
+
[serviceUUIDs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
|
34
|
+
[advServicesUuid addObject:[CBUUID UUIDWithString:obj]];
|
|
35
|
+
}];
|
|
36
|
+
NSDictionary *options = @{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithBool:allowDuplicates]};
|
|
37
|
+
[self.centralManager scanForPeripheralsWithServices:advServicesUuid options:options];
|
|
38
|
+
emit.ScanState(true);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
- (void)stopScan {
|
|
42
|
+
[self.centralManager stopScan];
|
|
43
|
+
emit.ScanState(false);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
|
|
47
|
+
std::string uuid = getUuid(peripheral);
|
|
48
|
+
|
|
49
|
+
Peripheral p;
|
|
50
|
+
p.address = getAddress(uuid, &p.addressType);
|
|
51
|
+
IF(NSNumber*, connect, [advertisementData objectForKey:CBAdvertisementDataIsConnectable]) {
|
|
52
|
+
p.connectable = [connect boolValue];
|
|
53
|
+
}
|
|
54
|
+
IF(NSString*, dataLocalName, [advertisementData objectForKey:CBAdvertisementDataLocalNameKey]) {
|
|
55
|
+
p.name = std::make_pair([dataLocalName UTF8String], true);
|
|
56
|
+
}
|
|
57
|
+
if(!std::get<1>(p.name)) {
|
|
58
|
+
IF(NSString*, name, [peripheral name]) {
|
|
59
|
+
p.name = std::make_pair([name UTF8String], true);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
IF(NSNumber*, txLevel, [advertisementData objectForKey:CBAdvertisementDataTxPowerLevelKey]) {
|
|
63
|
+
p.txPowerLevel = std::make_pair([txLevel intValue], true);
|
|
64
|
+
}
|
|
65
|
+
IF(NSData*, data, [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey]) {
|
|
66
|
+
const UInt8* bytes = (UInt8 *)[data bytes];
|
|
67
|
+
std::get<0>(p.manufacturerData).assign(bytes, bytes+[data length]);
|
|
68
|
+
std::get<1>(p.manufacturerData) = true;
|
|
69
|
+
}
|
|
70
|
+
IF(NSDictionary*, dictionary, [advertisementData objectForKey:CBAdvertisementDataServiceDataKey]) {
|
|
71
|
+
for (CBUUID* key in dictionary) {
|
|
72
|
+
IF(NSData*, value, dictionary[key]) {
|
|
73
|
+
auto serviceUuid = [[key UUIDString] UTF8String];
|
|
74
|
+
Data sData;
|
|
75
|
+
const UInt8* bytes = (UInt8 *)[value bytes];
|
|
76
|
+
sData.assign(bytes, bytes+[value length]);
|
|
77
|
+
std::get<0>(p.serviceData).push_back(std::make_pair(serviceUuid, sData));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
std::get<1>(p.serviceData) = true;
|
|
81
|
+
}
|
|
82
|
+
IF(NSArray*, services, [advertisementData objectForKey:CBAdvertisementDataServiceUUIDsKey]) {
|
|
83
|
+
for (CBUUID* service in services) {
|
|
84
|
+
std::get<0>(p.serviceUuids).push_back([[service UUIDString] UTF8String]);
|
|
85
|
+
}
|
|
86
|
+
std::get<1>(p.serviceUuids) = true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
int rssi = [RSSI intValue];
|
|
90
|
+
emit.Scan(uuid, rssi, p);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
- (BOOL)connect:(NSString*) uuid {
|
|
94
|
+
CBPeripheral *peripheral = [self.peripherals objectForKey:uuid];
|
|
95
|
+
if(!peripheral) {
|
|
96
|
+
NSArray* peripherals = [self.centralManager retrievePeripheralsWithIdentifiers:@[[[NSUUID alloc] initWithUUIDString:uuid]]];
|
|
97
|
+
peripheral = [peripherals firstObject];
|
|
98
|
+
if(peripheral) {
|
|
99
|
+
peripheral.delegate = self;
|
|
100
|
+
[self.peripherals setObject:peripheral forKey:uuid];
|
|
101
|
+
} else {
|
|
102
|
+
return NO;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
NSDictionary* options = @{CBConnectPeripheralOptionNotifyOnDisconnectionKey: [NSNumber numberWithBool:YES]};
|
|
106
|
+
[self.centralManager connectPeripheral:peripheral options:options];
|
|
107
|
+
return YES;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
|
|
111
|
+
std::string uuid = getUuid(peripheral);
|
|
112
|
+
emit.Connected(uuid, "");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
- (void) centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
|
|
116
|
+
[self.peripherals removeObjectForKey:getNSUuid(peripheral)];
|
|
117
|
+
std::string uuid = getUuid(peripheral);
|
|
118
|
+
emit.Connected(uuid, "connection failed");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
- (BOOL)disconnect:(NSString*) uuid {
|
|
122
|
+
IF(CBPeripheral*, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
123
|
+
[self.centralManager cancelPeripheralConnection:peripheral];
|
|
124
|
+
return YES;
|
|
125
|
+
}
|
|
126
|
+
return NO;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
-(void) centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
|
|
130
|
+
std::string uuid = getUuid(peripheral);
|
|
131
|
+
[self.peripherals removeObjectForKey:getNSUuid(peripheral)];
|
|
132
|
+
emit.Disconnected(uuid);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
- (BOOL)updateRSSI:(NSString*) uuid {
|
|
136
|
+
IF(CBPeripheral*, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
137
|
+
[peripheral readRSSI];
|
|
138
|
+
return YES;
|
|
139
|
+
}
|
|
140
|
+
return NO;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error {
|
|
144
|
+
std::string uuid = getUuid(peripheral);
|
|
145
|
+
NSNumber* rssi = peripheral.RSSI;
|
|
146
|
+
if(!error && rssi) {
|
|
147
|
+
emit.RSSI(uuid, [rssi longValue]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#pragma mark - Services
|
|
152
|
+
|
|
153
|
+
-(BOOL) discoverServices:(NSString*) uuid serviceUuids:(NSArray<NSString*>*) services {
|
|
154
|
+
IF(CBPeripheral*, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
155
|
+
NSMutableArray* servicesUuid = nil;
|
|
156
|
+
if(services) {
|
|
157
|
+
servicesUuid = [NSMutableArray arrayWithCapacity:[services count]];
|
|
158
|
+
[services enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
|
159
|
+
[servicesUuid addObject:[CBUUID UUIDWithString:obj]];
|
|
160
|
+
}];
|
|
161
|
+
}
|
|
162
|
+
[peripheral discoverServices:servicesUuid];
|
|
163
|
+
return YES;
|
|
164
|
+
}
|
|
165
|
+
return NO;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
- (void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
|
|
169
|
+
std::string uuid = getUuid(peripheral);
|
|
170
|
+
std::vector<std::string> services = getServices(peripheral.services);
|
|
171
|
+
emit.ServicesDiscovered(uuid, services);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
- (BOOL)discoverIncludedServices:(NSString*) uuid forService:(NSString*) serviceUuid services:(NSArray<NSString*>*) serviceUuids {
|
|
175
|
+
IF(CBPeripheral*, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
176
|
+
IF(CBService*, service, [self getService:peripheral service:serviceUuid]) {
|
|
177
|
+
NSMutableArray* includedServices = nil;
|
|
178
|
+
if(serviceUuids) {
|
|
179
|
+
includedServices = [NSMutableArray arrayWithCapacity:[serviceUuids count]];
|
|
180
|
+
[serviceUuids enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
|
181
|
+
[includedServices addObject:[CBUUID UUIDWithString:obj]];
|
|
182
|
+
}];
|
|
183
|
+
}
|
|
184
|
+
[peripheral discoverIncludedServices:includedServices forService:service];
|
|
185
|
+
return YES;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return NO;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(NSError *)error {
|
|
192
|
+
std::string uuid = getUuid(peripheral);
|
|
193
|
+
auto serviceUuid = [[service.UUID UUIDString] UTF8String];
|
|
194
|
+
std::vector<std::string> services = getServices(service.includedServices);
|
|
195
|
+
emit.IncludedServicesDiscovered(uuid, serviceUuid, services);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
#pragma mark - Characteristics
|
|
199
|
+
|
|
200
|
+
- (BOOL)discoverCharacteristics:(NSString*) uuid forService:(NSString*) serviceUuid characteristics:(NSArray<NSString*>*) characteristics {
|
|
201
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
202
|
+
IF(CBService*, service, [self getService:peripheral service:serviceUuid]) {
|
|
203
|
+
NSMutableArray* characteristicsUuid = nil;
|
|
204
|
+
if(characteristics) {
|
|
205
|
+
characteristicsUuid = [NSMutableArray arrayWithCapacity:[characteristics count]];
|
|
206
|
+
[characteristics enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
|
207
|
+
[characteristicsUuid addObject:[CBUUID UUIDWithString:obj]];
|
|
208
|
+
}];
|
|
209
|
+
}
|
|
210
|
+
[peripheral discoverCharacteristics:characteristicsUuid forService:service];
|
|
211
|
+
return YES;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return NO;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
-(void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
|
|
218
|
+
std::string uuid = getUuid(peripheral);
|
|
219
|
+
std::string serviceUuid = std::string([service.UUID.UUIDString UTF8String]);
|
|
220
|
+
auto characteristics = getCharacteristics(service.characteristics);
|
|
221
|
+
emit.CharacteristicsDiscovered(uuid, serviceUuid, characteristics);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
- (BOOL)read:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid {
|
|
225
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
226
|
+
IF(CBCharacteristic*, characteristic, [self getCharacteristic:peripheral service:serviceUuid characteristic:characteristicUuid]) {
|
|
227
|
+
pendingRead = true;
|
|
228
|
+
[peripheral readValueForCharacteristic:characteristic];
|
|
229
|
+
return YES;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return NO;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
|
|
236
|
+
std::string uuid = getUuid(peripheral);
|
|
237
|
+
std::string serviceUuid = [characteristic.service.UUID.UUIDString UTF8String];
|
|
238
|
+
std::string characteristicUuid = [characteristic.UUID.UUIDString UTF8String];
|
|
239
|
+
const UInt8* bytes = (UInt8 *)[characteristic.value bytes];
|
|
240
|
+
Data data;
|
|
241
|
+
data.assign(bytes, bytes+[characteristic.value length]);
|
|
242
|
+
bool isNotification = !pendingRead && characteristic.isNotifying;
|
|
243
|
+
pendingRead = false;
|
|
244
|
+
emit.Read(uuid, serviceUuid, characteristicUuid, data, isNotification);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
- (BOOL)write:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid data:(NSData*) data withoutResponse:(BOOL)withoutResponse {
|
|
248
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
249
|
+
IF(CBCharacteristic*, characteristic, [self getCharacteristic:peripheral service:serviceUuid characteristic:characteristicUuid]) {
|
|
250
|
+
CBCharacteristicWriteType type = withoutResponse ? CBCharacteristicWriteWithoutResponse : CBCharacteristicWriteWithResponse;
|
|
251
|
+
[peripheral writeValue:data forCharacteristic:characteristic type:type];
|
|
252
|
+
if (withoutResponse) {
|
|
253
|
+
emit.Write([uuid UTF8String], [serviceUuid UTF8String], [characteristicUuid UTF8String]);
|
|
254
|
+
}
|
|
255
|
+
return YES;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return NO;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
-(void) peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
|
|
262
|
+
std::string uuid = getUuid(peripheral);
|
|
263
|
+
std::string serviceUuid = [characteristic.service.UUID.UUIDString UTF8String];
|
|
264
|
+
std::string characteristicUuid = [characteristic.UUID.UUIDString UTF8String];
|
|
265
|
+
emit.Write(uuid, serviceUuid, characteristicUuid);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
- (BOOL)notify:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid on:(BOOL)on {
|
|
269
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
270
|
+
IF(CBCharacteristic*, characteristic, [self getCharacteristic:peripheral service:serviceUuid characteristic:characteristicUuid]) {
|
|
271
|
+
[peripheral setNotifyValue:on forCharacteristic:characteristic];
|
|
272
|
+
return YES;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return NO;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
|
|
279
|
+
std::string uuid = getUuid(peripheral);
|
|
280
|
+
std::string serviceUuid = [characteristic.service.UUID.UUIDString UTF8String];
|
|
281
|
+
std::string characteristicUuid = [characteristic.UUID.UUIDString UTF8String];
|
|
282
|
+
emit.Notify(uuid, serviceUuid, characteristicUuid, characteristic.isNotifying);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
#pragma mark - Descriptors
|
|
286
|
+
|
|
287
|
+
- (BOOL)discoverDescriptors:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid {
|
|
288
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
289
|
+
IF(CBCharacteristic*, characteristic, [self getCharacteristic:peripheral service:serviceUuid characteristic:characteristicUuid]) {
|
|
290
|
+
[peripheral discoverDescriptorsForCharacteristic:characteristic];
|
|
291
|
+
return YES;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return NO;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
|
|
298
|
+
std::string uuid = getUuid(peripheral);
|
|
299
|
+
std::string serviceUuid = [characteristic.service.UUID.UUIDString UTF8String];
|
|
300
|
+
std::string characteristicUuid = [characteristic.UUID.UUIDString UTF8String];
|
|
301
|
+
std::vector<std::string> descriptors = getDescriptors(characteristic.descriptors);
|
|
302
|
+
emit.DescriptorsDiscovered(uuid, serviceUuid, characteristicUuid, descriptors);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
- (BOOL)readValue:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid descriptor:(NSString*) descriptorUuid {
|
|
306
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
307
|
+
IF(CBDescriptor*, descriptor, [self getDescriptor:peripheral service:serviceUuid characteristic:characteristicUuid descriptor:descriptorUuid]) {
|
|
308
|
+
[peripheral readValueForDescriptor:descriptor];
|
|
309
|
+
return YES;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return NO;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error {
|
|
316
|
+
std::string uuid = getUuid(peripheral);
|
|
317
|
+
std::string serviceUuid = [descriptor.characteristic.service.UUID.UUIDString UTF8String];
|
|
318
|
+
std::string characteristicUuid = [descriptor.characteristic.UUID.UUIDString UTF8String];
|
|
319
|
+
std::string descriptorUuid = [descriptor.UUID.UUIDString UTF8String];
|
|
320
|
+
const UInt8* bytes = (UInt8 *)[descriptor.value bytes];
|
|
321
|
+
Data data;
|
|
322
|
+
data.assign(bytes, bytes+[descriptor.value length]);
|
|
323
|
+
IF(NSNumber*, handle, [self getDescriptorHandle:descriptor]) {
|
|
324
|
+
emit.ReadHandle(uuid, [handle intValue], data);
|
|
325
|
+
}
|
|
326
|
+
emit.ReadValue(uuid, serviceUuid, characteristicUuid, descriptorUuid, data);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
- (BOOL)writeValue:(NSString*) uuid service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid descriptor:(NSString*) descriptorUuid data:(NSData*) data {
|
|
330
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
331
|
+
IF(CBDescriptor*, descriptor, [self getDescriptor:peripheral service:serviceUuid characteristic:characteristicUuid descriptor:descriptorUuid]) {
|
|
332
|
+
[peripheral writeValue:data forDescriptor:descriptor];
|
|
333
|
+
return YES;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return NO;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error {
|
|
340
|
+
std::string uuid = getUuid(peripheral);
|
|
341
|
+
std::string serviceUuid = [descriptor.characteristic.service.UUID.UUIDString UTF8String];
|
|
342
|
+
std::string characteristicUuid = [descriptor.characteristic.UUID.UUIDString UTF8String];
|
|
343
|
+
std::string descriptorUuid = [descriptor.UUID.UUIDString UTF8String];
|
|
344
|
+
IF(NSNumber*, handle, [self getDescriptorHandle:descriptor]) {
|
|
345
|
+
emit.WriteHandle(uuid, [handle intValue]);
|
|
346
|
+
}
|
|
347
|
+
emit.WriteValue(uuid, serviceUuid, characteristicUuid, descriptorUuid);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
- (BOOL)readHandle:(NSString*) uuid handle:(NSNumber*) handle {
|
|
351
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
352
|
+
IF(CBDescriptor*, descriptor, [self getDescriptor:peripheral ByHandle:handle]) {
|
|
353
|
+
[peripheral readValueForDescriptor:descriptor];
|
|
354
|
+
return YES;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return NO;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
- (BOOL)writeHandle:(NSString*) uuid handle:(NSNumber*) handle data:(NSData*) data {
|
|
361
|
+
IF(CBPeripheral *, peripheral, [self.peripherals objectForKey:uuid]) {
|
|
362
|
+
IF(CBDescriptor*, descriptor, [self getDescriptor:peripheral ByHandle:handle]) {
|
|
363
|
+
[peripheral writeValue:data forDescriptor:descriptor];
|
|
364
|
+
return YES;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return NO;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
#pragma mark - Accessor
|
|
371
|
+
|
|
372
|
+
-(CBService*)getService:(CBPeripheral*) peripheral service:(NSString*) serviceUuid {
|
|
373
|
+
if(peripheral && peripheral.services) {
|
|
374
|
+
for(CBService* service in peripheral.services) {
|
|
375
|
+
if([service.UUID isEqualTo:[CBUUID UUIDWithString:serviceUuid]]) {
|
|
376
|
+
return service;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return nil;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
-(CBCharacteristic*)getCharacteristic:(CBPeripheral*) peripheral service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid {
|
|
384
|
+
CBService* service = [self getService:peripheral service:serviceUuid];
|
|
385
|
+
if(service && service.characteristics) {
|
|
386
|
+
for(CBCharacteristic* characteristic in service.characteristics) {
|
|
387
|
+
if([characteristic.UUID isEqualTo:[CBUUID UUIDWithString:characteristicUuid]]) {
|
|
388
|
+
return characteristic;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return nil;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
-(CBDescriptor*)getDescriptor:(CBPeripheral*) peripheral service:(NSString*) serviceUuid characteristic:(NSString*) characteristicUuid descriptor:(NSString*) descriptorUuid {
|
|
396
|
+
CBCharacteristic* characteristic = [self getCharacteristic:peripheral service:serviceUuid characteristic:characteristicUuid];
|
|
397
|
+
if(characteristic && characteristic.descriptors) {
|
|
398
|
+
for(CBDescriptor* descriptor in characteristic.descriptors) {
|
|
399
|
+
if([descriptor.UUID isEqualTo:[CBUUID UUIDWithString:descriptorUuid]]) {
|
|
400
|
+
return descriptor;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return nil;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
-(NSNumber*)getDescriptorHandle:(CBDescriptor*) descriptor {
|
|
408
|
+
// use KVC to get the private handle property
|
|
409
|
+
id handle = [descriptor valueForKey:@"handle"];
|
|
410
|
+
if([handle isKindOfClass:[NSNumber class]]) {
|
|
411
|
+
return handle;
|
|
412
|
+
}
|
|
413
|
+
return nil;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
-(CBDescriptor*)getDescriptor:(CBPeripheral*) peripheral ByHandle:(NSNumber*) handle {
|
|
417
|
+
if(peripheral && peripheral.services) {
|
|
418
|
+
for(CBService* service in peripheral.services) {
|
|
419
|
+
if(service.characteristics) {
|
|
420
|
+
for(CBCharacteristic* characteristic in service.characteristics) {
|
|
421
|
+
if(characteristic.descriptors) {
|
|
422
|
+
for(CBDescriptor* descriptor in characteristic.descriptors) {
|
|
423
|
+
if([handle isEqualTo:[self getDescriptorHandle:descriptor]]) {
|
|
424
|
+
return descriptor;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return nil;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
@end
|