react-native-ble-manager 12.2.2 → 12.4.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/android/src/main/java/it/innove/BleManager.java +10 -4
- package/android/src/main/java/it/innove/DefaultPeripheral.java +14 -9
- package/android/src/main/java/it/innove/DefaultScanManager.java +174 -28
- package/android/src/main/java/it/innove/Peripheral.java +121 -80
- package/android/src/main/java/it/innove/ScanManager.java +1 -1
- package/dist/cjs/NativeBleManager.d.ts +27 -26
- package/dist/cjs/NativeBleManager.js +1 -0
- package/dist/cjs/NativeBleManager.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -1
- package/dist/cjs/index.js +26 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types.d.ts +10 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/NativeBleManager.d.ts +27 -26
- package/dist/esm/NativeBleManager.js +1 -0
- package/dist/esm/NativeBleManager.js.map +1 -1
- package/dist/esm/index.d.ts +6 -1
- package/dist/esm/index.js +27 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.d.ts +10 -0
- package/dist/esm/types.js.map +1 -1
- package/ios/BleManager.mm +7 -11
- package/ios/Helper.swift +166 -110
- package/ios/NotifyBufferContainer.swift +11 -12
- package/ios/SwiftBleManager.swift +1224 -586
- package/package.json +12 -18
- package/src/NativeBleManager.ts +42 -82
- package/src/index.ts +33 -24
- package/src/types.ts +10 -0
|
@@ -1,40 +1,42 @@
|
|
|
1
|
-
import Foundation
|
|
2
1
|
import CoreBluetooth
|
|
2
|
+
import Foundation
|
|
3
3
|
|
|
4
|
+
@objc
|
|
5
|
+
public class SwiftBleManager: NSObject, CBCentralManagerDelegate,
|
|
6
|
+
CBPeripheralDelegate
|
|
7
|
+
{
|
|
8
|
+
static var shared: SwiftBleManager?
|
|
9
|
+
static var sharedManager: CBCentralManager?
|
|
4
10
|
|
|
5
|
-
@objc public class SwiftBleManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
|
|
6
|
-
static var shared:SwiftBleManager?
|
|
7
|
-
static var sharedManager:CBCentralManager?
|
|
8
|
-
|
|
9
11
|
private weak var bleManager: BleManager?
|
|
10
12
|
private var manager: CBCentralManager?
|
|
11
13
|
private var scanTimer: Timer?
|
|
12
|
-
|
|
13
|
-
private var peripherals:
|
|
14
|
-
private var connectCallbacks:
|
|
15
|
-
private var readCallbacks:
|
|
16
|
-
private var readRSSICallbacks:
|
|
17
|
-
private var readDescriptorCallbacks:
|
|
18
|
-
private var writeDescriptorCallbacks:
|
|
19
|
-
private var retrieveServicesCallbacks:
|
|
20
|
-
private var writeCallbacks:
|
|
21
|
-
private var
|
|
22
|
-
private var notificationCallbacks:
|
|
23
|
-
private var stopNotificationCallbacks:
|
|
24
|
-
private var bufferedCharacteristics:
|
|
25
|
-
|
|
14
|
+
|
|
15
|
+
private var peripherals: [String: Peripheral]
|
|
16
|
+
private var connectCallbacks: [String: [RCTResponseSenderBlock]]
|
|
17
|
+
private var readCallbacks: [String: [RCTResponseSenderBlock]]
|
|
18
|
+
private var readRSSICallbacks: [String: [RCTResponseSenderBlock]]
|
|
19
|
+
private var readDescriptorCallbacks: [String: [RCTResponseSenderBlock]]
|
|
20
|
+
private var writeDescriptorCallbacks: [String: [RCTResponseSenderBlock]]
|
|
21
|
+
private var retrieveServicesCallbacks: [String: [RCTResponseSenderBlock]]
|
|
22
|
+
private var writeCallbacks: [String: [RCTResponseSenderBlock]]
|
|
23
|
+
private var writeQueues: [String: [Data]]
|
|
24
|
+
private var notificationCallbacks: [String: [RCTResponseSenderBlock]]
|
|
25
|
+
private var stopNotificationCallbacks: [String: [RCTResponseSenderBlock]]
|
|
26
|
+
private var bufferedCharacteristics: [String: NotifyBufferContainer]
|
|
27
|
+
|
|
26
28
|
private var connectedPeripherals: Set<String>
|
|
27
|
-
|
|
28
|
-
private var retrieveServicesLatches:
|
|
29
|
-
private var characteristicsLatches:
|
|
30
|
-
|
|
29
|
+
|
|
30
|
+
private var retrieveServicesLatches: [String: Set<CBService>]
|
|
31
|
+
private var characteristicsLatches: [String: Set<CBCharacteristic>]
|
|
32
|
+
|
|
31
33
|
private let serialQueue = DispatchQueue(label: "BleManager.serialQueue")
|
|
32
|
-
|
|
34
|
+
|
|
33
35
|
private var exactAdvertisingName: [String]
|
|
34
|
-
|
|
36
|
+
|
|
35
37
|
static var verboseLogging = false
|
|
36
|
-
|
|
37
|
-
@objc public init(bleManager:BleManager) {
|
|
38
|
+
|
|
39
|
+
@objc public init(bleManager: BleManager) {
|
|
38
40
|
peripherals = [:]
|
|
39
41
|
connectCallbacks = [:]
|
|
40
42
|
readCallbacks = [:]
|
|
@@ -43,7 +45,7 @@ import CoreBluetooth
|
|
|
43
45
|
writeDescriptorCallbacks = [:]
|
|
44
46
|
retrieveServicesCallbacks = [:]
|
|
45
47
|
writeCallbacks = [:]
|
|
46
|
-
|
|
48
|
+
writeQueues = [:]
|
|
47
49
|
notificationCallbacks = [:]
|
|
48
50
|
stopNotificationCallbacks = [:]
|
|
49
51
|
bufferedCharacteristics = [:]
|
|
@@ -52,18 +54,23 @@ import CoreBluetooth
|
|
|
52
54
|
exactAdvertisingName = []
|
|
53
55
|
connectedPeripherals = []
|
|
54
56
|
self.bleManager = bleManager
|
|
55
|
-
|
|
57
|
+
|
|
56
58
|
super.init()
|
|
57
|
-
|
|
58
|
-
NSLog("BleManager created")
|
|
59
|
-
|
|
59
|
+
|
|
60
|
+
NSLog("BleManager created")
|
|
61
|
+
|
|
60
62
|
SwiftBleManager.shared = self
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
|
|
64
|
+
NotificationCenter.default.addObserver(
|
|
65
|
+
self,
|
|
66
|
+
selector: #selector(bridgeReloading),
|
|
67
|
+
name: NSNotification.Name(
|
|
68
|
+
rawValue: "RCTBridgeWillReloadNotification"
|
|
69
|
+
),
|
|
70
|
+
object: nil
|
|
71
|
+
)
|
|
64
72
|
}
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
|
|
67
74
|
@objc func bridgeReloading() {
|
|
68
75
|
if let manager = manager {
|
|
69
76
|
if let scanTimer = self.scanTimer {
|
|
@@ -71,255 +78,389 @@ import CoreBluetooth
|
|
|
71
78
|
self.scanTimer = nil
|
|
72
79
|
manager.stopScan()
|
|
73
80
|
}
|
|
74
|
-
|
|
81
|
+
|
|
75
82
|
manager.delegate = nil
|
|
76
83
|
}
|
|
77
|
-
|
|
84
|
+
|
|
78
85
|
serialQueue.sync {
|
|
79
86
|
for p in peripherals.values {
|
|
80
87
|
p.instance.delegate = nil
|
|
81
88
|
}
|
|
82
89
|
}
|
|
83
|
-
|
|
90
|
+
|
|
84
91
|
peripherals = [:]
|
|
85
92
|
}
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
|
|
88
94
|
// Helper method to find a peripheral by UUID
|
|
89
95
|
func findPeripheral(byUUID uuid: String) -> Peripheral? {
|
|
90
96
|
var foundPeripheral: Peripheral? = nil
|
|
91
|
-
|
|
97
|
+
|
|
92
98
|
serialQueue.sync {
|
|
93
99
|
if let peripheral = peripherals[uuid] {
|
|
94
|
-
foundPeripheral = peripheral
|
|
100
|
+
foundPeripheral = peripheral
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
|
-
|
|
103
|
+
|
|
98
104
|
return foundPeripheral
|
|
99
105
|
}
|
|
100
|
-
|
|
106
|
+
|
|
101
107
|
// Helper method to insert callback in different queues
|
|
102
|
-
func insertCallback(
|
|
108
|
+
func insertCallback(
|
|
109
|
+
_ callback: @escaping RCTResponseSenderBlock,
|
|
110
|
+
intoDictionary dictionary: inout [String: [RCTResponseSenderBlock]],
|
|
111
|
+
withKey key: String
|
|
112
|
+
) {
|
|
103
113
|
serialQueue.sync {
|
|
104
|
-
var peripheralCallbacks =
|
|
114
|
+
var peripheralCallbacks =
|
|
115
|
+
dictionary[key] ?? [RCTResponseSenderBlock]()
|
|
105
116
|
peripheralCallbacks.append(callback)
|
|
106
117
|
dictionary[key] = peripheralCallbacks
|
|
107
118
|
}
|
|
108
119
|
}
|
|
109
|
-
|
|
120
|
+
|
|
110
121
|
// Helper method to call the callbacks for a specific peripheral and clear the queue
|
|
111
|
-
func invokeAndClearDictionary(
|
|
122
|
+
func invokeAndClearDictionary(
|
|
123
|
+
_ dictionary: inout [String: [RCTResponseSenderBlock]],
|
|
124
|
+
withKey key: String,
|
|
125
|
+
usingParameters parameters: [Any]
|
|
126
|
+
) {
|
|
127
|
+
serialQueue.sync {
|
|
128
|
+
invokeAndClearDictionary_THREAD_UNSAFE(
|
|
129
|
+
&dictionary,
|
|
130
|
+
withKey: key,
|
|
131
|
+
usingParameters: parameters
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private func enqueueSplitMessages(
|
|
137
|
+
_ messages: [Data],
|
|
138
|
+
forKey key: String
|
|
139
|
+
) -> (firstChunk: Data?, remainingCount: Int) {
|
|
140
|
+
var chunkToSend: Data?
|
|
141
|
+
var remainingCount = 0
|
|
142
|
+
|
|
112
143
|
serialQueue.sync {
|
|
113
|
-
|
|
144
|
+
var queue = writeQueues[key] ?? []
|
|
145
|
+
queue.append(contentsOf: messages)
|
|
146
|
+
|
|
147
|
+
if !queue.isEmpty {
|
|
148
|
+
chunkToSend = queue.removeFirst()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
remainingCount = queue.count
|
|
152
|
+
writeQueues[key] = queue
|
|
114
153
|
}
|
|
154
|
+
|
|
155
|
+
return (chunkToSend, remainingCount)
|
|
115
156
|
}
|
|
116
|
-
|
|
117
|
-
func
|
|
157
|
+
|
|
158
|
+
private func dequeueNextSplitMessage(forKey key: String) -> Data? {
|
|
159
|
+
var nextMessage: Data?
|
|
160
|
+
|
|
161
|
+
serialQueue.sync {
|
|
162
|
+
if var queue = writeQueues[key], !queue.isEmpty {
|
|
163
|
+
nextMessage = queue.removeFirst()
|
|
164
|
+
writeQueues[key] = queue
|
|
165
|
+
} else {
|
|
166
|
+
writeQueues.removeValue(forKey: key)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return nextMessage
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
func invokeAndClearDictionary_THREAD_UNSAFE(
|
|
174
|
+
_ dictionary: inout [String: [RCTResponseSenderBlock]],
|
|
175
|
+
withKey key: String,
|
|
176
|
+
usingParameters parameters: [Any]
|
|
177
|
+
) {
|
|
118
178
|
if let peripheralCallbacks = dictionary[key] {
|
|
119
179
|
for callback in peripheralCallbacks {
|
|
120
180
|
callback(parameters)
|
|
121
181
|
}
|
|
122
|
-
|
|
182
|
+
|
|
123
183
|
dictionary.removeValue(forKey: key)
|
|
124
184
|
}
|
|
125
185
|
}
|
|
126
|
-
|
|
127
|
-
@objc func getContext(
|
|
186
|
+
|
|
187
|
+
@objc func getContext(
|
|
188
|
+
_ peripheralUUIDString: String,
|
|
189
|
+
serviceUUIDString: String,
|
|
190
|
+
characteristicUUIDString: String,
|
|
191
|
+
prop: CBCharacteristicProperties,
|
|
192
|
+
callback: @escaping RCTResponseSenderBlock
|
|
193
|
+
) -> BLECommandContext? {
|
|
128
194
|
let serviceUUID = CBUUID(string: serviceUUIDString)
|
|
129
195
|
let characteristicUUID = CBUUID(string: characteristicUUIDString)
|
|
130
|
-
|
|
196
|
+
|
|
131
197
|
guard let peripheral = peripherals[peripheralUUIDString] else {
|
|
132
|
-
let error = String(
|
|
198
|
+
let error = String(
|
|
199
|
+
format: "Could not find peripheral with UUID %@",
|
|
200
|
+
peripheralUUIDString
|
|
201
|
+
)
|
|
133
202
|
NSLog(error)
|
|
134
203
|
callback([error])
|
|
135
204
|
return nil
|
|
136
205
|
}
|
|
137
|
-
|
|
138
|
-
guard
|
|
139
|
-
let
|
|
140
|
-
|
|
141
|
-
|
|
206
|
+
|
|
207
|
+
guard
|
|
208
|
+
let service = Helper.findService(
|
|
209
|
+
fromUUID: serviceUUID,
|
|
210
|
+
peripheral: peripheral.instance
|
|
211
|
+
)
|
|
212
|
+
else {
|
|
213
|
+
let error = String(
|
|
214
|
+
format:
|
|
215
|
+
"Could not find service with UUID %@ on peripheral with UUID %@",
|
|
216
|
+
serviceUUIDString,
|
|
217
|
+
peripheral.instance.uuidAsString()
|
|
218
|
+
)
|
|
142
219
|
NSLog(error)
|
|
143
220
|
callback([error])
|
|
144
221
|
return nil
|
|
145
222
|
}
|
|
146
|
-
|
|
147
|
-
var characteristic = Helper.findCharacteristic(
|
|
148
|
-
|
|
223
|
+
|
|
224
|
+
var characteristic = Helper.findCharacteristic(
|
|
225
|
+
fromUUID: characteristicUUID,
|
|
226
|
+
service: service,
|
|
227
|
+
prop: prop
|
|
228
|
+
)
|
|
229
|
+
|
|
149
230
|
// Special handling for INDICATE. If characteristic with notify is not found, check for indicate.
|
|
150
231
|
if prop == CBCharacteristicProperties.notify && characteristic == nil {
|
|
151
|
-
characteristic = Helper.findCharacteristic(
|
|
232
|
+
characteristic = Helper.findCharacteristic(
|
|
233
|
+
fromUUID: characteristicUUID,
|
|
234
|
+
service: service,
|
|
235
|
+
prop: CBCharacteristicProperties.indicate
|
|
236
|
+
)
|
|
152
237
|
}
|
|
153
|
-
|
|
238
|
+
|
|
154
239
|
// As a last resort, try to find ANY characteristic with this UUID, even if it doesn't have the correct properties
|
|
155
240
|
if characteristic == nil {
|
|
156
|
-
characteristic = Helper.findCharacteristic(
|
|
241
|
+
characteristic = Helper.findCharacteristic(
|
|
242
|
+
fromUUID: characteristicUUID,
|
|
243
|
+
service: service
|
|
244
|
+
)
|
|
157
245
|
}
|
|
158
|
-
|
|
246
|
+
|
|
159
247
|
guard let finalCharacteristic = characteristic else {
|
|
160
|
-
let error = String(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
248
|
+
let error = String(
|
|
249
|
+
format:
|
|
250
|
+
"Could not find characteristic with UUID %@ on service with UUID %@ on peripheral with UUID %@",
|
|
251
|
+
characteristicUUIDString,
|
|
252
|
+
serviceUUIDString,
|
|
253
|
+
peripheral.instance.uuidAsString()
|
|
254
|
+
)
|
|
164
255
|
NSLog(error)
|
|
165
256
|
callback([error])
|
|
166
257
|
return nil
|
|
167
258
|
}
|
|
168
|
-
|
|
259
|
+
|
|
169
260
|
let context = BLECommandContext()
|
|
170
261
|
context.peripheral = peripheral
|
|
171
262
|
context.service = service
|
|
172
263
|
context.characteristic = finalCharacteristic
|
|
173
264
|
return context
|
|
174
265
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
266
|
+
|
|
267
|
+
@objc public func start(
|
|
268
|
+
_ options: NSDictionary,
|
|
269
|
+
callback: RCTResponseSenderBlock
|
|
270
|
+
) {
|
|
179
271
|
if SwiftBleManager.verboseLogging {
|
|
180
272
|
NSLog("BleManager initialized")
|
|
181
273
|
}
|
|
182
|
-
if let bluetoothUsageDescription = Bundle.main.object(
|
|
274
|
+
if let bluetoothUsageDescription = Bundle.main.object(
|
|
275
|
+
forInfoDictionaryKey: "NSBluetoothAlwaysUsageDescription"
|
|
276
|
+
) as? String {
|
|
183
277
|
// NSBluetoothAlwaysUsageDescription is ok
|
|
184
278
|
} else {
|
|
185
|
-
let error =
|
|
279
|
+
let error =
|
|
280
|
+
"NSBluetoothAlwaysUsageDescription is not set in the infoPlist"
|
|
186
281
|
NSLog(error)
|
|
187
282
|
callback([error])
|
|
188
283
|
return
|
|
189
284
|
}
|
|
190
285
|
var initOptions = [String: Any]()
|
|
191
|
-
|
|
286
|
+
|
|
192
287
|
if let showAlert = options["showAlert"] as? Bool {
|
|
193
288
|
initOptions[CBCentralManagerOptionShowPowerAlertKey] = showAlert
|
|
194
289
|
}
|
|
195
|
-
|
|
290
|
+
|
|
196
291
|
if let verboseLogging = options["verboseLogging"] as? Bool {
|
|
197
292
|
SwiftBleManager.verboseLogging = verboseLogging
|
|
198
293
|
}
|
|
199
|
-
|
|
294
|
+
|
|
200
295
|
var queue: DispatchQueue
|
|
201
296
|
if let queueIdentifierKey = options["queueIdentifierKey"] as? String {
|
|
202
|
-
queue = DispatchQueue(
|
|
297
|
+
queue = DispatchQueue(
|
|
298
|
+
label: queueIdentifierKey,
|
|
299
|
+
qos: DispatchQoS.background
|
|
300
|
+
)
|
|
203
301
|
} else {
|
|
204
302
|
queue = DispatchQueue.main
|
|
205
303
|
}
|
|
206
|
-
|
|
207
|
-
if let restoreIdentifierKey = options["restoreIdentifierKey"] as? String
|
|
208
|
-
|
|
209
|
-
|
|
304
|
+
|
|
305
|
+
if let restoreIdentifierKey = options["restoreIdentifierKey"] as? String
|
|
306
|
+
{
|
|
307
|
+
initOptions[CBCentralManagerOptionRestoreIdentifierKey] =
|
|
308
|
+
restoreIdentifierKey
|
|
309
|
+
|
|
210
310
|
if let sharedManager = SwiftBleManager.sharedManager {
|
|
211
311
|
manager = sharedManager
|
|
212
312
|
manager?.delegate = self
|
|
213
313
|
} else {
|
|
214
|
-
manager = CBCentralManager(
|
|
314
|
+
manager = CBCentralManager(
|
|
315
|
+
delegate: self,
|
|
316
|
+
queue: queue,
|
|
317
|
+
options: initOptions
|
|
318
|
+
)
|
|
215
319
|
SwiftBleManager.sharedManager = manager
|
|
216
320
|
}
|
|
217
321
|
} else {
|
|
218
|
-
manager = CBCentralManager(
|
|
322
|
+
manager = CBCentralManager(
|
|
323
|
+
delegate: self,
|
|
324
|
+
queue: queue,
|
|
325
|
+
options: initOptions
|
|
326
|
+
)
|
|
219
327
|
SwiftBleManager.sharedManager = manager
|
|
220
328
|
}
|
|
221
|
-
|
|
329
|
+
|
|
222
330
|
callback([])
|
|
223
331
|
}
|
|
224
|
-
|
|
225
|
-
@objc public func
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
332
|
+
|
|
333
|
+
@objc public func isStarted(_ callback: RCTResponseSenderBlock) {
|
|
334
|
+
let started = manager != nil
|
|
335
|
+
callback([NSNull(), started])
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
@objc public func scan(
|
|
339
|
+
_ scanningOptions: NSDictionary,
|
|
340
|
+
callback: RCTResponseSenderBlock
|
|
341
|
+
) {
|
|
342
|
+
if Int(truncating: scanningOptions["seconds"] as? NSNumber ?? 0) > 0 {
|
|
343
|
+
NSLog("scan with timeout \(scanningOptions["seconds"] ?? 0)")
|
|
232
344
|
} else {
|
|
233
345
|
NSLog("scan")
|
|
234
346
|
}
|
|
235
|
-
|
|
347
|
+
|
|
236
348
|
// Clear the peripherals before scanning again, otherwise cannot connect again after disconnection
|
|
237
349
|
// Only clear peripherals that are not connected - otherwise connections fail silently (without any
|
|
238
350
|
// onDisconnect* callback).
|
|
239
351
|
serialQueue.sync {
|
|
240
|
-
let disconnectedPeripherals = peripherals.filter({
|
|
352
|
+
let disconnectedPeripherals = peripherals.filter({
|
|
353
|
+
$0.value.instance.state != .connected
|
|
354
|
+
&& $0.value.instance.state != .connecting
|
|
355
|
+
})
|
|
241
356
|
disconnectedPeripherals.forEach { (uuid, peripheral) in
|
|
242
357
|
peripheral.instance.delegate = nil
|
|
243
358
|
peripherals.removeValue(forKey: uuid)
|
|
244
359
|
}
|
|
245
360
|
}
|
|
246
|
-
|
|
361
|
+
|
|
247
362
|
var serviceUUIDs = [CBUUID]()
|
|
248
|
-
if let serviceUUIDStrings = serviceUUIDStrings
|
|
363
|
+
if let serviceUUIDStrings = scanningOptions["serviceUUIDStrings"]
|
|
364
|
+
as? [String]
|
|
365
|
+
{
|
|
249
366
|
serviceUUIDs = serviceUUIDStrings.map { CBUUID(string: $0) }
|
|
250
367
|
}
|
|
251
|
-
|
|
368
|
+
|
|
252
369
|
var options: [String: Any]?
|
|
370
|
+
let allowDuplicates =
|
|
371
|
+
scanningOptions["allowDuplicates"] as? Bool ?? false
|
|
253
372
|
if allowDuplicates {
|
|
254
373
|
options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
|
|
255
374
|
}
|
|
256
|
-
|
|
375
|
+
|
|
257
376
|
exactAdvertisingName.removeAll()
|
|
258
377
|
if let names = scanningOptions["exactAdvertisingName"] as? [String] {
|
|
259
378
|
exactAdvertisingName.append(contentsOf: names)
|
|
260
379
|
}
|
|
261
|
-
|
|
262
|
-
manager?.scanForPeripherals(
|
|
263
|
-
|
|
264
|
-
|
|
380
|
+
|
|
381
|
+
manager?.scanForPeripherals(
|
|
382
|
+
withServices: serviceUUIDs,
|
|
383
|
+
options: options
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
let timeoutSeconds = scanningOptions["seconds"] as? Double ?? 0
|
|
387
|
+
if timeoutSeconds > 0 {
|
|
265
388
|
if let scanTimer = scanTimer {
|
|
266
389
|
scanTimer.invalidate()
|
|
267
390
|
self.scanTimer = nil
|
|
268
391
|
}
|
|
269
392
|
DispatchQueue.main.async {
|
|
270
|
-
self.scanTimer = Timer.scheduledTimer(
|
|
393
|
+
self.scanTimer = Timer.scheduledTimer(
|
|
394
|
+
timeInterval: timeoutSeconds,
|
|
395
|
+
target: self,
|
|
396
|
+
selector: #selector(self.stopTimer),
|
|
397
|
+
userInfo: nil,
|
|
398
|
+
repeats: false
|
|
399
|
+
)
|
|
271
400
|
}
|
|
272
401
|
}
|
|
273
|
-
|
|
402
|
+
|
|
274
403
|
callback([])
|
|
275
404
|
}
|
|
276
|
-
|
|
405
|
+
|
|
277
406
|
@objc func stopTimer() {
|
|
278
|
-
NSLog("Stop scan")
|
|
279
|
-
scanTimer = nil
|
|
407
|
+
NSLog("Stop scan")
|
|
408
|
+
scanTimer = nil
|
|
280
409
|
manager?.stopScan()
|
|
281
410
|
bleManager?.emit(onStopScan: ["status": 10])
|
|
282
411
|
}
|
|
283
|
-
|
|
284
|
-
|
|
412
|
+
|
|
285
413
|
@objc public func stopScan(_ callback: @escaping RCTResponseSenderBlock) {
|
|
286
414
|
if let scanTimer = self.scanTimer {
|
|
287
415
|
scanTimer.invalidate()
|
|
288
416
|
self.scanTimer = nil
|
|
289
417
|
}
|
|
290
|
-
|
|
418
|
+
|
|
291
419
|
manager?.stopScan()
|
|
292
|
-
|
|
420
|
+
|
|
293
421
|
bleManager?.emit(onStopScan: ["status": 0])
|
|
294
|
-
|
|
422
|
+
|
|
295
423
|
callback([])
|
|
296
424
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
425
|
+
|
|
426
|
+
@objc public func connect(
|
|
427
|
+
_ peripheralUUID: String,
|
|
428
|
+
options: NSDictionary,
|
|
429
|
+
callback: @escaping RCTResponseSenderBlock
|
|
430
|
+
) {
|
|
431
|
+
|
|
303
432
|
if let peripheral = peripherals[peripheralUUID] {
|
|
304
433
|
// Found the peripheral, connect to it
|
|
305
434
|
NSLog("Connecting to peripheral with UUID: \(peripheralUUID)")
|
|
306
|
-
|
|
307
|
-
insertCallback(
|
|
435
|
+
|
|
436
|
+
insertCallback(
|
|
437
|
+
callback,
|
|
438
|
+
intoDictionary: &connectCallbacks,
|
|
439
|
+
withKey: peripheral.instance.uuidAsString()
|
|
440
|
+
)
|
|
308
441
|
manager?.connect(peripheral.instance)
|
|
309
442
|
} else {
|
|
310
443
|
// Try to retrieve the peripheral
|
|
311
444
|
NSLog("Retrieving peripheral with UUID: \(peripheralUUID)")
|
|
312
|
-
|
|
445
|
+
|
|
313
446
|
if let uuid = UUID(uuidString: peripheralUUID) {
|
|
314
|
-
let peripheralArray = manager?.retrievePeripherals(
|
|
447
|
+
let peripheralArray = manager?.retrievePeripherals(
|
|
448
|
+
withIdentifiers: [uuid])
|
|
315
449
|
if let retrievedPeripheral = peripheralArray?.first {
|
|
316
450
|
serialQueue.sync {
|
|
317
|
-
peripherals[retrievedPeripheral.uuidAsString()] =
|
|
451
|
+
peripherals[retrievedPeripheral.uuidAsString()] =
|
|
452
|
+
Peripheral(peripheral: retrievedPeripheral)
|
|
318
453
|
}
|
|
319
|
-
NSLog(
|
|
320
|
-
|
|
454
|
+
NSLog(
|
|
455
|
+
"Successfully retrieved and connecting to peripheral with UUID: \(peripheralUUID)"
|
|
456
|
+
)
|
|
457
|
+
|
|
321
458
|
// Connect to the retrieved peripheral
|
|
322
|
-
insertCallback(
|
|
459
|
+
insertCallback(
|
|
460
|
+
callback,
|
|
461
|
+
intoDictionary: &connectCallbacks,
|
|
462
|
+
withKey: retrievedPeripheral.uuidAsString()
|
|
463
|
+
)
|
|
323
464
|
manager?.connect(retrievedPeripheral, options: nil)
|
|
324
465
|
} else {
|
|
325
466
|
let error = "Could not find peripheral \(peripheralUUID)."
|
|
@@ -332,198 +473,282 @@ import CoreBluetooth
|
|
|
332
473
|
}
|
|
333
474
|
}
|
|
334
475
|
}
|
|
335
|
-
|
|
336
|
-
@objc public func disconnect(
|
|
337
|
-
|
|
338
|
-
|
|
476
|
+
|
|
477
|
+
@objc public func disconnect(
|
|
478
|
+
_ peripheralUUID: String,
|
|
479
|
+
force: Bool,
|
|
480
|
+
callback: @escaping RCTResponseSenderBlock
|
|
481
|
+
) {
|
|
339
482
|
if let peripheral = peripherals[peripheralUUID] {
|
|
340
483
|
NSLog("Disconnecting from peripheral with UUID: \(peripheralUUID)")
|
|
341
|
-
|
|
484
|
+
|
|
342
485
|
if let services = peripheral.instance.services {
|
|
343
486
|
for service in services {
|
|
344
487
|
if let characteristics = service.characteristics {
|
|
345
488
|
for characteristic in characteristics {
|
|
346
489
|
if characteristic.isNotifying {
|
|
347
|
-
NSLog(
|
|
348
|
-
|
|
490
|
+
NSLog(
|
|
491
|
+
"Remove notification from: \(characteristic.uuid)"
|
|
492
|
+
)
|
|
493
|
+
peripheral.instance.setNotifyValue(
|
|
494
|
+
false,
|
|
495
|
+
for: characteristic
|
|
496
|
+
)
|
|
349
497
|
}
|
|
350
498
|
}
|
|
351
499
|
}
|
|
352
500
|
}
|
|
353
501
|
}
|
|
354
|
-
|
|
502
|
+
|
|
355
503
|
manager?.cancelPeripheralConnection(peripheral.instance)
|
|
356
504
|
callback([])
|
|
357
|
-
|
|
505
|
+
|
|
358
506
|
} else {
|
|
359
507
|
let error = "Could not find peripheral \(peripheralUUID)."
|
|
360
508
|
NSLog(error)
|
|
361
509
|
callback([error])
|
|
362
510
|
}
|
|
363
511
|
}
|
|
364
|
-
|
|
365
|
-
@objc public func retrieveServices(
|
|
366
|
-
|
|
367
|
-
|
|
512
|
+
|
|
513
|
+
@objc public func retrieveServices(
|
|
514
|
+
_ peripheralUUID: String,
|
|
515
|
+
services: [String],
|
|
516
|
+
callback: @escaping RCTResponseSenderBlock
|
|
517
|
+
) {
|
|
368
518
|
NSLog("retrieveServices \(services)")
|
|
369
|
-
|
|
370
|
-
if let peripheral = peripherals[peripheralUUID],
|
|
371
|
-
|
|
372
|
-
|
|
519
|
+
|
|
520
|
+
if let peripheral = peripherals[peripheralUUID],
|
|
521
|
+
peripheral.instance.state == .connected
|
|
522
|
+
{
|
|
523
|
+
insertCallback(
|
|
524
|
+
callback,
|
|
525
|
+
intoDictionary: &retrieveServicesCallbacks,
|
|
526
|
+
withKey: peripheral.instance.uuidAsString()
|
|
527
|
+
)
|
|
528
|
+
|
|
373
529
|
var uuids: [CBUUID] = []
|
|
374
530
|
for string in services {
|
|
375
531
|
let uuid = CBUUID(string: string)
|
|
376
532
|
uuids.append(uuid)
|
|
377
533
|
}
|
|
378
|
-
|
|
534
|
+
|
|
379
535
|
if !uuids.isEmpty {
|
|
380
536
|
peripheral.instance.discoverServices(uuids)
|
|
381
537
|
} else {
|
|
382
538
|
peripheral.instance.discoverServices(nil)
|
|
383
539
|
}
|
|
384
|
-
|
|
540
|
+
|
|
385
541
|
} else {
|
|
386
542
|
callback(["Peripheral not found or not connected"])
|
|
387
543
|
}
|
|
388
544
|
}
|
|
389
|
-
|
|
390
|
-
@objc public func readRSSI(
|
|
391
|
-
|
|
545
|
+
|
|
546
|
+
@objc public func readRSSI(
|
|
547
|
+
_ peripheralUUID: String,
|
|
548
|
+
callback: @escaping RCTResponseSenderBlock
|
|
549
|
+
) {
|
|
392
550
|
NSLog("readRSSI")
|
|
393
|
-
|
|
394
|
-
if let peripheral = peripherals[peripheralUUID],
|
|
395
|
-
|
|
551
|
+
|
|
552
|
+
if let peripheral = peripherals[peripheralUUID],
|
|
553
|
+
peripheral.instance.state == .connected
|
|
554
|
+
{
|
|
555
|
+
insertCallback(
|
|
556
|
+
callback,
|
|
557
|
+
intoDictionary: &readRSSICallbacks,
|
|
558
|
+
withKey: peripheral.instance.uuidAsString()
|
|
559
|
+
)
|
|
396
560
|
peripheral.instance.readRSSI()
|
|
397
561
|
} else {
|
|
398
562
|
callback(["Peripheral not found or not connected"])
|
|
399
563
|
}
|
|
400
564
|
}
|
|
401
|
-
|
|
402
|
-
@objc public func readDescriptor(
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
565
|
+
|
|
566
|
+
@objc public func readDescriptor(
|
|
567
|
+
_ peripheralUUID: String,
|
|
568
|
+
serviceUUID: String,
|
|
569
|
+
characteristicUUID: String,
|
|
570
|
+
descriptorUUID: String,
|
|
571
|
+
callback: @escaping RCTResponseSenderBlock
|
|
572
|
+
) {
|
|
407
573
|
NSLog("readDescriptor")
|
|
408
|
-
|
|
409
|
-
guard
|
|
574
|
+
|
|
575
|
+
guard
|
|
576
|
+
let context = getContext(
|
|
577
|
+
peripheralUUID,
|
|
578
|
+
serviceUUIDString: serviceUUID,
|
|
579
|
+
characteristicUUIDString: characteristicUUID,
|
|
580
|
+
prop: CBCharacteristicProperties.read,
|
|
581
|
+
callback: callback
|
|
582
|
+
)
|
|
583
|
+
else {
|
|
410
584
|
return
|
|
411
585
|
}
|
|
412
|
-
|
|
586
|
+
|
|
413
587
|
let peripheral = context.peripheral
|
|
414
588
|
let characteristic = context.characteristic
|
|
415
|
-
|
|
416
|
-
guard
|
|
417
|
-
let
|
|
589
|
+
|
|
590
|
+
guard
|
|
591
|
+
let descriptor = Helper.findDescriptor(
|
|
592
|
+
fromUUID: CBUUID(string: descriptorUUID),
|
|
593
|
+
characteristic: characteristic!
|
|
594
|
+
)
|
|
595
|
+
else {
|
|
596
|
+
let error =
|
|
597
|
+
"Could not find descriptor with UUID \(descriptorUUID) on characteristic with UUID \(String(describing: characteristic?.uuid.uuidString)) on peripheral with UUID \(peripheralUUID)"
|
|
418
598
|
NSLog(error)
|
|
419
599
|
callback([error])
|
|
420
600
|
return
|
|
421
601
|
}
|
|
422
|
-
|
|
602
|
+
|
|
423
603
|
if let peripheral = peripheral?.instance {
|
|
424
|
-
let key = Helper.key(
|
|
425
|
-
|
|
426
|
-
|
|
604
|
+
let key = Helper.key(
|
|
605
|
+
forPeripheral: peripheral,
|
|
606
|
+
andCharacteristic: characteristic!,
|
|
607
|
+
andDescriptor: descriptor
|
|
608
|
+
)
|
|
609
|
+
insertCallback(
|
|
610
|
+
callback,
|
|
611
|
+
intoDictionary: &readDescriptorCallbacks,
|
|
612
|
+
withKey: key
|
|
613
|
+
)
|
|
614
|
+
|
|
427
615
|
}
|
|
428
|
-
|
|
616
|
+
|
|
429
617
|
peripheral?.instance.readValue(for: descriptor)
|
|
430
618
|
}
|
|
431
|
-
|
|
432
|
-
@objc public func writeDescriptor(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
619
|
+
|
|
620
|
+
@objc public func writeDescriptor(
|
|
621
|
+
_ peripheralUUID: String,
|
|
622
|
+
serviceUUID: String,
|
|
623
|
+
characteristicUUID: String,
|
|
624
|
+
descriptorUUID: String,
|
|
625
|
+
message: [UInt8],
|
|
626
|
+
callback: @escaping RCTResponseSenderBlock
|
|
627
|
+
) {
|
|
438
628
|
NSLog("writeDescriptor")
|
|
439
|
-
|
|
440
|
-
guard
|
|
629
|
+
|
|
630
|
+
guard
|
|
631
|
+
let context = getContext(
|
|
632
|
+
peripheralUUID,
|
|
633
|
+
serviceUUIDString: serviceUUID,
|
|
634
|
+
characteristicUUIDString: characteristicUUID,
|
|
635
|
+
prop: CBCharacteristicProperties.read,
|
|
636
|
+
callback: callback
|
|
637
|
+
)
|
|
638
|
+
else {
|
|
441
639
|
return
|
|
442
640
|
}
|
|
443
|
-
|
|
641
|
+
|
|
444
642
|
let peripheral = context.peripheral
|
|
445
643
|
let characteristic = context.characteristic
|
|
446
|
-
|
|
447
|
-
guard
|
|
448
|
-
let
|
|
644
|
+
|
|
645
|
+
guard
|
|
646
|
+
let descriptor = Helper.findDescriptor(
|
|
647
|
+
fromUUID: CBUUID(string: descriptorUUID),
|
|
648
|
+
characteristic: characteristic!
|
|
649
|
+
)
|
|
650
|
+
else {
|
|
651
|
+
let error =
|
|
652
|
+
"Could not find descriptor with UUID \(descriptorUUID) on characteristic with UUID \(String(describing: characteristic?.uuid.uuidString)) on peripheral with UUID \(peripheralUUID)"
|
|
449
653
|
NSLog(error)
|
|
450
654
|
callback([error])
|
|
451
655
|
return
|
|
452
656
|
}
|
|
453
|
-
|
|
657
|
+
|
|
454
658
|
if let peripheral = peripheral?.instance {
|
|
455
|
-
let key = Helper.key(
|
|
456
|
-
|
|
457
|
-
|
|
659
|
+
let key = Helper.key(
|
|
660
|
+
forPeripheral: peripheral,
|
|
661
|
+
andCharacteristic: characteristic!,
|
|
662
|
+
andDescriptor: descriptor
|
|
663
|
+
)
|
|
664
|
+
insertCallback(
|
|
665
|
+
callback,
|
|
666
|
+
intoDictionary: &writeDescriptorCallbacks,
|
|
667
|
+
withKey: key
|
|
668
|
+
)
|
|
669
|
+
|
|
458
670
|
}
|
|
459
|
-
|
|
671
|
+
|
|
460
672
|
let dataMessage = Data(message)
|
|
461
673
|
peripheral?.instance.writeValue(dataMessage, for: descriptor)
|
|
462
674
|
}
|
|
463
|
-
|
|
464
|
-
@objc public func getDiscoveredPeripherals(
|
|
675
|
+
|
|
676
|
+
@objc public func getDiscoveredPeripherals(
|
|
677
|
+
_ callback: @escaping RCTResponseSenderBlock
|
|
678
|
+
) {
|
|
465
679
|
NSLog("Get discovered peripherals")
|
|
466
680
|
var discoveredPeripherals: [[String: Any]] = []
|
|
467
|
-
|
|
681
|
+
|
|
468
682
|
serialQueue.sync {
|
|
469
683
|
for (_, peripheral) in peripherals {
|
|
470
684
|
discoveredPeripherals.append(peripheral.advertisingInfo())
|
|
471
685
|
}
|
|
472
686
|
}
|
|
473
|
-
|
|
687
|
+
|
|
474
688
|
callback([NSNull(), discoveredPeripherals])
|
|
475
689
|
}
|
|
476
|
-
|
|
477
|
-
@objc public func getConnectedPeripherals(
|
|
478
|
-
|
|
690
|
+
|
|
691
|
+
@objc public func getConnectedPeripherals(
|
|
692
|
+
_ serviceUUIDStrings: [String],
|
|
693
|
+
callback: @escaping RCTResponseSenderBlock
|
|
694
|
+
) {
|
|
479
695
|
NSLog("Get connected peripherals")
|
|
480
696
|
var serviceUUIDs: [CBUUID] = []
|
|
481
|
-
|
|
697
|
+
|
|
482
698
|
for uuidString in serviceUUIDStrings {
|
|
483
699
|
serviceUUIDs.append(CBUUID(string: uuidString))
|
|
484
700
|
}
|
|
485
|
-
|
|
701
|
+
|
|
486
702
|
var connectedPeripherals: [Peripheral] = []
|
|
487
|
-
|
|
703
|
+
|
|
488
704
|
if serviceUUIDs.isEmpty {
|
|
489
705
|
serialQueue.sync {
|
|
490
|
-
connectedPeripherals = peripherals.filter({
|
|
706
|
+
connectedPeripherals = peripherals.filter({
|
|
707
|
+
$0.value.instance.state == .connected
|
|
708
|
+
}).map({ p in
|
|
491
709
|
p.value
|
|
492
710
|
})
|
|
493
711
|
}
|
|
494
712
|
} else {
|
|
495
|
-
let connectedCBPeripherals: [CBPeripheral] =
|
|
496
|
-
|
|
713
|
+
let connectedCBPeripherals: [CBPeripheral] =
|
|
714
|
+
manager?.retrieveConnectedPeripherals(
|
|
715
|
+
withServices: serviceUUIDs
|
|
716
|
+
) ?? []
|
|
717
|
+
|
|
497
718
|
serialQueue.sync {
|
|
498
719
|
for ph in connectedCBPeripherals {
|
|
499
720
|
if let peripheral = peripherals[ph.uuidAsString()] {
|
|
500
721
|
connectedPeripherals.append(peripheral)
|
|
501
722
|
} else {
|
|
502
|
-
peripherals[ph.uuidAsString()] = Peripheral(
|
|
723
|
+
peripherals[ph.uuidAsString()] = Peripheral(
|
|
724
|
+
peripheral: ph
|
|
725
|
+
)
|
|
503
726
|
}
|
|
504
727
|
}
|
|
505
728
|
}
|
|
506
729
|
}
|
|
507
|
-
|
|
730
|
+
|
|
508
731
|
var foundedPeripherals: [[String: Any]] = []
|
|
509
|
-
|
|
732
|
+
|
|
510
733
|
for peripheral in connectedPeripherals {
|
|
511
734
|
foundedPeripherals.append(peripheral.advertisingInfo())
|
|
512
735
|
}
|
|
513
|
-
|
|
736
|
+
|
|
514
737
|
callback([NSNull(), foundedPeripherals])
|
|
515
738
|
}
|
|
516
|
-
|
|
517
|
-
@objc public func isPeripheralConnected(
|
|
518
|
-
|
|
519
|
-
|
|
739
|
+
|
|
740
|
+
@objc public func isPeripheralConnected(
|
|
741
|
+
_ peripheralUUID: String,
|
|
742
|
+
callback: @escaping RCTResponseSenderBlock
|
|
743
|
+
) {
|
|
744
|
+
|
|
520
745
|
if let peripheral = peripherals[peripheralUUID] {
|
|
521
746
|
callback([NSNull(), peripheral.instance.state == .connected])
|
|
522
747
|
} else {
|
|
523
748
|
callback(["Peripheral not found"])
|
|
524
749
|
}
|
|
525
750
|
}
|
|
526
|
-
|
|
751
|
+
|
|
527
752
|
@objc public func isScanning(_ callback: @escaping RCTResponseSenderBlock) {
|
|
528
753
|
if let manager = manager {
|
|
529
754
|
callback([NSNull(), manager.isScanning])
|
|
@@ -531,194 +756,320 @@ import CoreBluetooth
|
|
|
531
756
|
callback(["CBCentralManager not found"])
|
|
532
757
|
}
|
|
533
758
|
}
|
|
534
|
-
|
|
759
|
+
|
|
535
760
|
@objc public func checkState(_ callback: @escaping RCTResponseSenderBlock) {
|
|
536
761
|
if let manager = manager {
|
|
537
762
|
centralManagerDidUpdateState(manager)
|
|
538
|
-
|
|
763
|
+
|
|
539
764
|
let stateName = Helper.centralManagerStateToString(manager.state)
|
|
540
765
|
callback([stateName])
|
|
541
766
|
}
|
|
542
767
|
}
|
|
543
|
-
|
|
544
|
-
@objc public func write(
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
768
|
+
|
|
769
|
+
@objc public func write(
|
|
770
|
+
_ peripheralUUID: String,
|
|
771
|
+
serviceUUID: String,
|
|
772
|
+
characteristicUUID: String,
|
|
773
|
+
message: [UInt8],
|
|
774
|
+
maxByteSize: Int,
|
|
775
|
+
callback: @escaping RCTResponseSenderBlock
|
|
776
|
+
) {
|
|
550
777
|
NSLog("write")
|
|
551
|
-
|
|
552
|
-
guard
|
|
778
|
+
|
|
779
|
+
guard
|
|
780
|
+
let context = getContext(
|
|
781
|
+
peripheralUUID,
|
|
782
|
+
serviceUUIDString: serviceUUID,
|
|
783
|
+
characteristicUUIDString: characteristicUUID,
|
|
784
|
+
prop: CBCharacteristicProperties.write,
|
|
785
|
+
callback: callback
|
|
786
|
+
)
|
|
787
|
+
else {
|
|
553
788
|
return
|
|
554
789
|
}
|
|
555
|
-
|
|
790
|
+
|
|
556
791
|
let dataMessage = Data(message)
|
|
557
|
-
|
|
558
|
-
if let peripheral = context.peripheral,
|
|
559
|
-
let
|
|
560
|
-
|
|
561
|
-
|
|
792
|
+
|
|
793
|
+
if let peripheral = context.peripheral,
|
|
794
|
+
let characteristic = context.characteristic
|
|
795
|
+
{
|
|
796
|
+
let key = Helper.key(
|
|
797
|
+
forPeripheral: peripheral.instance,
|
|
798
|
+
andCharacteristic: characteristic
|
|
799
|
+
)
|
|
800
|
+
insertCallback(
|
|
801
|
+
callback,
|
|
802
|
+
intoDictionary: &writeCallbacks,
|
|
803
|
+
withKey: key
|
|
804
|
+
)
|
|
805
|
+
|
|
562
806
|
if SwiftBleManager.verboseLogging {
|
|
563
|
-
NSLog(
|
|
807
|
+
NSLog(
|
|
808
|
+
"Message to write(\(dataMessage.count)): \(dataMessage.hexadecimalString())"
|
|
809
|
+
)
|
|
564
810
|
}
|
|
565
|
-
|
|
811
|
+
|
|
566
812
|
if dataMessage.count > maxByteSize {
|
|
567
813
|
var count = 0
|
|
568
814
|
var offset = 0
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
815
|
+
var splitMessages = [Data]()
|
|
816
|
+
|
|
817
|
+
while count < dataMessage.count,
|
|
818
|
+
(dataMessage.count - count) > maxByteSize
|
|
819
|
+
{
|
|
820
|
+
let splitMessage = dataMessage.subdata(
|
|
821
|
+
in: offset..<offset + maxByteSize
|
|
822
|
+
)
|
|
823
|
+
splitMessages.append(splitMessage)
|
|
572
824
|
count += maxByteSize
|
|
573
825
|
offset += maxByteSize
|
|
574
826
|
}
|
|
575
|
-
|
|
827
|
+
|
|
576
828
|
if count < dataMessage.count {
|
|
577
|
-
let splitMessage = dataMessage.subdata(
|
|
578
|
-
|
|
829
|
+
let splitMessage = dataMessage.subdata(
|
|
830
|
+
in: offset..<dataMessage.count
|
|
831
|
+
)
|
|
832
|
+
splitMessages.append(splitMessage)
|
|
579
833
|
}
|
|
580
|
-
|
|
834
|
+
|
|
835
|
+
let enqueueResult = enqueueSplitMessages(
|
|
836
|
+
splitMessages,
|
|
837
|
+
forKey: key
|
|
838
|
+
)
|
|
839
|
+
|
|
581
840
|
if SwiftBleManager.verboseLogging {
|
|
582
|
-
NSLog(
|
|
841
|
+
NSLog(
|
|
842
|
+
"Queued splitted message for \(key): \(enqueueResult.remainingCount) chunk(s) pending"
|
|
843
|
+
)
|
|
583
844
|
}
|
|
584
|
-
|
|
585
|
-
if
|
|
586
|
-
peripheral.instance.writeValue(
|
|
845
|
+
|
|
846
|
+
if let firstMessage = enqueueResult.firstChunk {
|
|
847
|
+
peripheral.instance.writeValue(
|
|
848
|
+
firstMessage,
|
|
849
|
+
for: characteristic,
|
|
850
|
+
type: .withResponse
|
|
851
|
+
)
|
|
587
852
|
}
|
|
588
853
|
} else {
|
|
589
|
-
peripheral.instance.writeValue(
|
|
854
|
+
peripheral.instance.writeValue(
|
|
855
|
+
dataMessage,
|
|
856
|
+
for: characteristic,
|
|
857
|
+
type: .withResponse
|
|
858
|
+
)
|
|
590
859
|
}
|
|
591
860
|
}
|
|
592
861
|
}
|
|
593
|
-
|
|
594
|
-
@objc public func writeWithoutResponse(
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
862
|
+
|
|
863
|
+
@objc public func writeWithoutResponse(
|
|
864
|
+
_ peripheralUUID: String,
|
|
865
|
+
serviceUUID: String,
|
|
866
|
+
characteristicUUID: String,
|
|
867
|
+
message: [UInt8],
|
|
868
|
+
maxByteSize: Int,
|
|
869
|
+
queueSleepTime: Int,
|
|
870
|
+
callback: @escaping RCTResponseSenderBlock
|
|
871
|
+
) {
|
|
601
872
|
NSLog("writeWithoutResponse")
|
|
602
|
-
|
|
603
|
-
guard
|
|
873
|
+
|
|
874
|
+
guard
|
|
875
|
+
let context = getContext(
|
|
876
|
+
peripheralUUID,
|
|
877
|
+
serviceUUIDString: serviceUUID,
|
|
878
|
+
characteristicUUIDString: characteristicUUID,
|
|
879
|
+
prop: CBCharacteristicProperties.writeWithoutResponse,
|
|
880
|
+
callback: callback
|
|
881
|
+
)
|
|
882
|
+
else {
|
|
604
883
|
return
|
|
605
884
|
}
|
|
606
|
-
|
|
885
|
+
|
|
607
886
|
let dataMessage = Data(message)
|
|
608
|
-
|
|
887
|
+
|
|
609
888
|
if SwiftBleManager.verboseLogging {
|
|
610
|
-
NSLog(
|
|
889
|
+
NSLog(
|
|
890
|
+
"Message to write(\(dataMessage.count)): \(dataMessage.hexadecimalString())"
|
|
891
|
+
)
|
|
611
892
|
}
|
|
612
|
-
|
|
893
|
+
|
|
613
894
|
if dataMessage.count > maxByteSize {
|
|
614
895
|
var offset = 0
|
|
615
896
|
let peripheral = context.peripheral
|
|
616
897
|
guard let characteristic = context.characteristic else { return }
|
|
617
|
-
|
|
898
|
+
|
|
618
899
|
repeat {
|
|
619
900
|
let thisChunkSize = min(maxByteSize, dataMessage.count - offset)
|
|
620
|
-
let chunk = dataMessage.subdata(
|
|
621
|
-
|
|
901
|
+
let chunk = dataMessage.subdata(
|
|
902
|
+
in: offset..<offset + thisChunkSize
|
|
903
|
+
)
|
|
904
|
+
|
|
622
905
|
offset += thisChunkSize
|
|
623
|
-
peripheral?.instance.writeValue(
|
|
624
|
-
|
|
906
|
+
peripheral?.instance.writeValue(
|
|
907
|
+
chunk,
|
|
908
|
+
for: characteristic,
|
|
909
|
+
type: .withoutResponse
|
|
910
|
+
)
|
|
911
|
+
|
|
625
912
|
let sleepTimeSeconds = TimeInterval(queueSleepTime) / 1000
|
|
626
913
|
Thread.sleep(forTimeInterval: sleepTimeSeconds)
|
|
627
914
|
} while offset < dataMessage.count
|
|
628
|
-
|
|
915
|
+
|
|
629
916
|
callback([])
|
|
630
917
|
} else {
|
|
631
918
|
let peripheral = context.peripheral
|
|
632
919
|
guard let characteristic = context.characteristic else { return }
|
|
633
|
-
|
|
634
|
-
peripheral?.instance.writeValue(
|
|
920
|
+
|
|
921
|
+
peripheral?.instance.writeValue(
|
|
922
|
+
dataMessage,
|
|
923
|
+
for: characteristic,
|
|
924
|
+
type: .withoutResponse
|
|
925
|
+
)
|
|
635
926
|
callback([])
|
|
636
927
|
}
|
|
637
928
|
}
|
|
638
|
-
|
|
639
|
-
@objc public func read(
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
929
|
+
|
|
930
|
+
@objc public func read(
|
|
931
|
+
_ peripheralUUID: String,
|
|
932
|
+
serviceUUID: String,
|
|
933
|
+
characteristicUUID: String,
|
|
934
|
+
callback: @escaping RCTResponseSenderBlock
|
|
935
|
+
) {
|
|
643
936
|
NSLog("read")
|
|
644
|
-
|
|
645
|
-
guard
|
|
937
|
+
|
|
938
|
+
guard
|
|
939
|
+
let context = getContext(
|
|
940
|
+
peripheralUUID,
|
|
941
|
+
serviceUUIDString: serviceUUID,
|
|
942
|
+
characteristicUUIDString: characteristicUUID,
|
|
943
|
+
prop: CBCharacteristicProperties.read,
|
|
944
|
+
callback: callback
|
|
945
|
+
)
|
|
946
|
+
else {
|
|
646
947
|
return
|
|
647
948
|
}
|
|
648
|
-
|
|
949
|
+
|
|
649
950
|
let peripheral = context.peripheral
|
|
650
951
|
let characteristic = context.characteristic
|
|
651
|
-
|
|
652
|
-
let key = Helper.key(
|
|
952
|
+
|
|
953
|
+
let key = Helper.key(
|
|
954
|
+
forPeripheral: peripheral!.instance as CBPeripheral,
|
|
955
|
+
andCharacteristic: characteristic!
|
|
956
|
+
)
|
|
653
957
|
insertCallback(callback, intoDictionary: &readCallbacks, withKey: key)
|
|
654
|
-
|
|
958
|
+
|
|
655
959
|
peripheral?.instance.readValue(for: characteristic!) // callback sends value
|
|
656
960
|
}
|
|
657
|
-
|
|
658
|
-
@objc public func startNotificationWithBuffer(
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
961
|
+
|
|
962
|
+
@objc public func startNotificationWithBuffer(
|
|
963
|
+
_ peripheralUUID: String,
|
|
964
|
+
serviceUUID: String,
|
|
965
|
+
characteristicUUID: String,
|
|
966
|
+
bufferLength: NSNumber,
|
|
967
|
+
callback: @escaping RCTResponseSenderBlock
|
|
968
|
+
) {
|
|
663
969
|
NSLog("startNotificationWithBuffer")
|
|
664
|
-
|
|
665
|
-
guard
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
970
|
+
|
|
971
|
+
guard
|
|
972
|
+
let context = getContext(
|
|
973
|
+
peripheralUUID,
|
|
974
|
+
serviceUUIDString: serviceUUID,
|
|
975
|
+
characteristicUUIDString: characteristicUUID,
|
|
976
|
+
prop: CBCharacteristicProperties.notify,
|
|
977
|
+
callback: callback
|
|
978
|
+
)
|
|
979
|
+
else { return }
|
|
672
980
|
guard let peripheral = context.peripheral else { return }
|
|
673
981
|
guard let characteristic = context.characteristic else { return }
|
|
674
|
-
|
|
675
|
-
let key = Helper.key(
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
982
|
+
|
|
983
|
+
let key = Helper.key(
|
|
984
|
+
forPeripheral: (peripheral.instance as CBPeripheral?)!,
|
|
985
|
+
andCharacteristic: characteristic
|
|
986
|
+
)
|
|
987
|
+
insertCallback(
|
|
988
|
+
callback,
|
|
989
|
+
intoDictionary: ¬ificationCallbacks,
|
|
990
|
+
withKey: key
|
|
991
|
+
)
|
|
992
|
+
|
|
993
|
+
self.bufferedCharacteristics[key] = NotifyBufferContainer(
|
|
994
|
+
size: bufferLength.intValue
|
|
995
|
+
)
|
|
996
|
+
|
|
680
997
|
peripheral.instance.setNotifyValue(true, for: characteristic)
|
|
681
998
|
}
|
|
682
|
-
|
|
683
|
-
@objc public func startNotification(
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
999
|
+
|
|
1000
|
+
@objc public func startNotification(
|
|
1001
|
+
_ peripheralUUID: String,
|
|
1002
|
+
serviceUUID: String,
|
|
1003
|
+
characteristicUUID: String,
|
|
1004
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1005
|
+
) {
|
|
687
1006
|
NSLog("startNotification")
|
|
688
|
-
|
|
689
|
-
guard
|
|
1007
|
+
|
|
1008
|
+
guard
|
|
1009
|
+
let context = getContext(
|
|
1010
|
+
peripheralUUID,
|
|
1011
|
+
serviceUUIDString: serviceUUID,
|
|
1012
|
+
characteristicUUIDString: characteristicUUID,
|
|
1013
|
+
prop: CBCharacteristicProperties.notify,
|
|
1014
|
+
callback: callback
|
|
1015
|
+
)
|
|
1016
|
+
else {
|
|
690
1017
|
return
|
|
691
1018
|
}
|
|
692
|
-
|
|
1019
|
+
|
|
693
1020
|
guard let peripheral = context.peripheral else { return }
|
|
694
1021
|
guard let characteristic = context.characteristic else { return }
|
|
695
|
-
|
|
696
|
-
let key = Helper.key(
|
|
697
|
-
|
|
698
|
-
|
|
1022
|
+
|
|
1023
|
+
let key = Helper.key(
|
|
1024
|
+
forPeripheral: (peripheral.instance as CBPeripheral?)!,
|
|
1025
|
+
andCharacteristic: characteristic
|
|
1026
|
+
)
|
|
1027
|
+
insertCallback(
|
|
1028
|
+
callback,
|
|
1029
|
+
intoDictionary: ¬ificationCallbacks,
|
|
1030
|
+
withKey: key
|
|
1031
|
+
)
|
|
1032
|
+
|
|
699
1033
|
peripheral.instance.setNotifyValue(true, for: characteristic)
|
|
700
1034
|
}
|
|
701
|
-
|
|
702
|
-
@objc public func stopNotification(
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
1035
|
+
|
|
1036
|
+
@objc public func stopNotification(
|
|
1037
|
+
_ peripheralUUID: String,
|
|
1038
|
+
serviceUUID: String,
|
|
1039
|
+
characteristicUUID: String,
|
|
1040
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1041
|
+
) {
|
|
706
1042
|
NSLog("stopNotification")
|
|
707
|
-
|
|
708
|
-
guard
|
|
1043
|
+
|
|
1044
|
+
guard
|
|
1045
|
+
let context = getContext(
|
|
1046
|
+
peripheralUUID,
|
|
1047
|
+
serviceUUIDString: serviceUUID,
|
|
1048
|
+
characteristicUUIDString: characteristicUUID,
|
|
1049
|
+
prop: CBCharacteristicProperties.notify,
|
|
1050
|
+
callback: callback
|
|
1051
|
+
)
|
|
1052
|
+
else {
|
|
709
1053
|
return
|
|
710
1054
|
}
|
|
711
|
-
|
|
1055
|
+
|
|
712
1056
|
let peripheral = context.peripheral
|
|
713
1057
|
guard let characteristic = context.characteristic else { return }
|
|
714
|
-
|
|
1058
|
+
|
|
715
1059
|
if characteristic.isNotifying {
|
|
716
|
-
let key = Helper.key(
|
|
717
|
-
|
|
718
|
-
|
|
1060
|
+
let key = Helper.key(
|
|
1061
|
+
forPeripheral: (peripheral?.instance as CBPeripheral?)!,
|
|
1062
|
+
andCharacteristic: characteristic
|
|
1063
|
+
)
|
|
1064
|
+
insertCallback(
|
|
1065
|
+
callback,
|
|
1066
|
+
intoDictionary: &stopNotificationCallbacks,
|
|
1067
|
+
withKey: key
|
|
1068
|
+
)
|
|
1069
|
+
|
|
719
1070
|
// Remove any buffered data if notification was started with buffer
|
|
720
1071
|
self.bufferedCharacteristics.removeValue(forKey: key)
|
|
721
|
-
|
|
1072
|
+
|
|
722
1073
|
peripheral?.instance.setNotifyValue(false, for: characteristic)
|
|
723
1074
|
NSLog("Characteristic stopped notifying")
|
|
724
1075
|
} else {
|
|
@@ -726,153 +1077,236 @@ import CoreBluetooth
|
|
|
726
1077
|
callback([])
|
|
727
1078
|
}
|
|
728
1079
|
}
|
|
729
|
-
|
|
730
|
-
@objc public func getMaximumWriteValueLengthForWithoutResponse(
|
|
731
|
-
|
|
1080
|
+
|
|
1081
|
+
@objc public func getMaximumWriteValueLengthForWithoutResponse(
|
|
1082
|
+
_ peripheralUUID: String,
|
|
1083
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1084
|
+
) {
|
|
732
1085
|
NSLog("getMaximumWriteValueLengthForWithoutResponse")
|
|
733
|
-
|
|
1086
|
+
|
|
734
1087
|
guard let peripheral = peripherals[peripheralUUID] else {
|
|
735
1088
|
callback(["Peripheral not found or not connected"])
|
|
736
1089
|
return
|
|
737
1090
|
}
|
|
738
|
-
|
|
1091
|
+
|
|
739
1092
|
if peripheral.instance.state == .connected {
|
|
740
|
-
let max = NSNumber(
|
|
1093
|
+
let max = NSNumber(
|
|
1094
|
+
value: peripheral.instance.maximumWriteValueLength(
|
|
1095
|
+
for: .withoutResponse
|
|
1096
|
+
)
|
|
1097
|
+
)
|
|
741
1098
|
callback([NSNull(), max])
|
|
742
1099
|
} else {
|
|
743
1100
|
callback(["Peripheral not found or not connected"])
|
|
744
1101
|
}
|
|
745
1102
|
}
|
|
746
|
-
|
|
747
|
-
@objc public func getMaximumWriteValueLengthForWithResponse(
|
|
748
|
-
|
|
1103
|
+
|
|
1104
|
+
@objc public func getMaximumWriteValueLengthForWithResponse(
|
|
1105
|
+
_ peripheralUUID: String,
|
|
1106
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1107
|
+
) {
|
|
749
1108
|
NSLog("getMaximumWriteValueLengthForWithResponse")
|
|
750
|
-
|
|
1109
|
+
|
|
751
1110
|
guard let peripheral = peripherals[peripheralUUID] else {
|
|
752
1111
|
callback(["Peripheral not found or not connected"])
|
|
753
1112
|
return
|
|
754
1113
|
}
|
|
755
|
-
|
|
1114
|
+
|
|
756
1115
|
if peripheral.instance.state == .connected {
|
|
757
|
-
let max = NSNumber(
|
|
1116
|
+
let max = NSNumber(
|
|
1117
|
+
value: peripheral.instance.maximumWriteValueLength(
|
|
1118
|
+
for: .withResponse
|
|
1119
|
+
)
|
|
1120
|
+
)
|
|
758
1121
|
callback([NSNull(), max])
|
|
759
1122
|
} else {
|
|
760
1123
|
callback(["Peripheral not found or not connected"])
|
|
761
1124
|
}
|
|
762
1125
|
}
|
|
763
|
-
|
|
764
|
-
public func centralManager(
|
|
765
|
-
|
|
1126
|
+
|
|
1127
|
+
public func centralManager(
|
|
1128
|
+
_ central: CBCentralManager,
|
|
1129
|
+
willRestoreState dict: [String: Any]
|
|
1130
|
+
) {
|
|
1131
|
+
if let restoredPeripherals = dict[
|
|
1132
|
+
CBCentralManagerRestoredStatePeripheralsKey
|
|
1133
|
+
] as? [CBPeripheral], restoredPeripherals.count > 0 {
|
|
766
1134
|
serialQueue.sync {
|
|
767
1135
|
var data = [[String: Any]]()
|
|
768
1136
|
for peripheral in restoredPeripherals {
|
|
769
|
-
let p = Peripheral(peripheral:peripheral)
|
|
1137
|
+
let p = Peripheral(peripheral: peripheral)
|
|
770
1138
|
peripherals[peripheral.uuidAsString()] = p
|
|
771
1139
|
data.append(p.advertisingInfo())
|
|
772
1140
|
peripheral.delegate = self
|
|
773
1141
|
}
|
|
774
|
-
self.bleManager?.emit(onCentralManagerWillRestoreState: [
|
|
1142
|
+
self.bleManager?.emit(onCentralManagerWillRestoreState: [
|
|
1143
|
+
"peripherals": data
|
|
1144
|
+
])
|
|
775
1145
|
}
|
|
776
1146
|
}
|
|
777
1147
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
1148
|
+
|
|
1149
|
+
public func centralManager(
|
|
1150
|
+
_ central: CBCentralManager,
|
|
1151
|
+
didConnect peripheral: CBPeripheral
|
|
1152
|
+
) {
|
|
782
1153
|
NSLog("Peripheral Connected: \(peripheral.uuidAsString() )")
|
|
783
1154
|
peripheral.delegate = self
|
|
784
|
-
|
|
1155
|
+
|
|
785
1156
|
/*
|
|
786
1157
|
The state of the peripheral isn't necessarily updated until a small
|
|
787
1158
|
delay after didConnectPeripheral is called and in the meantime
|
|
788
1159
|
didFailToConnectPeripheral may be called
|
|
789
1160
|
*/
|
|
790
1161
|
DispatchQueue.main.async {
|
|
791
|
-
Timer.scheduledTimer(withTimeInterval: 0.002, repeats: false) {
|
|
1162
|
+
Timer.scheduledTimer(withTimeInterval: 0.002, repeats: false) {
|
|
1163
|
+
timer in
|
|
792
1164
|
// didFailToConnectPeripheral should have been called already if not connected by now
|
|
793
|
-
self.invokeAndClearDictionary(
|
|
794
|
-
|
|
1165
|
+
self.invokeAndClearDictionary(
|
|
1166
|
+
&self.connectCallbacks,
|
|
1167
|
+
withKey: peripheral.uuidAsString(),
|
|
1168
|
+
usingParameters: [NSNull()]
|
|
1169
|
+
)
|
|
1170
|
+
|
|
795
1171
|
self.connectedPeripherals.insert(peripheral.uuidAsString())
|
|
796
|
-
self.bleManager?.emit(onConnectPeripheral: [
|
|
1172
|
+
self.bleManager?.emit(onConnectPeripheral: [
|
|
1173
|
+
"peripheral": peripheral.uuidAsString()
|
|
1174
|
+
])
|
|
797
1175
|
}
|
|
798
1176
|
}
|
|
799
1177
|
}
|
|
800
|
-
|
|
801
|
-
public func centralManager(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
1178
|
+
|
|
1179
|
+
public func centralManager(
|
|
1180
|
+
_ central: CBCentralManager,
|
|
1181
|
+
didFailToConnect peripheral: CBPeripheral,
|
|
1182
|
+
error: Error?
|
|
1183
|
+
) {
|
|
1184
|
+
let errorStr =
|
|
1185
|
+
"Peripheral connection failure: \(peripheral.uuidAsString() ) (\(error?.localizedDescription ?? "")"
|
|
805
1186
|
NSLog(errorStr)
|
|
806
|
-
|
|
807
|
-
invokeAndClearDictionary(
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
1187
|
+
|
|
1188
|
+
invokeAndClearDictionary(
|
|
1189
|
+
&connectCallbacks,
|
|
1190
|
+
withKey: peripheral.uuidAsString(),
|
|
1191
|
+
usingParameters: [errorStr]
|
|
1192
|
+
)
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
public func centralManager(
|
|
1196
|
+
_ central: CBCentralManager,
|
|
1197
|
+
didDisconnectPeripheral peripheral:
|
|
1198
|
+
CBPeripheral,
|
|
1199
|
+
error: Error?
|
|
1200
|
+
) {
|
|
1201
|
+
let peripheralUUIDString: String = peripheral.uuidAsString()
|
|
814
1202
|
NSLog("Peripheral Disconnected: \(peripheralUUIDString)")
|
|
815
|
-
|
|
1203
|
+
|
|
816
1204
|
if let error = error {
|
|
817
1205
|
NSLog("Error: \(error)")
|
|
818
1206
|
}
|
|
819
|
-
|
|
1207
|
+
|
|
820
1208
|
let errorStr = "Peripheral did disconnect: \(peripheralUUIDString)"
|
|
821
|
-
|
|
822
|
-
invokeAndClearDictionary(
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
1209
|
+
|
|
1210
|
+
invokeAndClearDictionary(
|
|
1211
|
+
&connectCallbacks,
|
|
1212
|
+
withKey: peripheralUUIDString,
|
|
1213
|
+
usingParameters: [errorStr]
|
|
1214
|
+
)
|
|
1215
|
+
invokeAndClearDictionary(
|
|
1216
|
+
&readRSSICallbacks,
|
|
1217
|
+
withKey: peripheralUUIDString,
|
|
1218
|
+
usingParameters: [errorStr]
|
|
1219
|
+
)
|
|
1220
|
+
invokeAndClearDictionary(
|
|
1221
|
+
&retrieveServicesCallbacks,
|
|
1222
|
+
withKey: peripheralUUIDString,
|
|
1223
|
+
usingParameters: [errorStr]
|
|
1224
|
+
)
|
|
1225
|
+
|
|
827
1226
|
for key in readCallbacks.keys {
|
|
828
|
-
if let keyString = key as String?,
|
|
829
|
-
|
|
1227
|
+
if let keyString = key as String?,
|
|
1228
|
+
keyString.hasPrefix(peripheralUUIDString)
|
|
1229
|
+
{
|
|
1230
|
+
invokeAndClearDictionary(
|
|
1231
|
+
&readCallbacks,
|
|
1232
|
+
withKey: key,
|
|
1233
|
+
usingParameters: [errorStr]
|
|
1234
|
+
)
|
|
830
1235
|
}
|
|
831
1236
|
}
|
|
832
|
-
|
|
1237
|
+
|
|
833
1238
|
for key in writeCallbacks.keys {
|
|
834
|
-
if let keyString = key as String?,
|
|
835
|
-
|
|
1239
|
+
if let keyString = key as String?,
|
|
1240
|
+
keyString.hasPrefix(peripheralUUIDString)
|
|
1241
|
+
{
|
|
1242
|
+
invokeAndClearDictionary(
|
|
1243
|
+
&writeCallbacks,
|
|
1244
|
+
withKey: key,
|
|
1245
|
+
usingParameters: [errorStr]
|
|
1246
|
+
)
|
|
836
1247
|
}
|
|
837
1248
|
}
|
|
838
|
-
|
|
1249
|
+
|
|
839
1250
|
for key in notificationCallbacks.keys {
|
|
840
|
-
if let keyString = key as String?,
|
|
841
|
-
|
|
1251
|
+
if let keyString = key as String?,
|
|
1252
|
+
keyString.hasPrefix(peripheralUUIDString)
|
|
1253
|
+
{
|
|
1254
|
+
invokeAndClearDictionary(
|
|
1255
|
+
¬ificationCallbacks,
|
|
1256
|
+
withKey: key,
|
|
1257
|
+
usingParameters: [errorStr]
|
|
1258
|
+
)
|
|
842
1259
|
}
|
|
843
1260
|
}
|
|
844
|
-
|
|
1261
|
+
|
|
845
1262
|
for key in readDescriptorCallbacks.keys {
|
|
846
|
-
if let keyString = key as String?,
|
|
847
|
-
|
|
1263
|
+
if let keyString = key as String?,
|
|
1264
|
+
keyString.hasPrefix(peripheralUUIDString)
|
|
1265
|
+
{
|
|
1266
|
+
invokeAndClearDictionary(
|
|
1267
|
+
&readDescriptorCallbacks,
|
|
1268
|
+
withKey: key,
|
|
1269
|
+
usingParameters: [errorStr]
|
|
1270
|
+
)
|
|
848
1271
|
}
|
|
849
1272
|
}
|
|
850
|
-
|
|
1273
|
+
|
|
851
1274
|
for key in stopNotificationCallbacks.keys {
|
|
852
|
-
if let keyString = key as String?,
|
|
853
|
-
|
|
1275
|
+
if let keyString = key as String?,
|
|
1276
|
+
keyString.hasPrefix(peripheralUUIDString)
|
|
1277
|
+
{
|
|
1278
|
+
invokeAndClearDictionary(
|
|
1279
|
+
&stopNotificationCallbacks,
|
|
1280
|
+
withKey: key,
|
|
1281
|
+
usingParameters: [errorStr]
|
|
1282
|
+
)
|
|
854
1283
|
}
|
|
855
1284
|
}
|
|
856
|
-
|
|
857
|
-
let bufferedCharacteristicsKeysToRemove = bufferedCharacteristics.keys
|
|
858
|
-
|
|
859
|
-
|
|
1285
|
+
|
|
1286
|
+
let bufferedCharacteristicsKeysToRemove = bufferedCharacteristics.keys
|
|
1287
|
+
.filter { key in
|
|
1288
|
+
if let keyString = key as String? {
|
|
1289
|
+
return keyString.hasPrefix(peripheralUUIDString)
|
|
1290
|
+
}
|
|
1291
|
+
return false
|
|
860
1292
|
}
|
|
861
|
-
return false
|
|
862
|
-
}
|
|
863
1293
|
for key in bufferedCharacteristicsKeysToRemove {
|
|
864
1294
|
bufferedCharacteristics.removeValue(forKey: key)
|
|
865
1295
|
}
|
|
866
|
-
|
|
1296
|
+
|
|
867
1297
|
connectedPeripherals.remove(peripheralUUIDString)
|
|
868
|
-
if let e:Error = error {
|
|
869
|
-
self.bleManager?.emit(onDisconnectPeripheral: [
|
|
1298
|
+
if let e: Error = error {
|
|
1299
|
+
self.bleManager?.emit(onDisconnectPeripheral: [
|
|
1300
|
+
"peripheral": peripheralUUIDString, "domain": e._domain,
|
|
1301
|
+
"code": e._code, "description": e.localizedDescription,
|
|
1302
|
+
])
|
|
870
1303
|
} else {
|
|
871
|
-
self.bleManager?.emit(onDisconnectPeripheral: [
|
|
1304
|
+
self.bleManager?.emit(onDisconnectPeripheral: [
|
|
1305
|
+
"peripheral": peripheralUUIDString
|
|
1306
|
+
])
|
|
872
1307
|
}
|
|
873
1308
|
}
|
|
874
|
-
|
|
875
|
-
|
|
1309
|
+
|
|
876
1310
|
public func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
|
877
1311
|
let stateName = Helper.centralManagerStateToString(central.state)
|
|
878
1312
|
self.bleManager?.emit(onDidUpdateState: ["state": stateName])
|
|
@@ -880,20 +1314,26 @@ import CoreBluetooth
|
|
|
880
1314
|
for peripheralUUID in connectedPeripherals {
|
|
881
1315
|
if let peripheral = peripherals[peripheralUUID] {
|
|
882
1316
|
if peripheral.instance.state == .disconnected {
|
|
883
|
-
self.centralManager(
|
|
1317
|
+
self.centralManager(
|
|
1318
|
+
manager!,
|
|
1319
|
+
didDisconnectPeripheral: peripheral.instance,
|
|
1320
|
+
error: nil
|
|
1321
|
+
)
|
|
884
1322
|
}
|
|
885
1323
|
}
|
|
886
1324
|
}
|
|
887
1325
|
}
|
|
888
1326
|
}
|
|
889
|
-
|
|
890
|
-
func handleDiscoveredPeripheral(
|
|
891
|
-
|
|
892
|
-
|
|
1327
|
+
|
|
1328
|
+
func handleDiscoveredPeripheral(
|
|
1329
|
+
_ peripheral: CBPeripheral,
|
|
1330
|
+
advertisementData: [String: Any],
|
|
1331
|
+
rssi: NSNumber
|
|
1332
|
+
) {
|
|
893
1333
|
if SwiftBleManager.verboseLogging {
|
|
894
|
-
NSLog("Discover peripheral: \(peripheral.name ?? "NO NAME")")
|
|
1334
|
+
NSLog("Discover peripheral: \(peripheral.name ?? "NO NAME")")
|
|
895
1335
|
}
|
|
896
|
-
|
|
1336
|
+
|
|
897
1337
|
var cp: Peripheral? = nil
|
|
898
1338
|
serialQueue.sync {
|
|
899
1339
|
if let p = peripherals[peripheral.uuidAsString()] {
|
|
@@ -901,39 +1341,60 @@ import CoreBluetooth
|
|
|
901
1341
|
cp?.setRSSI(rssi)
|
|
902
1342
|
cp?.setAdvertisementData(advertisementData)
|
|
903
1343
|
} else {
|
|
904
|
-
cp = Peripheral(
|
|
1344
|
+
cp = Peripheral(
|
|
1345
|
+
peripheral: peripheral,
|
|
1346
|
+
rssi: rssi,
|
|
1347
|
+
advertisementData: advertisementData
|
|
1348
|
+
)
|
|
905
1349
|
peripherals[peripheral.uuidAsString()] = cp
|
|
906
1350
|
}
|
|
907
1351
|
}
|
|
908
|
-
|
|
1352
|
+
|
|
909
1353
|
self.bleManager?.emit(onDiscoverPeripheral: cp?.advertisingInfo())
|
|
910
1354
|
}
|
|
911
|
-
|
|
912
|
-
public func centralManager(
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1355
|
+
|
|
1356
|
+
public func centralManager(
|
|
1357
|
+
_ central: CBCentralManager,
|
|
1358
|
+
didDiscover peripheral: CBPeripheral,
|
|
1359
|
+
advertisementData: [String: Any],
|
|
1360
|
+
rssi RSSI: NSNumber
|
|
1361
|
+
) {
|
|
916
1362
|
if exactAdvertisingName.count > 0 {
|
|
917
1363
|
if let peripheralName = peripheral.name {
|
|
918
1364
|
if exactAdvertisingName.contains(peripheralName) {
|
|
919
|
-
handleDiscoveredPeripheral(
|
|
1365
|
+
handleDiscoveredPeripheral(
|
|
1366
|
+
peripheral,
|
|
1367
|
+
advertisementData: advertisementData,
|
|
1368
|
+
rssi: RSSI
|
|
1369
|
+
)
|
|
920
1370
|
} else {
|
|
921
|
-
if let localName = advertisementData[
|
|
1371
|
+
if let localName = advertisementData[
|
|
1372
|
+
CBAdvertisementDataLocalNameKey
|
|
1373
|
+
] as? String {
|
|
922
1374
|
if exactAdvertisingName.contains(localName) {
|
|
923
|
-
handleDiscoveredPeripheral(
|
|
1375
|
+
handleDiscoveredPeripheral(
|
|
1376
|
+
peripheral,
|
|
1377
|
+
advertisementData: advertisementData,
|
|
1378
|
+
rssi: RSSI
|
|
1379
|
+
)
|
|
924
1380
|
}
|
|
925
1381
|
}
|
|
926
1382
|
}
|
|
927
1383
|
}
|
|
928
1384
|
} else {
|
|
929
|
-
handleDiscoveredPeripheral(
|
|
1385
|
+
handleDiscoveredPeripheral(
|
|
1386
|
+
peripheral,
|
|
1387
|
+
advertisementData: advertisementData,
|
|
1388
|
+
rssi: RSSI
|
|
1389
|
+
)
|
|
930
1390
|
}
|
|
931
|
-
|
|
932
|
-
|
|
1391
|
+
|
|
933
1392
|
}
|
|
934
|
-
|
|
935
|
-
public func peripheral(
|
|
936
|
-
|
|
1393
|
+
|
|
1394
|
+
public func peripheral(
|
|
1395
|
+
_ peripheral: CBPeripheral,
|
|
1396
|
+
didDiscoverServices error: Error?
|
|
1397
|
+
) {
|
|
937
1398
|
if let error = error {
|
|
938
1399
|
NSLog("Error: \(error)")
|
|
939
1400
|
return
|
|
@@ -941,35 +1402,42 @@ import CoreBluetooth
|
|
|
941
1402
|
if SwiftBleManager.verboseLogging {
|
|
942
1403
|
NSLog("Services Discover")
|
|
943
1404
|
}
|
|
944
|
-
|
|
1405
|
+
|
|
945
1406
|
var servicesForPeripheral = Set<CBService>()
|
|
946
1407
|
servicesForPeripheral.formUnion(peripheral.services ?? [])
|
|
947
|
-
retrieveServicesLatches[peripheral.uuidAsString()] =
|
|
948
|
-
|
|
1408
|
+
retrieveServicesLatches[peripheral.uuidAsString()] =
|
|
1409
|
+
servicesForPeripheral
|
|
1410
|
+
|
|
949
1411
|
if let services = peripheral.services {
|
|
950
1412
|
for service in services {
|
|
951
1413
|
if SwiftBleManager.verboseLogging {
|
|
952
|
-
NSLog(
|
|
1414
|
+
NSLog(
|
|
1415
|
+
"Service \(service.uuid.uuidString) \(service.description)"
|
|
1416
|
+
)
|
|
953
1417
|
}
|
|
954
|
-
peripheral.discoverIncludedServices(nil, for: service)
|
|
955
|
-
peripheral.discoverCharacteristics(nil, for: service)
|
|
1418
|
+
peripheral.discoverIncludedServices(nil, for: service) // discover included services
|
|
1419
|
+
peripheral.discoverCharacteristics(nil, for: service) // discover characteristics for service
|
|
956
1420
|
}
|
|
957
1421
|
}
|
|
958
1422
|
}
|
|
959
|
-
|
|
960
|
-
public func peripheral(
|
|
961
|
-
|
|
962
|
-
|
|
1423
|
+
|
|
1424
|
+
public func peripheral(
|
|
1425
|
+
_ peripheral: CBPeripheral,
|
|
1426
|
+
didDiscoverIncludedServicesFor service: CBService,
|
|
1427
|
+
error: Error?
|
|
1428
|
+
) {
|
|
963
1429
|
if let error = error {
|
|
964
1430
|
NSLog("Error: \(error)")
|
|
965
1431
|
return
|
|
966
1432
|
}
|
|
967
|
-
peripheral.discoverCharacteristics(nil, for: service)
|
|
1433
|
+
peripheral.discoverCharacteristics(nil, for: service) // discover characteristics for included service
|
|
968
1434
|
}
|
|
969
|
-
|
|
970
|
-
public func peripheral(
|
|
971
|
-
|
|
972
|
-
|
|
1435
|
+
|
|
1436
|
+
public func peripheral(
|
|
1437
|
+
_ peripheral: CBPeripheral,
|
|
1438
|
+
didDiscoverCharacteristicsFor service: CBService,
|
|
1439
|
+
error: Error?
|
|
1440
|
+
) {
|
|
973
1441
|
if let error = error {
|
|
974
1442
|
NSLog("Error: \(error)")
|
|
975
1443
|
return
|
|
@@ -977,200 +1445,306 @@ import CoreBluetooth
|
|
|
977
1445
|
if SwiftBleManager.verboseLogging {
|
|
978
1446
|
NSLog("Characteristics For Service Discover")
|
|
979
1447
|
}
|
|
980
|
-
|
|
1448
|
+
|
|
981
1449
|
var characteristicsForService = Set<CBCharacteristic>()
|
|
982
1450
|
characteristicsForService.formUnion(service.characteristics ?? [])
|
|
983
|
-
characteristicsLatches[service.uuid.uuidString] =
|
|
984
|
-
|
|
1451
|
+
characteristicsLatches[service.uuid.uuidString] =
|
|
1452
|
+
characteristicsForService
|
|
1453
|
+
|
|
985
1454
|
if let characteristics = service.characteristics {
|
|
986
1455
|
for characteristic in characteristics {
|
|
987
1456
|
peripheral.discoverDescriptors(for: characteristic)
|
|
988
1457
|
}
|
|
989
1458
|
}
|
|
990
1459
|
}
|
|
991
|
-
|
|
992
|
-
public func peripheral(
|
|
993
|
-
|
|
994
|
-
|
|
1460
|
+
|
|
1461
|
+
public func peripheral(
|
|
1462
|
+
_ peripheral: CBPeripheral,
|
|
1463
|
+
didDiscoverDescriptorsFor characteristic: CBCharacteristic,
|
|
1464
|
+
error: Error?
|
|
1465
|
+
) {
|
|
995
1466
|
if let error = error {
|
|
996
1467
|
NSLog("Error: \(error)")
|
|
997
1468
|
return
|
|
998
1469
|
}
|
|
999
|
-
let peripheralUUIDString:String = peripheral.uuidAsString()
|
|
1000
|
-
let serviceUUIDString:String =
|
|
1001
|
-
|
|
1470
|
+
let peripheralUUIDString: String = peripheral.uuidAsString()
|
|
1471
|
+
let serviceUUIDString: String =
|
|
1472
|
+
(characteristic.service?.uuid.uuidString)!
|
|
1473
|
+
|
|
1002
1474
|
if SwiftBleManager.verboseLogging {
|
|
1003
|
-
NSLog(
|
|
1475
|
+
NSLog(
|
|
1476
|
+
"Descriptor For Characteristic Discover \(serviceUUIDString) \(characteristic.uuid.uuidString)"
|
|
1477
|
+
)
|
|
1004
1478
|
}
|
|
1005
|
-
|
|
1006
|
-
if var servicesLatch = retrieveServicesLatches[peripheralUUIDString],
|
|
1007
|
-
|
|
1479
|
+
|
|
1480
|
+
if var servicesLatch = retrieveServicesLatches[peripheralUUIDString],
|
|
1481
|
+
var characteristicsLatch = characteristicsLatches[serviceUUIDString]
|
|
1482
|
+
{
|
|
1483
|
+
|
|
1008
1484
|
characteristicsLatch.remove(characteristic)
|
|
1009
1485
|
characteristicsLatches[serviceUUIDString] = characteristicsLatch
|
|
1010
|
-
|
|
1486
|
+
|
|
1011
1487
|
if characteristicsLatch.isEmpty {
|
|
1012
1488
|
// All characteristics for this service have been checked
|
|
1013
1489
|
servicesLatch.remove(characteristic.service!)
|
|
1014
1490
|
retrieveServicesLatches[peripheralUUIDString] = servicesLatch
|
|
1015
|
-
|
|
1491
|
+
|
|
1016
1492
|
if servicesLatch.isEmpty {
|
|
1017
1493
|
// All characteristics and services have been checked
|
|
1018
1494
|
if let peripheral = peripherals[peripheral.uuidAsString()] {
|
|
1019
|
-
invokeAndClearDictionary(
|
|
1495
|
+
invokeAndClearDictionary(
|
|
1496
|
+
&retrieveServicesCallbacks,
|
|
1497
|
+
withKey: peripheralUUIDString,
|
|
1498
|
+
usingParameters: [
|
|
1499
|
+
NSNull(), peripheral.servicesInfo(),
|
|
1500
|
+
]
|
|
1501
|
+
)
|
|
1020
1502
|
}
|
|
1021
|
-
characteristicsLatches.removeValue(
|
|
1022
|
-
|
|
1503
|
+
characteristicsLatches.removeValue(
|
|
1504
|
+
forKey: serviceUUIDString
|
|
1505
|
+
)
|
|
1506
|
+
retrieveServicesLatches.removeValue(
|
|
1507
|
+
forKey: peripheralUUIDString
|
|
1508
|
+
)
|
|
1023
1509
|
}
|
|
1024
1510
|
}
|
|
1025
|
-
|
|
1511
|
+
|
|
1026
1512
|
}
|
|
1027
1513
|
}
|
|
1028
|
-
|
|
1029
|
-
public func peripheral(
|
|
1030
|
-
|
|
1031
|
-
|
|
1514
|
+
|
|
1515
|
+
public func peripheral(
|
|
1516
|
+
_ peripheral: CBPeripheral,
|
|
1517
|
+
didReadRSSI RSSI: NSNumber,
|
|
1518
|
+
error: Error?
|
|
1519
|
+
) {
|
|
1032
1520
|
if SwiftBleManager.verboseLogging {
|
|
1033
1521
|
print("didReadRSSI \(RSSI)")
|
|
1034
1522
|
}
|
|
1035
|
-
|
|
1523
|
+
|
|
1036
1524
|
if let error = error {
|
|
1037
|
-
invokeAndClearDictionary(
|
|
1525
|
+
invokeAndClearDictionary(
|
|
1526
|
+
&readRSSICallbacks,
|
|
1527
|
+
withKey: peripheral.uuidAsString(),
|
|
1528
|
+
usingParameters: [error.localizedDescription, RSSI]
|
|
1529
|
+
)
|
|
1038
1530
|
} else {
|
|
1039
|
-
invokeAndClearDictionary(
|
|
1531
|
+
invokeAndClearDictionary(
|
|
1532
|
+
&readRSSICallbacks,
|
|
1533
|
+
withKey: peripheral.uuidAsString(),
|
|
1534
|
+
usingParameters: [NSNull(), RSSI]
|
|
1535
|
+
)
|
|
1040
1536
|
}
|
|
1041
1537
|
}
|
|
1042
|
-
|
|
1043
|
-
public func peripheral(
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1538
|
+
|
|
1539
|
+
public func peripheral(
|
|
1540
|
+
_ peripheral: CBPeripheral,
|
|
1541
|
+
didUpdateValueFor descriptor: CBDescriptor,
|
|
1542
|
+
error: Error?
|
|
1543
|
+
) {
|
|
1544
|
+
let key = Helper.key(
|
|
1545
|
+
forPeripheral: peripheral,
|
|
1546
|
+
andCharacteristic: descriptor.characteristic!,
|
|
1547
|
+
andDescriptor: descriptor
|
|
1548
|
+
)
|
|
1549
|
+
|
|
1048
1550
|
if let error = error {
|
|
1049
|
-
NSLog(
|
|
1050
|
-
|
|
1551
|
+
NSLog(
|
|
1552
|
+
"Error reading descriptor value for \(descriptor.uuid) on characteristic \(descriptor.characteristic!.uuid) :\(error)"
|
|
1553
|
+
)
|
|
1554
|
+
invokeAndClearDictionary(
|
|
1555
|
+
&readDescriptorCallbacks,
|
|
1556
|
+
withKey: key,
|
|
1557
|
+
usingParameters: [error.localizedDescription, NSNull()]
|
|
1558
|
+
)
|
|
1051
1559
|
return
|
|
1052
1560
|
}
|
|
1053
|
-
|
|
1561
|
+
|
|
1054
1562
|
if let descriptorValue = descriptor.value as? Data {
|
|
1055
|
-
NSLog(
|
|
1563
|
+
NSLog(
|
|
1564
|
+
"Read value [descriptor: \(descriptor.uuid), characteristic: \(descriptor.characteristic!.uuid)]: (\(descriptorValue.count)) \(descriptorValue.hexadecimalString())"
|
|
1565
|
+
)
|
|
1056
1566
|
} else {
|
|
1057
|
-
NSLog(
|
|
1567
|
+
NSLog(
|
|
1568
|
+
"Read value [descriptor: \(descriptor.uuid), characteristic: \(descriptor.characteristic!.uuid)]: \(String(describing: descriptor.value))"
|
|
1569
|
+
)
|
|
1058
1570
|
}
|
|
1059
|
-
|
|
1571
|
+
|
|
1060
1572
|
if readDescriptorCallbacks[key] != nil {
|
|
1061
1573
|
// The most future proof way of doing this that I could find, other option would be running strcmp on CBUUID strings
|
|
1062
1574
|
// https://developer.apple.com/documentation/corebluetooth/cbuuid/characteristic_descriptors
|
|
1063
1575
|
if let descriptorValue = descriptor.value as? Data {
|
|
1064
|
-
if
|
|
1576
|
+
if SwiftBleManager.verboseLogging {
|
|
1065
1577
|
NSLog("Descriptor value is Data")
|
|
1066
1578
|
}
|
|
1067
|
-
invokeAndClearDictionary(
|
|
1579
|
+
invokeAndClearDictionary(
|
|
1580
|
+
&readDescriptorCallbacks,
|
|
1581
|
+
withKey: key,
|
|
1582
|
+
usingParameters: [NSNull(), descriptorValue.toArray()]
|
|
1583
|
+
)
|
|
1068
1584
|
} else if let descriptorValue = descriptor.value as? NSNumber {
|
|
1069
|
-
if
|
|
1585
|
+
if SwiftBleManager.verboseLogging {
|
|
1070
1586
|
NSLog("Descriptor value is NSNumber")
|
|
1071
1587
|
}
|
|
1072
1588
|
var value = descriptorValue.uint64Value
|
|
1073
|
-
let byteData = Data(
|
|
1074
|
-
|
|
1589
|
+
let byteData = Data(
|
|
1590
|
+
bytes: &value,
|
|
1591
|
+
count: MemoryLayout.size(ofValue: value)
|
|
1592
|
+
)
|
|
1593
|
+
invokeAndClearDictionary(
|
|
1594
|
+
&readDescriptorCallbacks,
|
|
1595
|
+
withKey: key,
|
|
1596
|
+
usingParameters: [NSNull(), byteData.toArray()]
|
|
1597
|
+
)
|
|
1075
1598
|
} else if let descriptorValue = descriptor.value as? String {
|
|
1076
|
-
if
|
|
1599
|
+
if SwiftBleManager.verboseLogging {
|
|
1077
1600
|
NSLog("Descriptor value is String")
|
|
1078
1601
|
}
|
|
1079
1602
|
if let byteData = descriptorValue.data(using: .utf8) {
|
|
1080
|
-
invokeAndClearDictionary(
|
|
1603
|
+
invokeAndClearDictionary(
|
|
1604
|
+
&readDescriptorCallbacks,
|
|
1605
|
+
withKey: key,
|
|
1606
|
+
usingParameters: [NSNull(), byteData.toArray()]
|
|
1607
|
+
)
|
|
1081
1608
|
}
|
|
1082
1609
|
} else {
|
|
1083
|
-
NSLog(
|
|
1610
|
+
NSLog(
|
|
1611
|
+
"Unrecognized type of descriptor: (UUID: \(descriptor.uuid), value type: \(type(of: descriptor.value)), value: \(String(describing: descriptor.value)))"
|
|
1612
|
+
)
|
|
1084
1613
|
if let descriptorValue = descriptor.value as? Data {
|
|
1085
|
-
invokeAndClearDictionary(
|
|
1614
|
+
invokeAndClearDictionary(
|
|
1615
|
+
&readDescriptorCallbacks,
|
|
1616
|
+
withKey: key,
|
|
1617
|
+
usingParameters: [NSNull(), descriptorValue.toArray()]
|
|
1618
|
+
)
|
|
1086
1619
|
}
|
|
1087
1620
|
}
|
|
1088
1621
|
}
|
|
1089
1622
|
}
|
|
1090
|
-
|
|
1091
|
-
public func peripheral(
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1623
|
+
|
|
1624
|
+
public func peripheral(
|
|
1625
|
+
_ peripheral: CBPeripheral,
|
|
1626
|
+
didUpdateValueFor characteristic: CBCharacteristic,
|
|
1627
|
+
error: Error?
|
|
1628
|
+
) {
|
|
1629
|
+
let key = Helper.key(
|
|
1630
|
+
forPeripheral: peripheral,
|
|
1631
|
+
andCharacteristic: characteristic
|
|
1632
|
+
)
|
|
1633
|
+
|
|
1096
1634
|
if let error = error {
|
|
1097
1635
|
NSLog("Error \(characteristic.uuid) :\(error)")
|
|
1098
|
-
invokeAndClearDictionary(
|
|
1636
|
+
invokeAndClearDictionary(
|
|
1637
|
+
&readCallbacks,
|
|
1638
|
+
withKey: key,
|
|
1639
|
+
usingParameters: [error.localizedDescription, NSNull()]
|
|
1640
|
+
)
|
|
1099
1641
|
return
|
|
1100
1642
|
}
|
|
1101
|
-
|
|
1643
|
+
|
|
1102
1644
|
if SwiftBleManager.verboseLogging, let value = characteristic.value {
|
|
1103
|
-
NSLog(
|
|
1645
|
+
NSLog(
|
|
1646
|
+
"Read value [\(characteristic.uuid)]: \( value.hexadecimalString())"
|
|
1647
|
+
)
|
|
1104
1648
|
}
|
|
1105
|
-
|
|
1649
|
+
|
|
1106
1650
|
serialQueue.sync {
|
|
1107
1651
|
if readCallbacks[key] != nil {
|
|
1108
|
-
invokeAndClearDictionary_THREAD_UNSAFE(
|
|
1652
|
+
invokeAndClearDictionary_THREAD_UNSAFE(
|
|
1653
|
+
&readCallbacks,
|
|
1654
|
+
withKey: key,
|
|
1655
|
+
usingParameters: [
|
|
1656
|
+
NSNull(), characteristic.value!.toArray(),
|
|
1657
|
+
]
|
|
1658
|
+
)
|
|
1109
1659
|
} else {
|
|
1110
|
-
guard let bufferContainer = self.bufferedCharacteristics[key]
|
|
1660
|
+
guard let bufferContainer = self.bufferedCharacteristics[key]
|
|
1661
|
+
else {
|
|
1111
1662
|
// Standard notification
|
|
1112
1663
|
self.bleManager?.emitOnDidUpdateValue(forCharacteristic: [
|
|
1113
1664
|
"peripheral": peripheral.uuidAsString(),
|
|
1114
|
-
"characteristic": characteristic.uuid.uuidString
|
|
1115
|
-
|
|
1116
|
-
"
|
|
1665
|
+
"characteristic": characteristic.uuid.uuidString
|
|
1666
|
+
.lowercased(),
|
|
1667
|
+
"service": characteristic.service!.uuid.uuidString
|
|
1668
|
+
.lowercased(),
|
|
1669
|
+
"value": characteristic.value!.toArray(),
|
|
1117
1670
|
])
|
|
1118
1671
|
return
|
|
1119
1672
|
}
|
|
1120
|
-
|
|
1673
|
+
|
|
1121
1674
|
// Notification with buffer
|
|
1122
1675
|
var valueToEmit: Data = characteristic.value!
|
|
1123
|
-
while
|
|
1676
|
+
while !valueToEmit.isEmpty {
|
|
1124
1677
|
let rest = bufferContainer.put(valueToEmit)
|
|
1125
1678
|
if bufferContainer.isBufferFull {
|
|
1126
|
-
self.bleManager?.emitOnDidUpdateValue(
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1679
|
+
self.bleManager?.emitOnDidUpdateValue(
|
|
1680
|
+
forCharacteristic: [
|
|
1681
|
+
"peripheral": peripheral.uuidAsString(),
|
|
1682
|
+
"characteristic": characteristic.uuid.uuidString
|
|
1683
|
+
.lowercased(),
|
|
1684
|
+
"service": characteristic.service!.uuid
|
|
1685
|
+
.uuidString.lowercased(),
|
|
1686
|
+
"value": bufferContainer.items.toArray(),
|
|
1687
|
+
])
|
|
1132
1688
|
bufferContainer.resetBuffer()
|
|
1133
1689
|
}
|
|
1134
|
-
|
|
1690
|
+
|
|
1135
1691
|
valueToEmit = rest
|
|
1136
1692
|
}
|
|
1137
1693
|
}
|
|
1138
1694
|
}
|
|
1139
1695
|
}
|
|
1140
|
-
|
|
1141
|
-
public func peripheral(
|
|
1142
|
-
|
|
1143
|
-
|
|
1696
|
+
|
|
1697
|
+
public func peripheral(
|
|
1698
|
+
_ peripheral: CBPeripheral,
|
|
1699
|
+
didUpdateNotificationStateFor characteristic: CBCharacteristic,
|
|
1700
|
+
error: Error?
|
|
1701
|
+
) {
|
|
1144
1702
|
if let error = error {
|
|
1145
|
-
NSLog(
|
|
1146
|
-
|
|
1703
|
+
NSLog(
|
|
1704
|
+
"Error in didUpdateNotificationStateForCharacteristic: \(error)"
|
|
1705
|
+
)
|
|
1706
|
+
|
|
1147
1707
|
// Remove any buffered data if notification was started with buffer
|
|
1148
|
-
let key = Helper.key(
|
|
1708
|
+
let key = Helper.key(
|
|
1709
|
+
forPeripheral: peripheral,
|
|
1710
|
+
andCharacteristic: characteristic
|
|
1711
|
+
)
|
|
1149
1712
|
self.bufferedCharacteristics.removeValue(forKey: key)
|
|
1150
|
-
|
|
1713
|
+
|
|
1151
1714
|
self.bleManager?.emitOnDidUpdateNotificationState(for: [
|
|
1152
1715
|
"peripheral": peripheral.uuidAsString(),
|
|
1153
1716
|
"characteristic": characteristic.uuid.uuidString.lowercased(),
|
|
1154
1717
|
"isNotifying": false,
|
|
1155
1718
|
"domain": error._domain,
|
|
1156
|
-
"code": error._code
|
|
1719
|
+
"code": error._code,
|
|
1157
1720
|
])
|
|
1158
1721
|
} else {
|
|
1159
1722
|
self.bleManager?.emitOnDidUpdateNotificationState(for: [
|
|
1160
1723
|
"peripheral": peripheral.uuidAsString(),
|
|
1161
1724
|
"characteristic": characteristic.uuid.uuidString.lowercased(),
|
|
1162
|
-
"isNotifying": characteristic.isNotifying
|
|
1725
|
+
"isNotifying": characteristic.isNotifying,
|
|
1163
1726
|
])
|
|
1164
1727
|
}
|
|
1165
|
-
|
|
1166
|
-
let key = Helper.key(
|
|
1167
|
-
|
|
1728
|
+
|
|
1729
|
+
let key = Helper.key(
|
|
1730
|
+
forPeripheral: peripheral,
|
|
1731
|
+
andCharacteristic: characteristic
|
|
1732
|
+
)
|
|
1733
|
+
|
|
1168
1734
|
if let error = error {
|
|
1169
1735
|
if notificationCallbacks[key] != nil {
|
|
1170
|
-
invokeAndClearDictionary(
|
|
1736
|
+
invokeAndClearDictionary(
|
|
1737
|
+
¬ificationCallbacks,
|
|
1738
|
+
withKey: key,
|
|
1739
|
+
usingParameters: [error]
|
|
1740
|
+
)
|
|
1171
1741
|
}
|
|
1172
1742
|
if stopNotificationCallbacks[key] != nil {
|
|
1173
|
-
invokeAndClearDictionary(
|
|
1743
|
+
invokeAndClearDictionary(
|
|
1744
|
+
&stopNotificationCallbacks,
|
|
1745
|
+
withKey: key,
|
|
1746
|
+
usingParameters: [error]
|
|
1747
|
+
)
|
|
1174
1748
|
}
|
|
1175
1749
|
} else {
|
|
1176
1750
|
if characteristic.isNotifying {
|
|
@@ -1178,7 +1752,11 @@ import CoreBluetooth
|
|
|
1178
1752
|
NSLog("Notification began on \(characteristic.uuid)")
|
|
1179
1753
|
}
|
|
1180
1754
|
if notificationCallbacks[key] != nil {
|
|
1181
|
-
invokeAndClearDictionary(
|
|
1755
|
+
invokeAndClearDictionary(
|
|
1756
|
+
¬ificationCallbacks,
|
|
1757
|
+
withKey: key,
|
|
1758
|
+
usingParameters: []
|
|
1759
|
+
)
|
|
1182
1760
|
}
|
|
1183
1761
|
} else {
|
|
1184
1762
|
// Notification has stopped
|
|
@@ -1186,123 +1764,183 @@ import CoreBluetooth
|
|
|
1186
1764
|
NSLog("Notification ended on \(characteristic.uuid)")
|
|
1187
1765
|
}
|
|
1188
1766
|
if stopNotificationCallbacks[key] != nil {
|
|
1189
|
-
invokeAndClearDictionary(
|
|
1767
|
+
invokeAndClearDictionary(
|
|
1768
|
+
&stopNotificationCallbacks,
|
|
1769
|
+
withKey: key,
|
|
1770
|
+
usingParameters: []
|
|
1771
|
+
)
|
|
1190
1772
|
}
|
|
1191
1773
|
}
|
|
1192
1774
|
}
|
|
1193
1775
|
}
|
|
1194
|
-
|
|
1195
|
-
public func peripheral(
|
|
1196
|
-
|
|
1197
|
-
|
|
1776
|
+
|
|
1777
|
+
public func peripheral(
|
|
1778
|
+
_ peripheral: CBPeripheral,
|
|
1779
|
+
didWriteValueFor descriptor: CBDescriptor,
|
|
1780
|
+
error: Error?
|
|
1781
|
+
) {
|
|
1198
1782
|
NSLog("didWrite descriptor")
|
|
1199
|
-
|
|
1200
|
-
let key = Helper.key(
|
|
1783
|
+
|
|
1784
|
+
let key = Helper.key(
|
|
1785
|
+
forPeripheral: peripheral,
|
|
1786
|
+
andCharacteristic: descriptor.characteristic!,
|
|
1787
|
+
andDescriptor: descriptor
|
|
1788
|
+
)
|
|
1201
1789
|
let callbacks = writeDescriptorCallbacks[key]
|
|
1202
1790
|
if callbacks != nil {
|
|
1203
1791
|
if let error = error {
|
|
1204
1792
|
NSLog("\(error)")
|
|
1205
|
-
invokeAndClearDictionary(
|
|
1793
|
+
invokeAndClearDictionary(
|
|
1794
|
+
&writeDescriptorCallbacks,
|
|
1795
|
+
withKey: key,
|
|
1796
|
+
usingParameters: [error.localizedDescription]
|
|
1797
|
+
)
|
|
1206
1798
|
} else {
|
|
1207
|
-
invokeAndClearDictionary(
|
|
1799
|
+
invokeAndClearDictionary(
|
|
1800
|
+
&writeDescriptorCallbacks,
|
|
1801
|
+
withKey: key,
|
|
1802
|
+
usingParameters: []
|
|
1803
|
+
)
|
|
1208
1804
|
}
|
|
1209
1805
|
}
|
|
1210
1806
|
}
|
|
1211
|
-
|
|
1212
|
-
public func peripheral(
|
|
1213
|
-
|
|
1214
|
-
|
|
1807
|
+
|
|
1808
|
+
public func peripheral(
|
|
1809
|
+
_ peripheral: CBPeripheral,
|
|
1810
|
+
didWriteValueFor characteristic: CBCharacteristic,
|
|
1811
|
+
error: Error?
|
|
1812
|
+
) {
|
|
1215
1813
|
NSLog("didWrite")
|
|
1216
|
-
|
|
1217
|
-
let key = Helper.key(
|
|
1814
|
+
|
|
1815
|
+
let key = Helper.key(
|
|
1816
|
+
forPeripheral: peripheral,
|
|
1817
|
+
andCharacteristic: characteristic
|
|
1818
|
+
)
|
|
1218
1819
|
let peripheralWriteCallbacks = writeCallbacks[key]
|
|
1219
|
-
|
|
1820
|
+
|
|
1220
1821
|
if peripheralWriteCallbacks != nil {
|
|
1221
1822
|
if let error = error {
|
|
1222
1823
|
NSLog("\(error)")
|
|
1223
|
-
invokeAndClearDictionary(
|
|
1824
|
+
invokeAndClearDictionary(
|
|
1825
|
+
&writeCallbacks,
|
|
1826
|
+
withKey: key,
|
|
1827
|
+
usingParameters: [error.localizedDescription]
|
|
1828
|
+
)
|
|
1829
|
+
serialQueue.sync {
|
|
1830
|
+
writeQueues.removeValue(forKey: key)
|
|
1831
|
+
}
|
|
1224
1832
|
} else {
|
|
1225
|
-
if
|
|
1226
|
-
invokeAndClearDictionary(&writeCallbacks, withKey: key, usingParameters: [])
|
|
1227
|
-
} else {
|
|
1228
|
-
let message = writeQueue.removeFirst() as! Data
|
|
1833
|
+
if let message = dequeueNextSplitMessage(forKey: key) {
|
|
1229
1834
|
NSLog("Message to write \(message.hexadecimalString())")
|
|
1230
|
-
peripheral.writeValue(
|
|
1835
|
+
peripheral.writeValue(
|
|
1836
|
+
message,
|
|
1837
|
+
for: characteristic,
|
|
1838
|
+
type: .withResponse
|
|
1839
|
+
)
|
|
1840
|
+
} else {
|
|
1841
|
+
invokeAndClearDictionary(
|
|
1842
|
+
&writeCallbacks,
|
|
1843
|
+
withKey: key,
|
|
1844
|
+
usingParameters: []
|
|
1845
|
+
)
|
|
1231
1846
|
}
|
|
1232
1847
|
}
|
|
1233
1848
|
}
|
|
1234
1849
|
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1850
|
+
|
|
1237
1851
|
@objc public static func getCentralManager() -> CBCentralManager? {
|
|
1238
1852
|
return sharedManager
|
|
1239
1853
|
}
|
|
1240
|
-
|
|
1854
|
+
|
|
1241
1855
|
@objc public static func getInstance() -> SwiftBleManager? {
|
|
1242
1856
|
return shared
|
|
1243
1857
|
}
|
|
1244
|
-
|
|
1245
|
-
@objc public func enableBluetooth(
|
|
1858
|
+
|
|
1859
|
+
@objc public func enableBluetooth(
|
|
1860
|
+
_ callback: @escaping RCTResponseSenderBlock
|
|
1861
|
+
) {
|
|
1246
1862
|
callback(["Not supported"])
|
|
1247
1863
|
}
|
|
1248
|
-
|
|
1249
|
-
@objc public func getBondedPeripherals(
|
|
1864
|
+
|
|
1865
|
+
@objc public func getBondedPeripherals(
|
|
1866
|
+
_ callback: @escaping RCTResponseSenderBlock
|
|
1867
|
+
) {
|
|
1250
1868
|
callback(["Not supported"])
|
|
1251
1869
|
}
|
|
1252
|
-
|
|
1253
|
-
@objc public func createBond(
|
|
1254
|
-
|
|
1255
|
-
|
|
1870
|
+
|
|
1871
|
+
@objc public func createBond(
|
|
1872
|
+
_ peripheralUUID: String,
|
|
1873
|
+
devicePin: String,
|
|
1874
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1875
|
+
) {
|
|
1256
1876
|
callback(["Not supported"])
|
|
1257
1877
|
}
|
|
1258
|
-
|
|
1259
|
-
@objc public func removeBond(
|
|
1260
|
-
|
|
1878
|
+
|
|
1879
|
+
@objc public func removeBond(
|
|
1880
|
+
_ peripheralUUID: String,
|
|
1881
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1882
|
+
) {
|
|
1261
1883
|
callback(["Not supported"])
|
|
1262
1884
|
}
|
|
1263
|
-
|
|
1264
|
-
@objc public func removePeripheral(
|
|
1265
|
-
|
|
1885
|
+
|
|
1886
|
+
@objc public func removePeripheral(
|
|
1887
|
+
_ peripheralUUID: String,
|
|
1888
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1889
|
+
) {
|
|
1266
1890
|
callback(["Not supported"])
|
|
1267
1891
|
}
|
|
1268
|
-
|
|
1269
|
-
@objc public func requestMTU(
|
|
1270
|
-
|
|
1271
|
-
|
|
1892
|
+
|
|
1893
|
+
@objc public func requestMTU(
|
|
1894
|
+
_ peripheralUUID: String,
|
|
1895
|
+
mtu: Int,
|
|
1896
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1897
|
+
) {
|
|
1272
1898
|
callback(["Not supported"])
|
|
1273
1899
|
}
|
|
1274
|
-
|
|
1275
|
-
@objc public func requestConnectionPriority(
|
|
1276
|
-
|
|
1277
|
-
|
|
1900
|
+
|
|
1901
|
+
@objc public func requestConnectionPriority(
|
|
1902
|
+
_ peripheralUUID: String,
|
|
1903
|
+
connectionPriority: Int,
|
|
1904
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1905
|
+
) {
|
|
1278
1906
|
callback(["Not supported"])
|
|
1279
1907
|
}
|
|
1280
|
-
|
|
1281
|
-
@objc public func refreshCache(
|
|
1282
|
-
|
|
1908
|
+
|
|
1909
|
+
@objc public func refreshCache(
|
|
1910
|
+
_ peripheralUUID: String,
|
|
1911
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1912
|
+
) {
|
|
1283
1913
|
callback(["Not supported"])
|
|
1284
1914
|
}
|
|
1285
|
-
|
|
1915
|
+
|
|
1286
1916
|
@objc public func setName(_ name: String) {
|
|
1287
1917
|
// Not supported
|
|
1288
1918
|
}
|
|
1289
|
-
|
|
1290
|
-
@objc public func getAssociatedPeripherals(
|
|
1919
|
+
|
|
1920
|
+
@objc public func getAssociatedPeripherals(
|
|
1921
|
+
_ callback: @escaping RCTResponseSenderBlock
|
|
1922
|
+
) {
|
|
1291
1923
|
callback(["Not supported"])
|
|
1292
1924
|
}
|
|
1293
|
-
|
|
1294
|
-
@objc public func removeAssociatedPeripheral(
|
|
1295
|
-
|
|
1925
|
+
|
|
1926
|
+
@objc public func removeAssociatedPeripheral(
|
|
1927
|
+
_ peripheralUUID: String,
|
|
1928
|
+
callback: @escaping RCTResponseSenderBlock
|
|
1929
|
+
) {
|
|
1296
1930
|
callback(["Not supported"])
|
|
1297
1931
|
}
|
|
1298
|
-
|
|
1299
|
-
@objc public func supportsCompanion(
|
|
1932
|
+
|
|
1933
|
+
@objc public func supportsCompanion(
|
|
1934
|
+
_ callback: @escaping RCTResponseSenderBlock
|
|
1935
|
+
) {
|
|
1300
1936
|
callback([NSNull(), false])
|
|
1301
1937
|
}
|
|
1302
|
-
|
|
1303
|
-
@objc public func companionScan(
|
|
1304
|
-
|
|
1305
|
-
|
|
1938
|
+
|
|
1939
|
+
@objc public func companionScan(
|
|
1940
|
+
_ serviceUUIDs: [Any],
|
|
1941
|
+
option: NSDictionary,
|
|
1942
|
+
callback: RCTResponseSenderBlock
|
|
1943
|
+
) {
|
|
1306
1944
|
callback(["Not supported"])
|
|
1307
1945
|
}
|
|
1308
1946
|
}
|