@stoprocent/bleno 0.7.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 (77) hide show
  1. package/.jshintrc +5 -0
  2. package/LICENSE +20 -0
  3. package/README.md +409 -0
  4. package/binding.gyp +17 -0
  5. package/examples/battery-service/README.md +14 -0
  6. package/examples/battery-service/battery-level-characteristic.js +45 -0
  7. package/examples/battery-service/battery-service.js +16 -0
  8. package/examples/battery-service/main.js +28 -0
  9. package/examples/battery-service/package-lock.json +1314 -0
  10. package/examples/battery-service/package.json +20 -0
  11. package/examples/blink1/README.md +44 -0
  12. package/examples/blink1/blink1-fade-rgb-characteristic.js +42 -0
  13. package/examples/blink1/blink1-rgb-characteristic.js +38 -0
  14. package/examples/blink1/blink1-service.js +19 -0
  15. package/examples/blink1/device-information-service.js +19 -0
  16. package/examples/blink1/hardware-revision-characteristic.js +32 -0
  17. package/examples/blink1/main.js +32 -0
  18. package/examples/blink1/serial-number-characteristic.js +21 -0
  19. package/examples/echo/characteristic.js +45 -0
  20. package/examples/echo/main.js +33 -0
  21. package/examples/pizza/README.md +16 -0
  22. package/examples/pizza/peripheral.js +57 -0
  23. package/examples/pizza/pizza-bake-characteristic.js +40 -0
  24. package/examples/pizza/pizza-crust-characteristic.js +52 -0
  25. package/examples/pizza/pizza-service.js +20 -0
  26. package/examples/pizza/pizza-toppings-characteristic.js +41 -0
  27. package/examples/pizza/pizza.js +58 -0
  28. package/examples/uart/main.js +23 -0
  29. package/index.d.ts +153 -0
  30. package/index.js +1 -0
  31. package/lib/bleno.js +231 -0
  32. package/lib/characteristic.js +91 -0
  33. package/lib/descriptor.js +17 -0
  34. package/lib/hci-socket/acl-stream.js +37 -0
  35. package/lib/hci-socket/bindings.js +219 -0
  36. package/lib/hci-socket/crypto.js +74 -0
  37. package/lib/hci-socket/gap.js +212 -0
  38. package/lib/hci-socket/gatt.js +1028 -0
  39. package/lib/hci-socket/hci-status.json +67 -0
  40. package/lib/hci-socket/hci.js +796 -0
  41. package/lib/hci-socket/mgmt.js +89 -0
  42. package/lib/hci-socket/smp.js +160 -0
  43. package/lib/hci-socket/vs.js +156 -0
  44. package/lib/mac/binding.gyp +39 -0
  45. package/lib/mac/bindings.js +12 -0
  46. package/lib/mac/src/ble_peripheral_manager.h +32 -0
  47. package/lib/mac/src/ble_peripheral_manager.mm +241 -0
  48. package/lib/mac/src/bleno_mac.h +26 -0
  49. package/lib/mac/src/bleno_mac.mm +167 -0
  50. package/lib/mac/src/callbacks.h +76 -0
  51. package/lib/mac/src/callbacks.mm +124 -0
  52. package/lib/mac/src/napi_objc.h +30 -0
  53. package/lib/mac/src/napi_objc.mm +286 -0
  54. package/lib/mac/src/noble_mac.h +34 -0
  55. package/lib/mac/src/noble_mac.mm +260 -0
  56. package/lib/mac/src/objc_cpp.h +27 -0
  57. package/lib/mac/src/objc_cpp.mm +144 -0
  58. package/lib/mac/src/peripheral.h +23 -0
  59. package/lib/primary-service.js +19 -0
  60. package/lib/resolve-bindings.js +19 -0
  61. package/lib/uuid-util.js +7 -0
  62. package/package.json +77 -0
  63. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  64. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  65. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  66. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  67. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  68. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  69. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  70. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  71. package/prebuilds/win32-ia32/node.napi.node +0 -0
  72. package/prebuilds/win32-x64/node.napi.node +0 -0
  73. package/test/characteristic.test.js +174 -0
  74. package/test/descriptor.test.js +46 -0
  75. package/test/mocha.setup.js +0 -0
  76. package/with-bindings.js +5 -0
  77. package/with-custom-binding.js +6 -0
