@iotize/device-com-ble.cordova 3.2.1 → 3.3.2

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 (49) hide show
  1. package/README.md +174 -177
  2. package/bundles/iotize-device-com-ble.cordova.umd.js +102 -69
  3. package/bundles/iotize-device-com-ble.cordova.umd.js.map +1 -1
  4. package/bundles/iotize-device-com-ble.cordova.umd.min.js +16 -0
  5. package/bundles/iotize-device-com-ble.cordova.umd.min.js.map +1 -0
  6. package/esm2015/lib/ble-com-protocol.js +10 -10
  7. package/esm2015/lib/ble-com-protocol.js.map +1 -1
  8. package/esm2015/lib/cordova-ble-error.js +11 -2
  9. package/esm2015/lib/cordova-ble-error.js.map +1 -1
  10. package/esm2015/lib/cordova-interface.js.map +1 -1
  11. package/esm2015/lib/cordova-service-adapter.js +15 -14
  12. package/esm2015/lib/cordova-service-adapter.js.map +1 -1
  13. package/esm2015/lib/cordova-service-adapter.metadata.json +1 -1
  14. package/esm2015/lib/definitions.js +0 -2
  15. package/esm2015/lib/definitions.js.map +1 -1
  16. package/esm2015/lib/iotize-ble-cordova-plugin.js +59 -51
  17. package/esm2015/lib/iotize-ble-cordova-plugin.js.map +1 -1
  18. package/esm2015/lib/iotize-ble-cordova-plugin.metadata.json +1 -1
  19. package/esm2015/lib/iotize-ble-cordova-plugin.ngsummary.json +1 -1
  20. package/esm2015/lib/logger.js +1 -1
  21. package/esm2015/lib/logger.js.map +1 -1
  22. package/esm2015/lib/scanner.js +14 -12
  23. package/esm2015/lib/scanner.js.map +1 -1
  24. package/esm2015/lib/scanner.metadata.json +1 -1
  25. package/esm2015/lib/utility.js +1 -1
  26. package/esm2015/lib/utility.js.map +1 -1
  27. package/esm2015/public_api.js +4 -4
  28. package/esm2015/public_api.js.map +1 -1
  29. package/fesm2015/iotize-device-com-ble.cordova.js +93 -74
  30. package/fesm2015/iotize-device-com-ble.cordova.js.map +1 -1
  31. package/iotize-device-com-ble.cordova.metadata.json +1 -1
  32. package/lib/ble-com-protocol.d.ts +4 -4
  33. package/lib/cordova-ble-error.d.ts +12 -3
  34. package/lib/cordova-service-adapter.d.ts +1 -1
  35. package/lib/definitions.d.ts +1 -1
  36. package/lib/iotize-ble-cordova-plugin.d.ts +4 -3
  37. package/lib/scanner.d.ts +4 -4
  38. package/package.json +1 -1
  39. package/plugin.xml +66 -63
  40. package/public_api.d.ts +5 -5
  41. package/src/android/.gradle/4.8.1/fileHashes/fileHashes.bin +0 -0
  42. package/src/android/.gradle/4.8.1/fileHashes/fileHashes.lock +0 -0
  43. package/src/android/build.gradle +1 -0
  44. package/src/android/src/ble/BLECom.java +559 -558
  45. package/src/ios/BLECom.swift +732 -732
  46. package/src/windows/IoTizeBLE.pdb +0 -0
  47. package/src/windows/IoTizeBLE.pri +0 -0
  48. package/src/windows/iotize-ble-com.js +159 -179
  49. package/www/plugin.js +1 -1