@@ -0,0 +1,241 @@
1
+ //
2
+ // ble_peripheral_manager.mm
3
+ // bleno-mac-native
4
+ //
5
+ // Created by Georg Vienna on 28.08.18.
6
+ //
7
+ #include "ble_peripheral_manager.h"
8
+
9
+ #include <dispatch/dispatch.h>
10
+
11
+ #include "objc_cpp.h"
12
+
13
+ @interface BLEPeripheralManager () <CBPeripheralManagerDelegate>
14
+
15
+ @property (nonatomic, strong) dispatch_queue_t queue;
16
+ @property (nonatomic, strong) CBPeripheralManager *peripheralManager;
17
+
18
+ @end
19
+
20
+ @implementation BLEPeripheralManager
21
+
22
+ - (instancetype)init {
23
+ if (self = [super init]) {
24
+ NSLog(@"-[BLEPeripheralManager init]");
25
+
26
+ self.queue = dispatch_queue_create("CBqueue", 0);
27
+ }
28
+ return self;
29
+ }
30
+
31
+ #pragma mark - API
32
+
33
+ - (void)start {
34
+ self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self
35
+ queue:self.queue];
36
+ }
37
+
38
+ - (void)startAdvertising:(nonnull NSString *)name serviceUUIDs:(nonnull NSArray<CBUUID *> *)serviceUUIDs {
39
+ NSLog(@"startAdvertising:%@ serviceUUIDs:%@", name, serviceUUIDs);
40
+ if (self.peripheralManager.isAdvertising) {
41
+ return;
42
+ }
43
+
44
+ [self.peripheralManager startAdvertising:@{
45
+ CBAdvertisementDataLocalNameKey: name,
46
+ CBAdvertisementDataServiceUUIDsKey: serviceUUIDs,
47
+ }];
48
+ }
49
+
50
+ - (void)startAdvertisingIBeacon:(NSData *)data {
51
+ NSLog(@"startAdvertisingIBeacon:%@", data);
52
+ }
53
+
54
+ - (void)startAdvertisingWithEIRData:(NSData *)data {
55
+ NSLog(@"startAdvertisingWithEIRData:%@", data);
56
+
57
+ if (self.peripheralManager.isAdvertising) {
58
+ return;
59
+ }
60
+ }
61
+
62
+ - (void)stopAdvertising {
63
+ NSLog(@"stopAdvertising");
64
+
65
+ [self.peripheralManager stopAdvertising];
66
+ }
67
+
68
+ - (void)setServices:(NSArray<CBMutableService *> *)services {
69
+ for (CBMutableService *service in services) {
70
+ [self.peripheralManager addService:service];
71
+ }
72
+ }
73
+
74
+ - (void)disconnect {
75
+ NSLog(@"disconnect");
76
+
77
+ // throw new Error('disconnect is not supported on OS X!');
78
+ }
79
+
80
+ - (void)updateRssi {
81
+ NSLog(@"updateRssi");
82
+ }
83
+
84
+ #pragma mark - CBPeripheralManagerDelegate
85
+
86
+ - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
87
+ NSString *string = @"Unknown state";
88
+
89
+ switch(peripheral.state) {
90
+ case CBManagerStatePoweredOff:
91
+ string = @"CoreBluetooth BLE hardware is powered off.";
92
+ break;
93
+
94
+ case CBManagerStatePoweredOn:
95
+ string = @"CoreBluetooth BLE hardware is powered on and ready.";
96
+ break;
97
+
98
+ case CBManagerStateUnauthorized:
99
+ string = @"CoreBluetooth BLE state is unauthorized.";
100
+ break;
101
+
102
+ case CBManagerStateUnknown:
103
+ string = @"CoreBluetooth BLE state is unknown.";
104
+ break;
105
+
106
+ case CBManagerStateUnsupported:
107
+ string = @"CoreBluetooth BLE hardware is unsupported on this platform.";
108
+ break;
109
+
110
+ default:
111
+ break;
112
+ }
113
+
114
+ NSLog(@"%@", string);
115
+
116
+ auto state = StringFromCBPeripheralState(peripheral.state);
117
+ emit.StateChange(state);
118
+ }
119
+
120
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral willRestoreState:(NSDictionary<NSString *, id> *)dict {
121
+ NSLog(@"willRestoreState");
122
+ }
123
+
124
+ - (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(nullable NSError *)error {
125
+ NSLog(@"peripheralManagerDidStartAdvertising: %@", peripheral.description);
126
+ if (error) {
127
+ NSLog(@"Error advertising: %@", [error localizedDescription]);
128
+ }
129
+
130
+ emit.AdvertisingStart();
131
+ }
132
+
133
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(nullable NSError *)error {
134
+ NSLog(@"peripheralManagerDidAddService: %@ %@", service, error);
135
+ if (error) {
136
+ NSLog(@"Error publishing service: %@", [error localizedDescription]);
137
+ }
138
+
139
+ emit.ServicesSet();
140
+ }
141
+
142
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBMutableCharacteristic *)characteristic {
143
+ NSLog(@"didSubscribeToCharacteristic");
144
+
145
+ CBUUID *uuid = characteristic.UUID;
146
+
147
+ for (auto it = emitters.begin(); it != emitters.end(); ++it) {
148
+ if ([it->first isEqual:uuid]) {
149
+ auto cb = [peripheral, central, characteristic](NSData *data) {
150
+ NSLog(@"subscription note: %@ %@", data, NSStringFromClass(characteristic.class));
151
+
152
+ [peripheral updateValue:data
153
+ forCharacteristic:characteristic
154
+ onSubscribedCentrals:@[central]];
155
+ };
156
+
157
+ it->second.Subscribe(central.maximumUpdateValueLength, cb);
158
+
159
+ if ((characteristic.properties & CBCharacteristicPropertyNotify) == CBCharacteristicPropertyNotify) {
160
+
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {
167
+ NSLog(@"didUnsubscribeFromCharacteristic");
168
+
169
+ CBUUID *uuid = characteristic.UUID;
170
+
171
+ for (auto it = emitters.begin(); it != emitters.end(); ++it) {
172
+ if ([it->first isEqual:uuid]) {
173
+ it->second.Unsubscribe();
174
+ }
175
+ }
176
+ }
177
+
178
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
179
+ NSLog(@"didReceiveReadRequest: %@ %@", request.central, request.characteristic.UUID);
180
+
181
+ CBCharacteristic *characteristic = request.characteristic;
182
+ CBUUID *uuid = characteristic.UUID;
183
+
184
+ for (auto it = emitters.begin(); it != emitters.end(); ++it) {
185
+ if ([it->first isEqual:uuid]) {
186
+ auto cb = [peripheral, request](int result, NSData *data) {
187
+ request.value = data;
188
+
189
+ [peripheral respondToRequest:request
190
+ withResult:(CBATTError)result];
191
+ };
192
+
193
+ it->second.ReadRequest(request.offset, cb);
194
+ }
195
+ }
196
+ }
197
+
198
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests {
199
+ for (CBATTRequest *request in requests) {
200
+ NSLog(@"didReceiveWriteRequest: %@ %@", request.central, request.characteristic.UUID);
201
+
202
+ CBCharacteristic *characteristic = request.characteristic;
203
+ CBUUID *uuid = characteristic.UUID;
204
+
205
+ for (auto it = emitters.begin(); it != emitters.end(); ++it) {
206
+ if ([it->first isEqual:uuid]) {
207
+ bool sendResponse = (request.characteristic.properties & CBCharacteristicPropertyWrite) == CBCharacteristicPropertyWrite;
208
+
209
+ auto cb = [peripheral, request, sendResponse](int result) {
210
+ if (sendResponse) {
211
+ [peripheral respondToRequest:request
212
+ withResult:(CBATTError)result];
213
+ }
214
+ };
215
+
216
+ it->second.WriteRequest(request.value,
217
+ request.offset,
218
+ !sendResponse,
219
+ cb);
220
+ }
221
+ }
222
+ }
223
+ }
224
+
225
+ - (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral {
226
+ NSLog(@"peripheralManagerIsReadyToUpdateSubscribers");
227
+ }
228
+
229
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral didPublishL2CAPChannel:(CBL2CAPPSM)PSM error:(nullable NSError *)error {
230
+ NSLog(@"didPublishL2CAPChannel");
231
+ }
232
+
233
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral didUnpublishL2CAPChannel:(CBL2CAPPSM)PSM error:(nullable NSError *)error {
234
+ NSLog(@"didUnpublishL2CAPChannel");
235
+ }
236
+
237
+ - (void)peripheralManager:(CBPeripheralManager *)peripheral didOpenL2CAPChannel:(nullable CBL2CAPChannel *)channel error:(nullable NSError *)error {
238
+ NSLog(@"didOpenL2CAPChannel");
239
+ }
240
+
241
+ @end
@@ -0,0 +1,26 @@
1
+ #pragma once
2
+
3
+ #include <napi.h>
4
+
5
+ #include "ble_peripheral_manager.h"
6
+
7
+ class BlenoMac : public Napi::ObjectWrap<BlenoMac>
8
+ {
9
+ public:
10
+ BlenoMac(const Napi::CallbackInfo&);
11
+ Napi::Value Init(const Napi::CallbackInfo&);
12
+ Napi::Value CleanUp(const Napi::CallbackInfo&);
13
+
14
+ Napi::Value StartAdvertising(const Napi::CallbackInfo&);
15
+ Napi::Value StartAdvertisingIBeacon(const Napi::CallbackInfo&);
16
+ Napi::Value StartAdvertisingWithEIRData(const Napi::CallbackInfo&);
17
+ Napi::Value StopAdvertising(const Napi::CallbackInfo&);
18
+ Napi::Value SetServices(const Napi::CallbackInfo&);
19
+ Napi::Value Disconnect(const Napi::CallbackInfo&);
20
+ Napi::Value UpdateRssi(const Napi::CallbackInfo&);
21
+
22
+ static Napi::Function GetClass(Napi::Env);
23
+
24
+ private:
25
+ BLEPeripheralManager *peripheralManager;
26
+ };
@@ -0,0 +1,167 @@
1
+ //
2
+ // bleno_mac.mm
3
+ // bleno-mac-native
4
+ //
5
+ // Created by Georg Vienna on 28.08.18.
6
+ //
7
+ #include "bleno_mac.h"
8
+
9
+ #include "napi_objc.h"
10
+
11
+ #define THROW(msg) \
12
+ Napi::TypeError::New(info.Env(), msg).ThrowAsJavaScriptException(); \
13
+ return Napi::Value();
14
+
15
+ #define ARG1(type1) \
16
+ if (!info[0].Is##type1()) { \
17
+ THROW("There should be one argument: (" #type1 ")") \
18
+ }
19
+
20
+ #define ARG2(type1, type2) \
21
+ if (!info[0].Is##type1() || !info[1].Is##type2()) { \
22
+ THROW("There should be 2 arguments: (" #type1 ", " #type2 ")"); \
23
+ }
24
+
25
+ #define ARG3(type1, type2, type3) \
26
+ if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3()) { \
27
+ THROW("There should be 3 arguments: (" #type1 ", " #type2 ", " #type3 ")"); \
28
+ }
29
+
30
+ #define ARG4(type1, type2, type3, type4) \
31
+ if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4()) { \
32
+ THROW("There should be 4 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ")"); \
33
+ }
34
+
35
+ #define ARG5(type1, type2, type3, type4, type5) \
36
+ if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4() || !info[4].Is##type5()) { \
37
+ THROW("There should be 5 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ", " #type5 ")"); \
38
+ }
39
+
40
+ #define CHECK_MANAGER() \
41
+ if(!peripheralManager) { \
42
+ THROW("BLEManager has already been cleaned up"); \
43
+ }
44
+
45
+ BlenoMac::BlenoMac(const Napi::CallbackInfo& info) : ObjectWrap(info) {
46
+ }
47
+
48
+ Napi::Value BlenoMac::Init(const Napi::CallbackInfo& info) {
49
+ NSLog(@"BlenoMac::Init");
50
+
51
+ Napi::Function emit = info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();
52
+ peripheralManager = [BLEPeripheralManager new];
53
+ peripheralManager->emit.Wrap(info.This(), emit);
54
+ [peripheralManager start];
55
+ return Napi::Value();
56
+ }
57
+
58
+ Napi::Value BlenoMac::CleanUp(const Napi::CallbackInfo& info) {
59
+ CHECK_MANAGER()
60
+ CFRelease((__bridge CFTypeRef)peripheralManager);
61
+ peripheralManager = nil;
62
+ return Napi::Value();
63
+ }
64
+
65
+ // startAdvertising(name, undashedServiceUuids)
66
+ Napi::Value BlenoMac::StartAdvertising(const Napi::CallbackInfo& info) {
67
+ NSLog(@"BlenoMac::StartAdvertising");
68
+
69
+ CHECK_MANAGER();
70
+ ARG2(String, Array);
71
+
72
+ auto name = napiToString(info[0].As<Napi::String>());
73
+ NSArray *array = getCBUuidArray(info[1]);
74
+
75
+ [peripheralManager startAdvertising:name
76
+ serviceUUIDs:array];
77
+
78
+ return Napi::Value();
79
+ }
80
+
81
+ // startAdvertisingIBeacon(iBeaconData)
82
+ Napi::Value BlenoMac::StartAdvertisingIBeacon(const Napi::CallbackInfo& info) {
83
+ NSLog(@"BlenoMac::StartAdvertisingIBeacon");
84
+
85
+ return Napi::Value();
86
+ }
87
+
88
+ // startAdvertisingWithEIRData(advertisementData, scanData)
89
+ Napi::Value BlenoMac::StartAdvertisingWithEIRData(const Napi::CallbackInfo& info) {
90
+ NSLog(@"BlenoMac::StartAdvertisingWithEIRData");
91
+
92
+ return Napi::Value();
93
+ }
94
+
95
+ // stopAdvertising()
96
+ Napi::Value BlenoMac::StopAdvertising(const Napi::CallbackInfo& info) {
97
+ NSLog(@"BlenoMac::StopAdvertising");
98
+
99
+ return Napi::Value();
100
+ }
101
+
102
+ // setServices(services)
103
+ Napi::Value BlenoMac::SetServices(const Napi::CallbackInfo& info) {
104
+ NSLog(@"BlenoMac::SetServices");
105
+
106
+ CHECK_MANAGER();
107
+ ARG1(Array);
108
+
109
+ auto array = info[0].As<Napi::Array>();
110
+
111
+ NSArray<CBMutableService *> *services = napiArrayToCBMutableServices(array);
112
+ [peripheralManager setServices:services];
113
+
114
+ auto pairs = napiArrayToUUIDEmitters(array);
115
+ std::map<CBUUID *, EmitCharacteristic> emitters;
116
+ for (auto const& x : pairs) {
117
+ EmitCharacteristic emit = EmitCharacteristic();
118
+
119
+ auto obj = x.second;
120
+ auto fn = obj.Get("emit").As<Napi::Function>();
121
+ emit.Wrap(obj, fn);
122
+
123
+ CBUUID *uuid = [CBUUID UUIDWithString:napiToUuidString(x.first)];
124
+ emitters[uuid] = emit;
125
+ }
126
+
127
+ peripheralManager->emitters = emitters;
128
+
129
+ return Napi::Value();
130
+ }
131
+
132
+ // disconnect()
133
+ Napi::Value BlenoMac::Disconnect(const Napi::CallbackInfo& info) {
134
+ NSLog(@"BlenoMac::Disconnect");
135
+
136
+ return Napi::Value();
137
+ }
138
+
139
+ // updateRssi()
140
+ Napi::Value BlenoMac::UpdateRssi(const Napi::CallbackInfo& info) {
141
+ NSLog(@"BlenoMac::UpdateRssi");
142
+
143
+ return Napi::Value();
144
+ }
145
+
146
+ Napi::Function BlenoMac::GetClass(Napi::Env env) {
147
+ return DefineClass(env, "BlenoMac", {
148
+ BlenoMac::InstanceMethod("init", &BlenoMac::Init),
149
+ BlenoMac::InstanceMethod("cleanUp", &BlenoMac::CleanUp),
150
+
151
+ BlenoMac::InstanceMethod("startAdvertising", &BlenoMac::StartAdvertising),
152
+ BlenoMac::InstanceMethod("startAdvertisingIBeacon", &BlenoMac::StartAdvertisingIBeacon),
153
+ BlenoMac::InstanceMethod("startAdvertisingWithEIRData", &BlenoMac::StartAdvertisingWithEIRData),
154
+ BlenoMac::InstanceMethod("stopAdvertising", &BlenoMac::StopAdvertising),
155
+ BlenoMac::InstanceMethod("setServices", &BlenoMac::SetServices),
156
+ BlenoMac::InstanceMethod("disconnect", &BlenoMac::Disconnect),
157
+ BlenoMac::InstanceMethod("updateRssi", &BlenoMac::UpdateRssi),
158
+ });
159
+ }
160
+
161
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
162
+ Napi::String name = Napi::String::New(env, "BlenoMac");
163
+ exports.Set(name, BlenoMac::GetClass(env));
164
+ return exports;
165
+ }
166
+
167
+ NODE_API_MODULE(addon, Init)
@@ -0,0 +1,76 @@
1
+ #pragma once
2
+
3
+ #include <napi.h>
4
+ #include "peripheral.h"
5
+
6
+ #import <Foundation/Foundation.h>
7
+
8
+ class ThreadSafeCallback;
9
+
10
+ class Emit {
11
+ public:
12
+ void Wrap(const Napi::Value& receiver, const Napi::Function& callback);
13
+
14
+ void AdvertisingStart();
15
+ void ServicesSet();
16
+
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
+ protected:
37
+ std::shared_ptr<ThreadSafeCallback> mCallback;
38
+ };
39
+
40
+ class EmitCharacteristic {
41
+ public:
42
+ void Wrap(const Napi::Value& receiver, const Napi::Function& callback);
43
+
44
+ void ReadRequest(int offset, std::function<void (int, NSData *)> completion);
45
+ void WriteRequest(NSData *data, int offset, bool ignoreResponse, std::function<void (int)> completion);
46
+ void Subscribe(int maxValueSize, std::function<void (NSData *)> completion);
47
+ void Unsubscribe();
48
+ void Notify();
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);
68
+ protected:
69
+ std::shared_ptr<ThreadSafeCallback> mCallback;
70
+
71
+ private:
72
+ Napi::Buffer<uint8_t> toBuffer(Napi::Env& env, const Data& data);
73
+ };
74
+
75
+ Napi::Buffer<uint8_t> toBufferFromNSData(Napi::Env& env, const NSData *data);
76
+ Napi::Buffer<uint8_t> toBuffer(Napi::Env& env, const Data& data);
@@ -0,0 +1,124 @@
1
+ //
2
+ // callbacks.cc
3
+ // bleno-mac-native
4
+ //
5
+ // Created by Georg Vienna on 30.08.18.
6
+ //
7
+ #include "callbacks.h"
8
+
9
+ #import <napi-thread-safe-callback.hpp>
10
+
11
+ #include "napi_objc.h"
12
+
13
+ #define _s(val) Napi::String::New(env, val)
14
+ #define _b(val) Napi::Boolean::New(env, val)
15
+ #define _n(val) Napi::Number::New(env, val)
16
+ #define _u(str) toUuid(env, str)
17
+
18
+ Napi::Buffer<uint8_t> toBufferFromNSData(Napi::Env& env, const NSData *nsdata) {
19
+ auto data = Data();
20
+ const UInt8* bytes = (UInt8 *)[nsdata bytes];
21
+ data.assign(bytes, bytes + [nsdata length]);
22
+ return toBuffer(env, data);
23
+ }
24
+
25
+ Napi::Buffer<uint8_t> toBuffer(Napi::Env& env, const Data& data) {
26
+ if (data.empty()) {
27
+ return Napi::Buffer<uint8_t>::New(env, 0);
28
+ }
29
+ return Napi::Buffer<uint8_t>::Copy(env, &data[0], data.size());
30
+ }
31
+
32
+ void Emit::Wrap(const Napi::Value& receiver, const Napi::Function& callback) {
33
+ mCallback = std::make_shared<ThreadSafeCallback>(receiver, callback);
34
+ }
35
+
36
+ void Emit::AdvertisingStart() {
37
+ mCallback->call([](Napi::Env env, std::vector<napi_value>& args) {
38
+ // emit('advertisingStart', error)
39
+ args = { _s("advertisingStart") };
40
+ });
41
+ }
42
+
43
+ void Emit::ServicesSet() {
44
+ mCallback->call([](Napi::Env env, std::vector<napi_value>& args) {
45
+ // emit('servicesSet', this._setServicesError)
46
+ args = { _s("servicesSet") };
47
+ });
48
+ }
49
+
50
+ void Emit::StateChange(const std::string& state) {
51
+ mCallback->call([state](Napi::Env env, std::vector<napi_value>& args) {
52
+ // emit('stateChange', state);
53
+ args = { _s("stateChange"), _s(state) };
54
+ });
55
+ }
56
+
57
+ void EmitCharacteristic::Wrap(const Napi::Value& receiver, const Napi::Function& callback) {
58
+ mCallback = std::make_shared<ThreadSafeCallback>(receiver, callback);
59
+ }
60
+
61
+ void EmitCharacteristic::ReadRequest(int offset, std::function<void (int, NSData *)> completion) {
62
+ mCallback->call([offset, completion](Napi::Env env, std::vector<napi_value>& args) {
63
+ // callback(result, data)
64
+ auto callable = [completion](const Napi::CallbackInfo& info){
65
+ completion(info[0].As<Napi::Number>().Int32Value(),
66
+ napiToData(info[1].As<Napi::Buffer<Byte>>()));
67
+ };
68
+ Napi::Function cb = Napi::Function::New(env, callable);
69
+
70
+ // emit('readRequest', offset, callback);
71
+ args = { _s("readRequest"), _n(offset), cb };
72
+ });
73
+ }
74
+
75
+ void EmitCharacteristic::WriteRequest(NSData *data, int offset, bool ignoreResponse, std::function<void (int)> completion) {
76
+ mCallback->call([data, offset, ignoreResponse, completion](Napi::Env env, std::vector<napi_value>& args) {
77
+ // callback(result)
78
+ auto callable = [completion](const Napi::CallbackInfo& info){
79
+ completion(info[0].As<Napi::Number>().Int32Value());
80
+ };
81
+ Napi::Function cb = Napi::Function::New(env, callable);
82
+
83
+ // emit('writeRequest', data, offset, ignoreResponse, callback)
84
+ args = { _s("writeRequest"), toBufferFromNSData(env, data), _n(offset), _b(ignoreResponse), cb };
85
+ });
86
+ }
87
+
88
+ void EmitCharacteristic::Subscribe(int maxValueSize, std::function<void (NSData *)> completion) {
89
+ mCallback->call([maxValueSize, completion](Napi::Env env, std::vector<napi_value>& args) {
90
+ // callback(data)
91
+ auto callable = [completion](const Napi::CallbackInfo& info){
92
+ completion(napiToData(info[0].As<Napi::Buffer<Byte>>()));
93
+ };
94
+ Napi::Function cb = Napi::Function::New(env, callable);
95
+
96
+ // emit('subscribe', maxValueSize, callback)
97
+ args = { _s("subscribe"), _n(maxValueSize), cb };
98
+ });
99
+ }
100
+
101
+ void EmitCharacteristic::Unsubscribe() {
102
+ mCallback->call([](Napi::Env env, std::vector<napi_value>& args) {
103
+ // emit('unsubscribe')
104
+ args = { _s("unsubscribe") };
105
+ });
106
+ }
107
+
108
+ void EmitCharacteristic::Notify() {
109
+ mCallback->call([](Napi::Env env, std::vector<napi_value>& args) {
110
+ // emit('notify')
111
+ args = { _s("notify") };
112
+ });
113
+ }
114
+
115
+ void EmitCharacteristic::Indicate() {
116
+ mCallback->call([](Napi::Env env, std::vector<napi_value>& args) {
117
+ // emit('indicate')
118
+ args = { _s("indicate") };
119
+ });
120
+ }
121
+
122
+
123
+ // emit('notify');
124
+ // emit('indicate');
@@ -0,0 +1,30 @@
1
+ #pragma once
2
+
3
+ #include <napi.h>
4
+ #import <Foundation/Foundation.h>
5
+ #import <CoreBluetooth/CoreBluetooth.h>
6
+ #include <map>
7
+
8
+ NSArray* getUuidArray(const Napi::Value& value);
9
+ NSArray* getCBUuidArray(const Napi::Value& value);
10
+ BOOL getBool(const Napi::Value& value, BOOL def);
11
+ NSArray* napiToCBUuidArray(Napi::Array array);
12
+ CBUUID* napiToCBUuidString(Napi::String string);
13
+ NSArray<CBMutableService *> *napiArrayToCBMutableServices(Napi::Array array);
14
+ CBMutableService *napiToCBMutableService(Napi::Object obj);
15
+ NSArray<CBMutableCharacteristic *> *napiArrayToCBMutableCharacteristics(Napi::Array array);
16
+ CBMutableCharacteristic *napiToCBMutableCharacteristic(Napi::Object obj);
17
+ CBCharacteristicProperties napiToCBCharacteristicProperties(Napi::Array properties, Napi::Array secure);
18
+ CBAttributePermissions napiToCBAttributePermissions(Napi::Array properties, Napi::Array secure);
19
+ NSArray<CBDescriptor *> *napiArrayToCBDescriptors(Napi::Array array);
20
+ CBDescriptor *napiToCBDescriptor(Napi::Object obj);
21
+ NSArray<NSString *> *napiToStringArray(Napi::Array array);
22
+
23
+ std::map<Napi::String, Napi::Object> napiArrayToUUIDEmitters(Napi::Array services);
24
+
25
+ NSString *napiToString(Napi::String string);
26
+ NSString* napiToUuidString(Napi::String string);
27
+ NSArray* napiToUuidArray(Napi::Array array);
28
+ NSData* napiToData(Napi::Buffer<Byte> buffer);
29
+ NSNumber* napiToNumber(Napi::Number number);
30
+ NSArray<NSString *> *napiToStringArray(Napi::Array array);