@@ -1,732 +1,732 @@
1
- //
2
- // Copyright 2018 IoTize SAS Inc. Licensed under the MIT license.
3
- //
4
- // BLECom.swift
5
- // device-com-ble.cordova BLE Cordova Plugin
6
- //
7
-
8
- import Foundation
9
- import CoreBluetooth
10
-
11
- // Custom debug print functions
12
-
13
- public func printBLE(_ object: Any...) {
14
- #if true
15
- for item in object {
16
- Swift.print("BLE:", object)
17
- }
18
- #endif
19
- }
20
-
21
- public func printBLE(_ object: Any) {
22
- #if true
23
- Swift.print("BLE:", object)
24
- #endif
25
- }
26
-
27
-
28
- struct IoTizeBleError: Error {
29
-
30
- let code: Int
31
- let message: String
32
-
33
- init(code: Int, message: String) {
34
- self.code = code
35
- self.message = message
36
- }
37
-
38
- static func BleUnsupported() -> IoTizeBleError { return IoTizeBleError(code:100, message:"Bluetooth is not supported")}
39
- static func BleUnauthorized() -> IoTizeBleError { return IoTizeBleError(code:101, message:"Bluetooth is not authorized")}
40
- static func BlePoweredOff() -> IoTizeBleError { return IoTizeBleError(code:102, message:"Bluetooth is powered off")}
41
- static func BleResetting() -> IoTizeBleError { return IoTizeBleError(code:103, message:"Bluetooth is resetting")}
42
- static func BleUnknown() -> IoTizeBleError { return IoTizeBleError(code:104, message:"Bluetooth is in an unknown state")}
43
-
44
- static func PeripheralConnectionFailed(peripheral: CBPeripheral, error: Error?) -> IoTizeBleError { return IoTizeBleError(code:200, message:"Connection to \(peripheral.name ?? "unknown peripheral") failed: \(error?.localizedDescription ?? "unknown")" )}
45
- static func NoDeviceConnected() -> IoTizeBleError { return IoTizeBleError(code:201, message:"No Device Connected")}
46
-
47
- static func ServiceDiscoveryFailed(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:300, message:"Failed to discover services for \(peripheral.name ?? "unknown peripheral")" )}
48
- static func CharacteristicsDiscoveryFailed(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:301, message:"Failed to discover characteristics for \(peripheral.name ?? "unknown peripheral")" )}
49
- static func CharacteristicSPPNotFound(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:302, message:"Characteristic SPP not found for \(peripheral.name ?? "unknown peripheral")" )}
50
- static func CharacteristicNotifyChangeFailed() -> IoTizeBleError { return IoTizeBleError(code:304, message:"Failed to set notification for characteristic" )}
51
- static func BleVersionIsOld(version: String) -> IoTizeBleError { return IoTizeBleError(code:303, message:"BLE firmware version is too old: \(version)" )}
52
-
53
- static func InvalidWriteData(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:403, message:"Invalid write data for \(peripheral.name ?? "unknown peripheral")" )}
54
- static func TimedOutRequest(msg: String) -> IoTizeBleError { return IoTizeBleError(code:404, message:"Waiting for response timed out, txData: " + msg )}
55
-
56
- }
57
-
58
- enum CordovaBLEErrorCode: CustomStringConvertible {
59
- case InternalError
60
- case IllegalArgument
61
-
62
- var description: String {
63
- switch self {
64
- case .InternalError: return "CordovaBLEErrorInternalError"
65
- case .IllegalArgument: return "CordovaBLEErrorIllegalArgument"
66
- }
67
- }
68
- }
69
-
70
- struct CordovaBLEError: Error {
71
- var code: CordovaBLEErrorCode
72
- var message: String
73
-
74
- init(_ code: CordovaBLEErrorCode, _ message: String) {
75
- self.code = code
76
- self.message = message
77
- }
78
-
79
- func toJSON() -> [AnyHashable: Any] {
80
- return ["code": code.description, "message": message]
81
- }
82
-
83
- static func InternalError(_ message: String) -> CordovaBLEError {return CordovaBLEError(.InternalError, message)}
84
-
85
- static func IllegalArgument(_ message: String) -> CordovaBLEError {return CordovaBLEError(.IllegalArgument, message)}
86
- }
87
-
88
- struct BLEAction {
89
- var id: String
90
- var action: () -> Void
91
-
92
- init(_ id: String, _ action: @escaping () -> Void) {
93
- self.id = id
94
- self.action = action
95
- }
96
- }
97
-
98
- //Main class handling the plugin functionalities.
99
- @objc(BLECom) class BLECom : CDVPlugin {
100
-
101
- var bleActionQueue: Queue<BLEAction>!
102
-
103
- var isHandlingQueue = false
104
-
105
- var bleController: BLEManager!
106
- var lastError: IoTizeBleError?
107
-
108
- //
109
- override func pluginInitialize(){
110
- bleController = BLEManager()
111
- bleActionQueue = Queue<BLEAction>()
112
- }
113
-
114
- //helper to return an empty response
115
- func sendSuccessWithoutResponse(command: CDVInvokedUrlCommand) {
116
- let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK)
117
-
118
- self.commandDelegate!.send(pluginResult, callbackId: command.callbackId)
119
- if (bleActionQueue.first?.id == command.callbackId) {
120
- removeFromQueue()
121
- }
122
- }
123
-
124
- //helper to return a string
125
- func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: String){
126
- let pluginResult = CDVPluginResult(
127
- status: CDVCommandStatus_OK,
128
- messageAs: result
129
- )
130
- self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
131
- if (bleActionQueue.first?.id == command.callbackId) {
132
- removeFromQueue()
133
- }
134
- }
135
-
136
- //helper to return a boolean
137
- private func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: Bool) {
138
- let pluginResult = CDVPluginResult(
139
- status: CDVCommandStatus_OK,
140
- messageAs: result
141
- )
142
- self.commandDelegate!.send(pluginResult, callbackId: command.callbackId)
143
- if (bleActionQueue.first?.id == command.callbackId) {
144
- removeFromQueue()
145
- }
146
- }
147
-
148
- //helper to return a JSon object
149
- func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: DiscoveredDeviceType){
150
- let pluginResult = CDVPluginResult(
151
- status: CDVCommandStatus_OK,
152
- messageAs: result.ToJSON()
153
- )
154
- self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
155
- if (bleActionQueue.first?.id == command.callbackId) {
156
- removeFromQueue()
157
- }
158
- }
159
-
160
- //helper to return a String with keeping the callback
161
- func sendSuccessWithMultipleResponse(command: CDVInvokedUrlCommand, result: String){
162
- let pluginResult = CDVPluginResult(
163
- status: CDVCommandStatus_OK,
164
- messageAs: result
165
- )
166
- pluginResult!.setKeepCallbackAs(true);
167
- self.commandDelegate!.send( pluginResult, callbackId: command.callbackId )
168
- if (bleActionQueue.first?.id == command.callbackId) {
169
- removeFromQueue()
170
- }
171
- }
172
-
173
- //helper to return a JSon DiscoveredDeviceType object with keeping the callback
174
- func sendSuccessWithMultipleResponse(command: CDVInvokedUrlCommand, result: DiscoveredDeviceType){
175
- let pluginResult = CDVPluginResult(
176
- status: CDVCommandStatus_OK,
177
- messageAs: result.ToJSON()
178
- )
179
- pluginResult!.setKeepCallbackAs(true);
180
- self.commandDelegate!.send( pluginResult, callbackId: command.callbackId )
181
- if (bleActionQueue.first?.id == command.callbackId) {
182
- removeFromQueue()
183
- }
184
- }
185
- //helper to return a JSon Array object object
186
- func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: [[AnyHashable: Any]]) {
187
- let pluginResult = CDVPluginResult(
188
- status: CDVCommandStatus_OK,
189
- messageAs: result
190
- )
191
- self.commandDelegate!.send( pluginResult, callbackId: command.callbackId )
192
- if (bleActionQueue.first?.id == command.callbackId) {
193
- removeFromQueue()
194
- } }
195
-
196
- //helper to send back an error
197
- func sendError(command: CDVInvokedUrlCommand, result: String){
198
- let pluginResult = CDVPluginResult(
199
- status: CDVCommandStatus_ERROR,
200
- messageAs: result
201
- )
202
- self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
203
- if (bleActionQueue.first?.id == command.callbackId) {
204
- removeFromQueue()
205
- } }
206
-
207
- func sendError(command: CDVInvokedUrlCommand, result: CordovaBLEError){
208
- let pluginResult = CDVPluginResult(
209
- status: CDVCommandStatus_ERROR,
210
- messageAs: result.toJSON()
211
- )
212
- self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
213
- if (bleActionQueue.first?.id == command.callbackId) {
214
- removeFromQueue()
215
- }
216
- }
217
-
218
-
219
- //Is BLE available
220
- @objc(checkAvailable:)
221
- func checkAvailable(command: CDVInvokedUrlCommand) {
222
- addToQueue(command: command, bleAction: {[self] in
223
- DispatchQueue.main.async {
224
-
225
- //from ios5
226
- if ( floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_5_1) ){
227
- self.sendError(command: command, result: IoTizeBleError.BleUnsupported().message)
228
- }
229
-
230
- //check State
231
- self.bleController.checkState(completion: {
232
- (error: IoTizeBleError?) -> () in
233
-
234
- DispatchQueue.main.async {
235
-
236
- if (error != nil){
237
- self.lastError = error
238
- self.sendError(command: command, result: error!.message)
239
- }
240
- else {
241
- self.sendSuccessWithSingleResponse(command: command, result: true)
242
- }
243
-
244
- }
245
- })
246
- }
247
- })
248
- }
249
-
250
-
251
- //Start scanning IoTize devices
252
- @objc(startScan:)
253
- func startScan(command: CDVInvokedUrlCommand) {
254
- addToQueue(command: command, bleAction: {[self] in
255
- if (!self.isReady()){
256
-
257
- DispatchQueue.main.async {
258
- Thread.sleep(forTimeInterval: 0.01)
259
- self.startScan(command: command)
260
- }
261
- return
262
- }
263
-
264
- self.bleController.beginScan(completion: {
265
- (result: Any, error: IoTizeBleError?) -> () in
266
-
267
- DispatchQueue.main.async {
268
-
269
- if (error != nil){
270
- self.lastError = error
271
- self.sendError(command: command, result: error!.message)
272
- }
273
- else if let resultString = result as? String{
274
- self.sendSuccessWithMultipleResponse(command: command, result: resultString)
275
- } else if let resultDiscoveredDevice = result as? DiscoveredDeviceType {
276
- self.sendSuccessWithMultipleResponse(command: command, result: resultDiscoveredDevice)
277
- } else if let resultDevice = result as? CBPeripheral {
278
- self.sendSuccessWithMultipleResponse(command: command, result: CBPeripheralConverter.toDiscoveredDeviceType(device: resultDevice))
279
- } else {
280
- }
281
- }
282
- })
283
- })
284
- }
285
-
286
- //Stop scanning
287
- @objc(stopScan:)
288
- func stopScan(command: CDVInvokedUrlCommand) {
289
- addToQueue(command: command, bleAction: {[self] in
290
- bleController.stopScan();
291
- self.sendSuccessWithSingleResponse(command: command, result: "OK")
292
- })
293
- }
294
-
295
-
296
- //Connect to a device using its UUID
297
- @objc(connectAndDiscoverTapServices:)
298
- func connectAndDiscoverTapServices(command: CDVInvokedUrlCommand) {
299
- addToQueue(command: command, bleAction: {[self] in
300
- //we need the UUID of the device
301
- if (command.arguments.count == 0){
302
- let error = CordovaBLEError.IllegalArgument("Missing arguments")
303
- self.sendError(command: command, result: error)
304
- return
305
- }
306
-
307
- let deviceUUID = command.arguments[0] as? String ?? ""
308
-
309
- bleController.useBLETapPeripheral = true
310
-
311
- bleController.connectWithUUID(device: deviceUUID, completion: {
312
- (state: Any?, error: IoTizeBleError?) -> () in
313
-
314
- DispatchQueue.main.async {
315
-
316
- if (error != nil){
317
- self.lastError = error
318
- self.sendError(command: command, result: error!.message)
319
- }
320
- else {
321
- //printBLE("##> Sending Connected Ok")
322
- let _state = state as? String
323
-
324
- self.sendSuccessWithMultipleResponse(command: command, result: _state ?? "") // keep callback
325
- }
326
- }
327
- })
328
- })
329
- }
330
-
331
-
332
- @objc(connect:)
333
- func connect(command: CDVInvokedUrlCommand) {
334
- addToQueue(command: command, bleAction: {[self] in
335
- //we need the UUID of the device
336
- if (command.arguments.count == 0){
337
- self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
338
- return
339
- }
340
-
341
- let deviceUUID = command.arguments[0] as? String ?? ""
342
-
343
- bleController.useBLETapPeripheral = false
344
-
345
- bleController.connectWithUUID(device: deviceUUID, completion: {
346
- (state: Any?, error: IoTizeBleError?) -> () in
347
-
348
- DispatchQueue.main.async {
349
-
350
- if (error != nil){
351
- self.lastError = error
352
- self.sendError(command: command, result: error!.message)
353
- }
354
- else {
355
- //printBLE("##> Sending Connected Ok")
356
- let _state = state as? String
357
-
358
- self.sendSuccessWithMultipleResponse(command: command, result: _state ?? "") // keep callback
359
- }
360
- }
361
- })
362
- })
363
- }
364
-
365
- //Disconnect from a device using its name
366
- @objc(disConnect:)
367
- func disConnect(command: CDVInvokedUrlCommand) {
368
- addToQueue(command: command, bleAction: { [self] in
369
- //we need the name of the device
370
- if (command.arguments.count == 0){
371
- self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
372
- return
373
- }
374
-
375
- bleController.disconnect( completion: {
376
- (error: IoTizeBleError?) -> () in
377
-
378
- DispatchQueue.main.async {
379
-
380
- if (error != nil){
381
- self.lastError = error
382
- self.sendError(command: command, result: error!.message)
383
- }
384
- else {
385
- self.sendSuccessWithSingleResponse(command: command, result: "OK")
386
- }
387
- }
388
- })
389
- })
390
- }
391
-
392
- //Retrieve additional information
393
- @objc(getLastError:)
394
- func getLastError(command: CDVInvokedUrlCommand) {
395
- addToQueue(command: command, bleAction: {[self] in
396
- let msg: String = (lastError != nil) ? (lastError!.message) : ""
397
- self.sendSuccessWithSingleResponse(command: command, result: msg)
398
- })
399
- }
400
-
401
- //Send Data to device
402
- @objc(sendRequest:)
403
- func sendRequest(command: CDVInvokedUrlCommand) {
404
-
405
- addToQueue(command: command, bleAction: {[self] in
406
- printBLE("##> SendRequest")
407
- //we need data to send
408
- if (command.arguments.count == 1){
409
- self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
410
- return
411
- }
412
-
413
- let data = command.arguments[1] as? String ?? ""
414
-
415
- bleController.sendRequest(data: data, completion: {
416
- (response: Any, error: IoTizeBleError?) -> () in
417
-
418
- DispatchQueue.main.async {
419
-
420
- if (error != nil){
421
- self.lastError = error
422
- self.sendError(command: command, result: error!.message)
423
- }
424
- else {
425
- if let responseString = response as? String {
426
- self.sendSuccessWithSingleResponse(command: command, result: responseString)
427
- }
428
- else if let responseDiscoveredDevice = response as? DiscoveredDeviceType {
429
- self.sendSuccessWithSingleResponse(command: command, result: responseDiscoveredDevice)
430
- } else if let responseDevice = response as? CBPeripheral {
431
- self.sendSuccessWithSingleResponse(command: command, result: CBPeripheralConverter.toDiscoveredDeviceType(device: responseDevice))
432
- }
433
- }
434
- }
435
- })
436
- })
437
- }
438
-
439
- @objc(isConnected:)
440
- func isConnected(command: CDVInvokedUrlCommand) {
441
- addToQueue(command: command, bleAction: { [self] in
442
- var status: Bool ;
443
-
444
- if (command.arguments.count < 1) {
445
- let error = CordovaBLEError.IllegalArgument("Missing arguments")
446
- self.sendError(command: command, result: error)
447
- }
448
-
449
- let deviceUUID = command.arguments[0] as? String ?? ""
450
- do {
451
- status = try bleController.isConnected(deviceUUID)
452
- self.sendSuccessWithSingleResponse(command: command, result: status)
453
- }
454
- catch {
455
- if (error is CordovaBLEError) {
456
- self.sendError(command: command, result: (error as! CordovaBLEError))
457
- } else {
458
- let cordovaError = CordovaBLEError.InternalError("Unkown error")
459
- self.sendError(command: command, result: cordovaError)
460
- }
461
- }
462
- })
463
-
464
- }
465
-
466
- func isReady() -> Bool {
467
- return bleController.isReady()
468
- }
469
-
470
- @objc(discoverServices:)
471
- func discoverServices(command: CDVInvokedUrlCommand) {
472
- addToQueue(command: command, bleAction: {[self] in
473
- printBLE("discoverServices called")
474
- if (command.arguments.count == 0){
475
- self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
476
- return
477
- }
478
-
479
- let deviceUUID = command.arguments[0] as? String ?? ""
480
-
481
- bleController.discoverServices(forUUID: deviceUUID) { (anyPeripheral, error) in
482
- if (error != nil) {
483
- self.lastError = error
484
- self.sendError(command: command, result: error?.message ?? "discoverServicesError")
485
- } else {
486
- if let peripheral = anyPeripheral as? CBPeripheral {
487
- let result = CBPeripheralConverter.toServiceDescriptionsJSON(device: peripheral)
488
- self.sendSuccessWithSingleResponse(command: command, result: result)
489
- }
490
- }
491
- }
492
- })
493
- }
494
-
495
- @objc(characteristicWriteWithoutResponse:)
496
- func characteristicWriteWithoutResponse(command: CDVInvokedUrlCommand) {
497
-
498
- addToQueue(command: command, bleAction: {[self] in
499
- printBLE("characteristicWriteWithoutResponse called")
500
- if (command.arguments.count < 4){
501
- self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
502
- return
503
- }
504
- let deviceID = command.arguments[0] as? String ?? ""
505
-
506
- guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
507
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
508
- self.sendError(command: command, result: cordovaError)
509
- return
510
- }
511
- guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
512
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
513
- self.sendError(command: command, result: cordovaError)
514
- return
515
- }
516
-
517
- let dataToWrite = Data(Request.stringToHexArray(command.arguments[3] as? String ?? ""))
518
-
519
- bleController.characteristicWriteWithoutResponse(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, data: dataToWrite, completion: { (error) in
520
- if (error != nil) {
521
- self.sendError(command: command, result: error!.message)
522
- return
523
- }
524
- self.sendSuccessWithSingleResponse(command: command, result: "OK")
525
- })
526
- })
527
- }
528
-
529
- @objc(characteristicWrite:)
530
- func characteristicWrite(command: CDVInvokedUrlCommand) {
531
- addToQueue(command: command, bleAction: {[self] in
532
- printBLE("characteristicWrite called")
533
- if (command.arguments.count < 4){
534
- self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
535
- return
536
- }
537
- let deviceID = command.arguments[0] as? String ?? ""
538
-
539
- guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
540
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
541
- self.sendError(command: command, result: cordovaError)
542
- return
543
- }
544
-
545
- guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
546
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
547
-
548
- self.sendError(command: command, result: cordovaError)
549
- return
550
- }
551
-
552
- let dataToWrite = Data(Request.stringToHexArray(command.arguments[3] as? String ?? ""))
553
-
554
- bleController.characteristicWrite(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, data: dataToWrite, completion: { (error) in
555
- if (error != nil) {
556
- self.sendError(command: command, result: error!.message)
557
- return
558
- }
559
- self.sendSuccessWithSingleResponse(command: command, result: "OK")
560
- })
561
- })
562
- }
563
-
564
- @objc(characteristicRead:)
565
- func characteristicRead(command: CDVInvokedUrlCommand) {
566
-
567
- addToQueue(command: command, bleAction: {[self] in
568
- printBLE("characteristicRead called")
569
- if (command.arguments.count < 3){
570
- self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
571
- return
572
- }
573
- let deviceID = command.arguments[0] as? String ?? ""
574
- guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
575
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
576
- self.sendError(command: command, result: cordovaError)
577
- return
578
- }
579
- guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
580
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
581
- self.sendError(command: command, result: cordovaError)
582
- return
583
- }
584
-
585
- bleController.characteristicRead(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { (readData, error) in
586
- if (error != nil) {
587
- self.sendError(command: command, result: error!.message)
588
- return
589
- }
590
- let data = readData as! String
591
- self.sendSuccessWithSingleResponse(command: command, result: data)
592
- })
593
- })
594
-
595
-
596
- }
597
-
598
- @objc(characteristicStartNotification:)
599
- func characteristicStartNotification(command: CDVInvokedUrlCommand) {
600
-
601
- addToQueue(command: command, bleAction: {[self] () in
602
- printBLE("characteristicStartNotification called")
603
- if (command.arguments.count < 3){
604
- self.sendError(command: command, result: "characteristicStartNotification parameter error")
605
- return
606
- }
607
- let deviceID = command.arguments[0] as? String ?? ""
608
-
609
- guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
610
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
611
- self.sendError(command: command, result: cordovaError)
612
- return
613
- }
614
- guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
615
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
616
- self.sendError(command: command, result: cordovaError)
617
- return
618
- }
619
-
620
- bleController.characteristicStartNotification(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { error in
621
- if (error != nil) {
622
- printBLE("characteristicStartNotification response error")
623
- self.sendError(command: command, result: error!.message)
624
- return
625
- }
626
- printBLE("characteristicStartNotification response OK")
627
- self.sendSuccessWithSingleResponse(command: command, result: "OK")
628
- })
629
- })
630
-
631
- }
632
-
633
- @objc(characteristicStopNotification:)
634
- func characteristicStopNotification(command: CDVInvokedUrlCommand) {
635
-
636
- addToQueue(command: command, bleAction: { [self] () in
637
- printBLE("characteristicStopNotification called")
638
- if (command.arguments.count < 3){
639
- self.sendError(command: command, result: "characteristicStopNotification parameter error")
640
- return
641
- }
642
- let deviceID = command.arguments[0] as? String ?? ""
643
-
644
- guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
645
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
646
- self.sendError(command: command, result: cordovaError)
647
- return
648
- }
649
- guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
650
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
651
- self.sendError(command: command, result: cordovaError)
652
- return
653
- }
654
-
655
- bleController.characteristicStopNotification(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { error in
656
- if (error != nil) {
657
- printBLE("characteristicStopNotification response error")
658
- self.sendError(command: command, result: error!.message)
659
- return
660
- }
661
- printBLE("characteristicStopNotification response OK")
662
- self.sendSuccessWithSingleResponse(command: command, result: "OK")
663
- })
664
- })
665
-
666
- }
667
-
668
- @objc(characteristicChanged:)
669
- func characteristicChanged(command: CDVInvokedUrlCommand) {
670
-
671
- addToQueue(command: command, bleAction: { [self] () in
672
-
673
- printBLE("characteristicChanged called")
674
- if (command.arguments.count < 3){
675
- self.sendError(command: command, result: "SendRequest parameter error")
676
- return
677
- }
678
- let deviceID = command.arguments[0] as? String ?? ""
679
-
680
- guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
681
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
682
- self.sendError(command: command, result: cordovaError)
683
- return
684
- }
685
- guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
686
- let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
687
- self.sendError(command: command, result: cordovaError)
688
- return
689
- }
690
-
691
- bleController.characteristicChanged(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { (result, error) in
692
- if (error != nil) {
693
- self.sendError(command: command, result: error!.message)
694
- return
695
- }
696
- self.sendSuccessWithMultipleResponse(command: command, result: result as! String)
697
- })
698
- if (bleActionQueue.first?.id == command.callbackId) {
699
- removeFromQueue()
700
- }
701
- })
702
- }
703
-
704
- func addToQueue(command: CDVInvokedUrlCommand, bleAction: @escaping () -> Void) {
705
- bleActionQueue.enqueue(BLEAction(command.callbackId, bleAction))
706
- if (!isHandlingQueue) {
707
- isHandlingQueue = true
708
- DispatchQueue.main.async {
709
- bleAction()
710
- }
711
- }
712
- }
713
-
714
- func removeFromQueue() {
715
- bleActionQueue.dequeue()
716
- if (isHandlingQueue) {
717
- if (bleActionQueue.first != nil) {
718
- DispatchQueue.main.async {
719
- self.bleActionQueue.first!.action()
720
- }
721
- } else {
722
- isHandlingQueue = false
723
- }
724
- }
725
- }
726
-
727
-
728
- @objc(close:)
729
- func close(command: CDVInvokedUrlCommand) {
730
- disConnect(command)
731
- }
732
- }
1
+ //
2
+ // Copyright 2018 IoTize SAS Inc. Licensed under the MIT license.
3
+ //
4
+ // BLECom.swift
5
+ // device-com-ble.cordova BLE Cordova Plugin
6
+ //
7
+
8
+ import Foundation
9
+ import CoreBluetooth
10
+
11
+ // Custom debug print functions
12
+
13
+ public func printBLE(_ object: Any...) {
14
+ #if true
15
+ for item in object {
16
+ Swift.print("BLE:", object)
17
+ }
18
+ #endif
19
+ }
20
+
21
+ public func printBLE(_ object: Any) {
22
+ #if true
23
+ Swift.print("BLE:", object)
24
+ #endif
25
+ }
26
+
27
+
28
+ struct IoTizeBleError: Error {
29
+
30
+ let code: Int
31
+ let message: String
32
+
33
+ init(code: Int, message: String) {
34
+ self.code = code
35
+ self.message = message
36
+ }
37
+
38
+ static func BleUnsupported() -> IoTizeBleError { return IoTizeBleError(code:100, message:"Bluetooth is not supported")}
39
+ static func BleUnauthorized() -> IoTizeBleError { return IoTizeBleError(code:101, message:"Bluetooth is not authorized")}
40
+ static func BlePoweredOff() -> IoTizeBleError { return IoTizeBleError(code:102, message:"Bluetooth is powered off")}
41
+ static func BleResetting() -> IoTizeBleError { return IoTizeBleError(code:103, message:"Bluetooth is resetting")}
42
+ static func BleUnknown() -> IoTizeBleError { return IoTizeBleError(code:104, message:"Bluetooth is in an unknown state")}
43
+
44
+ static func PeripheralConnectionFailed(peripheral: CBPeripheral, error: Error?) -> IoTizeBleError { return IoTizeBleError(code:200, message:"Connection to \(peripheral.name ?? "unknown peripheral") failed: \(error?.localizedDescription ?? "unknown")" )}
45
+ static func NoDeviceConnected() -> IoTizeBleError { return IoTizeBleError(code:201, message:"No Device Connected")}
46
+
47
+ static func ServiceDiscoveryFailed(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:300, message:"Failed to discover services for \(peripheral.name ?? "unknown peripheral")" )}
48
+ static func CharacteristicsDiscoveryFailed(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:301, message:"Failed to discover characteristics for \(peripheral.name ?? "unknown peripheral")" )}
49
+ static func CharacteristicSPPNotFound(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:302, message:"Characteristic SPP not found for \(peripheral.name ?? "unknown peripheral")" )}
50
+ static func CharacteristicNotifyChangeFailed() -> IoTizeBleError { return IoTizeBleError(code:304, message:"Failed to set notification for characteristic" )}
51
+ static func BleVersionIsOld(version: String) -> IoTizeBleError { return IoTizeBleError(code:303, message:"BLE firmware version is too old: \(version)" )}
52
+
53
+ static func InvalidWriteData(peripheral: CBPeripheral) -> IoTizeBleError { return IoTizeBleError(code:403, message:"Invalid write data for \(peripheral.name ?? "unknown peripheral")" )}
54
+ static func TimedOutRequest(msg: String) -> IoTizeBleError { return IoTizeBleError(code:404, message:"Waiting for response timed out, txData: " + msg )}
55
+
56
+ }
57
+
58
+ enum CordovaBLEErrorCode: CustomStringConvertible {
59
+ case InternalError
60
+ case IllegalArgument
61
+
62
+ var description: String {
63
+ switch self {
64
+ case .InternalError: return "CordovaBLEErrorInternalError"
65
+ case .IllegalArgument: return "CordovaBLEErrorIllegalArgument"
66
+ }
67
+ }
68
+ }
69
+
70
+ struct CordovaBLEError: Error {
71
+ var code: CordovaBLEErrorCode
72
+ var message: String
73
+
74
+ init(_ code: CordovaBLEErrorCode, _ message: String) {
75
+ self.code = code
76
+ self.message = message
77
+ }
78
+
79
+ func toJSON() -> [AnyHashable: Any] {
80
+ return ["code": code.description, "message": message]
81
+ }
82
+
83
+ static func InternalError(_ message: String) -> CordovaBLEError {return CordovaBLEError(.InternalError, message)}
84
+
85
+ static func IllegalArgument(_ message: String) -> CordovaBLEError {return CordovaBLEError(.IllegalArgument, message)}
86
+ }
87
+
88
+ struct BLEAction {
89
+ var id: String
90
+ var action: () -> Void
91
+
92
+ init(_ id: String, _ action: @escaping () -> Void) {
93
+ self.id = id
94
+ self.action = action
95
+ }
96
+ }
97
+
98
+ //Main class handling the plugin functionalities.
99
+ @objc(BLECom) class BLECom : CDVPlugin {
100
+
101
+ var bleActionQueue: Queue<BLEAction>!
102
+
103
+ var isHandlingQueue = false
104
+
105
+ var bleController: BLEManager!
106
+ var lastError: IoTizeBleError?
107
+
108
+ //
109
+ override func pluginInitialize(){
110
+ bleController = BLEManager()
111
+ bleActionQueue = Queue<BLEAction>()
112
+ }
113
+
114
+ //helper to return an empty response
115
+ func sendSuccessWithoutResponse(command: CDVInvokedUrlCommand) {
116
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK)
117
+
118
+ self.commandDelegate!.send(pluginResult, callbackId: command.callbackId)
119
+ if (bleActionQueue.first?.id == command.callbackId) {
120
+ removeFromQueue()
121
+ }
122
+ }
123
+
124
+ //helper to return a string
125
+ func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: String){
126
+ let pluginResult = CDVPluginResult(
127
+ status: CDVCommandStatus_OK,
128
+ messageAs: result
129
+ )
130
+ self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
131
+ if (bleActionQueue.first?.id == command.callbackId) {
132
+ removeFromQueue()
133
+ }
134
+ }
135
+
136
+ //helper to return a boolean
137
+ private func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: Bool) {
138
+ let pluginResult = CDVPluginResult(
139
+ status: CDVCommandStatus_OK,
140
+ messageAs: result
141
+ )
142
+ self.commandDelegate!.send(pluginResult, callbackId: command.callbackId)
143
+ if (bleActionQueue.first?.id == command.callbackId) {
144
+ removeFromQueue()
145
+ }
146
+ }
147
+
148
+ //helper to return a JSon object
149
+ func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: DiscoveredDeviceType){
150
+ let pluginResult = CDVPluginResult(
151
+ status: CDVCommandStatus_OK,
152
+ messageAs: result.ToJSON()
153
+ )
154
+ self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
155
+ if (bleActionQueue.first?.id == command.callbackId) {
156
+ removeFromQueue()
157
+ }
158
+ }
159
+
160
+ //helper to return a String with keeping the callback
161
+ func sendSuccessWithMultipleResponse(command: CDVInvokedUrlCommand, result: String){
162
+ let pluginResult = CDVPluginResult(
163
+ status: CDVCommandStatus_OK,
164
+ messageAs: result
165
+ )
166
+ pluginResult!.setKeepCallbackAs(true);
167
+ self.commandDelegate!.send( pluginResult, callbackId: command.callbackId )
168
+ if (bleActionQueue.first?.id == command.callbackId) {
169
+ removeFromQueue()
170
+ }
171
+ }
172
+
173
+ //helper to return a JSon DiscoveredDeviceType object with keeping the callback
174
+ func sendSuccessWithMultipleResponse(command: CDVInvokedUrlCommand, result: DiscoveredDeviceType){
175
+ let pluginResult = CDVPluginResult(
176
+ status: CDVCommandStatus_OK,
177
+ messageAs: result.ToJSON()
178
+ )
179
+ pluginResult!.setKeepCallbackAs(true);
180
+ self.commandDelegate!.send( pluginResult, callbackId: command.callbackId )
181
+ if (bleActionQueue.first?.id == command.callbackId) {
182
+ removeFromQueue()
183
+ }
184
+ }
185
+ //helper to return a JSon Array object object
186
+ func sendSuccessWithSingleResponse(command: CDVInvokedUrlCommand, result: [[AnyHashable: Any]]) {
187
+ let pluginResult = CDVPluginResult(
188
+ status: CDVCommandStatus_OK,
189
+ messageAs: result
190
+ )
191
+ self.commandDelegate!.send( pluginResult, callbackId: command.callbackId )
192
+ if (bleActionQueue.first?.id == command.callbackId) {
193
+ removeFromQueue()
194
+ } }
195
+
196
+ //helper to send back an error
197
+ func sendError(command: CDVInvokedUrlCommand, result: String){
198
+ let pluginResult = CDVPluginResult(
199
+ status: CDVCommandStatus_ERROR,
200
+ messageAs: result
201
+ )
202
+ self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
203
+ if (bleActionQueue.first?.id == command.callbackId) {
204
+ removeFromQueue()
205
+ } }
206
+
207
+ func sendError(command: CDVInvokedUrlCommand, result: CordovaBLEError){
208
+ let pluginResult = CDVPluginResult(
209
+ status: CDVCommandStatus_ERROR,
210
+ messageAs: result.toJSON()
211
+ )
212
+ self.commandDelegate!.send( pluginResult, callbackId: command.callbackId)
213
+ if (bleActionQueue.first?.id == command.callbackId) {
214
+ removeFromQueue()
215
+ }
216
+ }
217
+
218
+
219
+ //Is BLE available
220
+ @objc(checkAvailable:)
221
+ func checkAvailable(command: CDVInvokedUrlCommand) {
222
+ addToQueue(command: command, bleAction: {[self] in
223
+ DispatchQueue.main.async {
224
+
225
+ //from ios5
226
+ if ( floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_5_1) ){
227
+ self.sendError(command: command, result: IoTizeBleError.BleUnsupported().message)
228
+ }
229
+
230
+ //check State
231
+ self.bleController.checkState(completion: {
232
+ (error: IoTizeBleError?) -> () in
233
+
234
+ DispatchQueue.main.async {
235
+
236
+ if (error != nil){
237
+ self.lastError = error
238
+ self.sendError(command: command, result: error!.message)
239
+ }
240
+ else {
241
+ self.sendSuccessWithSingleResponse(command: command, result: true)
242
+ }
243
+
244
+ }
245
+ })
246
+ }
247
+ })
248
+ }
249
+
250
+
251
+ //Start scanning IoTize devices
252
+ @objc(startScan:)
253
+ func startScan(command: CDVInvokedUrlCommand) {
254
+ addToQueue(command: command, bleAction: {[self] in
255
+ if (!self.isReady()){
256
+
257
+ DispatchQueue.main.async {
258
+ Thread.sleep(forTimeInterval: 0.01)
259
+ self.startScan(command: command)
260
+ }
261
+ return
262
+ }
263
+
264
+ self.bleController.beginScan(completion: {
265
+ (result: Any, error: IoTizeBleError?) -> () in
266
+
267
+ DispatchQueue.main.async {
268
+
269
+ if (error != nil){
270
+ self.lastError = error
271
+ self.sendError(command: command, result: error!.message)
272
+ }
273
+ else if let resultString = result as? String{
274
+ self.sendSuccessWithMultipleResponse(command: command, result: resultString)
275
+ } else if let resultDiscoveredDevice = result as? DiscoveredDeviceType {
276
+ self.sendSuccessWithMultipleResponse(command: command, result: resultDiscoveredDevice)
277
+ } else if let resultDevice = result as? CBPeripheral {
278
+ self.sendSuccessWithMultipleResponse(command: command, result: CBPeripheralConverter.toDiscoveredDeviceType(device: resultDevice))
279
+ } else {
280
+ }
281
+ }
282
+ })
283
+ })
284
+ }
285
+
286
+ //Stop scanning
287
+ @objc(stopScan:)
288
+ func stopScan(command: CDVInvokedUrlCommand) {
289
+ addToQueue(command: command, bleAction: {[self] in
290
+ bleController.stopScan();
291
+ self.sendSuccessWithSingleResponse(command: command, result: "OK")
292
+ })
293
+ }
294
+
295
+
296
+ //Connect to a device using its UUID
297
+ @objc(connectAndDiscoverTapServices:)
298
+ func connectAndDiscoverTapServices(command: CDVInvokedUrlCommand) {
299
+ addToQueue(command: command, bleAction: {[self] in
300
+ //we need the UUID of the device
301
+ if (command.arguments.count == 0){
302
+ let error = CordovaBLEError.IllegalArgument("Missing arguments")
303
+ self.sendError(command: command, result: error)
304
+ return
305
+ }
306
+
307
+ let deviceUUID = command.arguments[0] as? String ?? ""
308
+
309
+ bleController.useBLETapPeripheral = true
310
+
311
+ bleController.connectWithUUID(device: deviceUUID, completion: {
312
+ (state: Any?, error: IoTizeBleError?) -> () in
313
+
314
+ DispatchQueue.main.async {
315
+
316
+ if (error != nil){
317
+ self.lastError = error
318
+ self.sendError(command: command, result: error!.message)
319
+ }
320
+ else {
321
+ //printBLE("##> Sending Connected Ok")
322
+ let _state = state as? String
323
+
324
+ self.sendSuccessWithMultipleResponse(command: command, result: _state ?? "") // keep callback
325
+ }
326
+ }
327
+ })
328
+ })
329
+ }
330
+
331
+
332
+ @objc(connect:)
333
+ func connect(command: CDVInvokedUrlCommand) {
334
+ addToQueue(command: command, bleAction: {[self] in
335
+ //we need the UUID of the device
336
+ if (command.arguments.count == 0){
337
+ self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
338
+ return
339
+ }
340
+
341
+ let deviceUUID = command.arguments[0] as? String ?? ""
342
+
343
+ bleController.useBLETapPeripheral = false
344
+
345
+ bleController.connectWithUUID(device: deviceUUID, completion: {
346
+ (state: Any?, error: IoTizeBleError?) -> () in
347
+
348
+ DispatchQueue.main.async {
349
+
350
+ if (error != nil){
351
+ self.lastError = error
352
+ self.sendError(command: command, result: error!.message)
353
+ }
354
+ else {
355
+ //printBLE("##> Sending Connected Ok")
356
+ let _state = state as? String
357
+
358
+ self.sendSuccessWithMultipleResponse(command: command, result: _state ?? "") // keep callback
359
+ }
360
+ }
361
+ })
362
+ })
363
+ }
364
+
365
+ //Disconnect from a device using its name
366
+ @objc(disConnect:)
367
+ func disConnect(command: CDVInvokedUrlCommand) {
368
+ addToQueue(command: command, bleAction: { [self] in
369
+ //we need the name of the device
370
+ if (command.arguments.count == 0){
371
+ self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
372
+ return
373
+ }
374
+
375
+ bleController.disconnect( completion: {
376
+ (error: IoTizeBleError?) -> () in
377
+
378
+ DispatchQueue.main.async {
379
+
380
+ if (error != nil){
381
+ self.lastError = error
382
+ self.sendError(command: command, result: error!.message)
383
+ }
384
+ else {
385
+ self.sendSuccessWithSingleResponse(command: command, result: "OK")
386
+ }
387
+ }
388
+ })
389
+ })
390
+ }
391
+
392
+ //Retrieve additional information
393
+ @objc(getLastError:)
394
+ func getLastError(command: CDVInvokedUrlCommand) {
395
+ addToQueue(command: command, bleAction: {[self] in
396
+ let msg: String = (lastError != nil) ? (lastError!.message) : ""
397
+ self.sendSuccessWithSingleResponse(command: command, result: msg)
398
+ })
399
+ }
400
+
401
+ //Send Data to device
402
+ @objc(sendRequest:)
403
+ func sendRequest(command: CDVInvokedUrlCommand) {
404
+
405
+ addToQueue(command: command, bleAction: {[self] in
406
+ printBLE("##> SendRequest")
407
+ //we need data to send
408
+ if (command.arguments.count == 1){
409
+ self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
410
+ return
411
+ }
412
+
413
+ let data = command.arguments[1] as? String ?? ""
414
+
415
+ bleController.sendRequest(data: data, completion: {
416
+ (response: Any, error: IoTizeBleError?) -> () in
417
+
418
+ DispatchQueue.main.async {
419
+
420
+ if (error != nil){
421
+ self.lastError = error
422
+ self.sendError(command: command, result: error!.message)
423
+ }
424
+ else {
425
+ if let responseString = response as? String {
426
+ self.sendSuccessWithSingleResponse(command: command, result: responseString)
427
+ }
428
+ else if let responseDiscoveredDevice = response as? DiscoveredDeviceType {
429
+ self.sendSuccessWithSingleResponse(command: command, result: responseDiscoveredDevice)
430
+ } else if let responseDevice = response as? CBPeripheral {
431
+ self.sendSuccessWithSingleResponse(command: command, result: CBPeripheralConverter.toDiscoveredDeviceType(device: responseDevice))
432
+ }
433
+ }
434
+ }
435
+ })
436
+ })
437
+ }
438
+
439
+ @objc(isConnected:)
440
+ func isConnected(command: CDVInvokedUrlCommand) {
441
+ addToQueue(command: command, bleAction: { [self] in
442
+ var status: Bool ;
443
+
444
+ if (command.arguments.count < 1) {
445
+ let error = CordovaBLEError.IllegalArgument("Missing arguments")
446
+ self.sendError(command: command, result: error)
447
+ }
448
+
449
+ let deviceUUID = command.arguments[0] as? String ?? ""
450
+ do {
451
+ status = try bleController.isConnected(deviceUUID)
452
+ self.sendSuccessWithSingleResponse(command: command, result: status)
453
+ }
454
+ catch {
455
+ if (error is CordovaBLEError) {
456
+ self.sendError(command: command, result: (error as! CordovaBLEError))
457
+ } else {
458
+ let cordovaError = CordovaBLEError.InternalError("Unkown error")
459
+ self.sendError(command: command, result: cordovaError)
460
+ }
461
+ }
462
+ })
463
+
464
+ }
465
+
466
+ func isReady() -> Bool {
467
+ return bleController.isReady()
468
+ }
469
+
470
+ @objc(discoverServices:)
471
+ func discoverServices(command: CDVInvokedUrlCommand) {
472
+ addToQueue(command: command, bleAction: {[self] in
473
+ printBLE("discoverServices called")
474
+ if (command.arguments.count == 0){
475
+ self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
476
+ return
477
+ }
478
+
479
+ let deviceUUID = command.arguments[0] as? String ?? ""
480
+
481
+ bleController.discoverServices(forUUID: deviceUUID) { (anyPeripheral, error) in
482
+ if (error != nil) {
483
+ self.lastError = error
484
+ self.sendError(command: command, result: error?.message ?? "discoverServicesError")
485
+ } else {
486
+ if let peripheral = anyPeripheral as? CBPeripheral {
487
+ let result = CBPeripheralConverter.toServiceDescriptionsJSON(device: peripheral)
488
+ self.sendSuccessWithSingleResponse(command: command, result: result)
489
+ }
490
+ }
491
+ }
492
+ })
493
+ }
494
+
495
+ @objc(characteristicWriteWithoutResponse:)
496
+ func characteristicWriteWithoutResponse(command: CDVInvokedUrlCommand) {
497
+
498
+ addToQueue(command: command, bleAction: {[self] in
499
+ printBLE("characteristicWriteWithoutResponse called")
500
+ if (command.arguments.count < 4){
501
+ self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
502
+ return
503
+ }
504
+ let deviceID = command.arguments[0] as? String ?? ""
505
+
506
+ guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
507
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
508
+ self.sendError(command: command, result: cordovaError)
509
+ return
510
+ }
511
+ guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
512
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
513
+ self.sendError(command: command, result: cordovaError)
514
+ return
515
+ }
516
+
517
+ let dataToWrite = Data(Request.stringToHexArray(command.arguments[3] as? String ?? ""))
518
+
519
+ bleController.characteristicWriteWithoutResponse(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, data: dataToWrite, completion: { (error) in
520
+ if (error != nil) {
521
+ self.sendError(command: command, result: error!.message)
522
+ return
523
+ }
524
+ self.sendSuccessWithSingleResponse(command: command, result: "OK")
525
+ })
526
+ })
527
+ }
528
+
529
+ @objc(characteristicWrite:)
530
+ func characteristicWrite(command: CDVInvokedUrlCommand) {
531
+ addToQueue(command: command, bleAction: {[self] in
532
+ printBLE("characteristicWrite called")
533
+ if (command.arguments.count < 4){
534
+ self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
535
+ return
536
+ }
537
+ let deviceID = command.arguments[0] as? String ?? ""
538
+
539
+ guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
540
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
541
+ self.sendError(command: command, result: cordovaError)
542
+ return
543
+ }
544
+
545
+ guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
546
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
547
+
548
+ self.sendError(command: command, result: cordovaError)
549
+ return
550
+ }
551
+
552
+ let dataToWrite = Data(Request.stringToHexArray(command.arguments[3] as? String ?? ""))
553
+
554
+ bleController.characteristicWrite(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, data: dataToWrite, completion: { (error) in
555
+ if (error != nil) {
556
+ self.sendError(command: command, result: error!.message)
557
+ return
558
+ }
559
+ self.sendSuccessWithSingleResponse(command: command, result: "OK")
560
+ })
561
+ })
562
+ }
563
+
564
+ @objc(characteristicRead:)
565
+ func characteristicRead(command: CDVInvokedUrlCommand) {
566
+
567
+ addToQueue(command: command, bleAction: {[self] in
568
+ printBLE("characteristicRead called")
569
+ if (command.arguments.count < 3){
570
+ self.sendError(command: command, result: CordovaBLEError.IllegalArgument("Missing arguments"))
571
+ return
572
+ }
573
+ let deviceID = command.arguments[0] as? String ?? ""
574
+ guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
575
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
576
+ self.sendError(command: command, result: cordovaError)
577
+ return
578
+ }
579
+ guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
580
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
581
+ self.sendError(command: command, result: cordovaError)
582
+ return
583
+ }
584
+
585
+ bleController.characteristicRead(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { (readData, error) in
586
+ if (error != nil) {
587
+ self.sendError(command: command, result: error!.message)
588
+ return
589
+ }
590
+ let data = readData as! String
591
+ self.sendSuccessWithSingleResponse(command: command, result: data)
592
+ })
593
+ })
594
+
595
+
596
+ }
597
+
598
+ @objc(characteristicStartNotification:)
599
+ func characteristicStartNotification(command: CDVInvokedUrlCommand) {
600
+
601
+ addToQueue(command: command, bleAction: {[self] () in
602
+ printBLE("characteristicStartNotification called")
603
+ if (command.arguments.count < 3){
604
+ self.sendError(command: command, result: "characteristicStartNotification parameter error")
605
+ return
606
+ }
607
+ let deviceID = command.arguments[0] as? String ?? ""
608
+
609
+ guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
610
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
611
+ self.sendError(command: command, result: cordovaError)
612
+ return
613
+ }
614
+ guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
615
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
616
+ self.sendError(command: command, result: cordovaError)
617
+ return
618
+ }
619
+
620
+ bleController.characteristicStartNotification(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { error in
621
+ if (error != nil) {
622
+ printBLE("characteristicStartNotification response error")
623
+ self.sendError(command: command, result: error!.message)
624
+ return
625
+ }
626
+ printBLE("characteristicStartNotification response OK")
627
+ self.sendSuccessWithSingleResponse(command: command, result: "OK")
628
+ })
629
+ })
630
+
631
+ }
632
+
633
+ @objc(characteristicStopNotification:)
634
+ func characteristicStopNotification(command: CDVInvokedUrlCommand) {
635
+
636
+ addToQueue(command: command, bleAction: { [self] () in
637
+ printBLE("characteristicStopNotification called")
638
+ if (command.arguments.count < 3){
639
+ self.sendError(command: command, result: "characteristicStopNotification parameter error")
640
+ return
641
+ }
642
+ let deviceID = command.arguments[0] as? String ?? ""
643
+
644
+ guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
645
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
646
+ self.sendError(command: command, result: cordovaError)
647
+ return
648
+ }
649
+ guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
650
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
651
+ self.sendError(command: command, result: cordovaError)
652
+ return
653
+ }
654
+
655
+ bleController.characteristicStopNotification(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { error in
656
+ if (error != nil) {
657
+ printBLE("characteristicStopNotification response error")
658
+ self.sendError(command: command, result: error!.message)
659
+ return
660
+ }
661
+ printBLE("characteristicStopNotification response OK")
662
+ self.sendSuccessWithSingleResponse(command: command, result: "OK")
663
+ })
664
+ })
665
+
666
+ }
667
+
668
+ @objc(characteristicChanged:)
669
+ func characteristicChanged(command: CDVInvokedUrlCommand) {
670
+
671
+ addToQueue(command: command, bleAction: { [self] () in
672
+
673
+ printBLE("characteristicChanged called")
674
+ if (command.arguments.count < 3){
675
+ self.sendError(command: command, result: "SendRequest parameter error")
676
+ return
677
+ }
678
+ let deviceID = command.arguments[0] as? String ?? ""
679
+
680
+ guard let serviceUUID = CBUUIDHelper.fromString(command.arguments[1] as? String ?? "") else {
681
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[1] as? String ?? "")\" is not a valid BLE UUID")
682
+ self.sendError(command: command, result: cordovaError)
683
+ return
684
+ }
685
+ guard let characteristicUUID = CBUUIDHelper.fromString(command.arguments[2] as? String ?? "") else {
686
+ let cordovaError = CordovaBLEError.IllegalArgument("\"\(command.arguments[2] as? String ?? "")\" is not a valid BLE UUID")
687
+ self.sendError(command: command, result: cordovaError)
688
+ return
689
+ }
690
+
691
+ bleController.characteristicChanged(deviceID: deviceID, serviceUUID: serviceUUID, characteristicUUID: characteristicUUID, completion: { (result, error) in
692
+ if (error != nil) {
693
+ self.sendError(command: command, result: error!.message)
694
+ return
695
+ }
696
+ self.sendSuccessWithMultipleResponse(command: command, result: result as! String)
697
+ })
698
+ if (bleActionQueue.first?.id == command.callbackId) {
699
+ removeFromQueue()
700
+ }
701
+ })
702
+ }
703
+
704
+ func addToQueue(command: CDVInvokedUrlCommand, bleAction: @escaping () -> Void) {
705
+ bleActionQueue.enqueue(BLEAction(command.callbackId, bleAction))
706
+ if (!isHandlingQueue) {
707
+ isHandlingQueue = true
708
+ DispatchQueue.main.async {
709
+ bleAction()
710
+ }
711
+ }
712
+ }
713
+
714
+ func removeFromQueue() {
715
+ bleActionQueue.dequeue()
716
+ if (isHandlingQueue) {
717
+ if (bleActionQueue.first != nil) {
718
+ DispatchQueue.main.async {
719
+ self.bleActionQueue.first!.action()
720
+ }
721
+ } else {
722
+ isHandlingQueue = false
723
+ }
724
+ }
725
+ }
726
+
727
+
728
+ @objc(close:)
729
+ func close(command: CDVInvokedUrlCommand) {
730
+ disConnect(command: command)
731
+ }
732
+ }