@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.
- package/README.md +174 -177
- package/bundles/iotize-device-com-ble.cordova.umd.js +102 -69
- package/bundles/iotize-device-com-ble.cordova.umd.js.map +1 -1
- package/bundles/iotize-device-com-ble.cordova.umd.min.js +16 -0
- package/bundles/iotize-device-com-ble.cordova.umd.min.js.map +1 -0
- package/esm2015/lib/ble-com-protocol.js +10 -10
- package/esm2015/lib/ble-com-protocol.js.map +1 -1
- package/esm2015/lib/cordova-ble-error.js +11 -2
- package/esm2015/lib/cordova-ble-error.js.map +1 -1
- package/esm2015/lib/cordova-interface.js.map +1 -1
- package/esm2015/lib/cordova-service-adapter.js +15 -14
- package/esm2015/lib/cordova-service-adapter.js.map +1 -1
- package/esm2015/lib/cordova-service-adapter.metadata.json +1 -1
- package/esm2015/lib/definitions.js +0 -2
- package/esm2015/lib/definitions.js.map +1 -1
- package/esm2015/lib/iotize-ble-cordova-plugin.js +59 -51
- package/esm2015/lib/iotize-ble-cordova-plugin.js.map +1 -1
- package/esm2015/lib/iotize-ble-cordova-plugin.metadata.json +1 -1
- package/esm2015/lib/iotize-ble-cordova-plugin.ngsummary.json +1 -1
- package/esm2015/lib/logger.js +1 -1
- package/esm2015/lib/logger.js.map +1 -1
- package/esm2015/lib/scanner.js +14 -12
- package/esm2015/lib/scanner.js.map +1 -1
- package/esm2015/lib/scanner.metadata.json +1 -1
- package/esm2015/lib/utility.js +1 -1
- package/esm2015/lib/utility.js.map +1 -1
- package/esm2015/public_api.js +4 -4
- package/esm2015/public_api.js.map +1 -1
- package/fesm2015/iotize-device-com-ble.cordova.js +93 -74
- package/fesm2015/iotize-device-com-ble.cordova.js.map +1 -1
- package/iotize-device-com-ble.cordova.metadata.json +1 -1
- package/lib/ble-com-protocol.d.ts +4 -4
- package/lib/cordova-ble-error.d.ts +12 -3
- package/lib/cordova-service-adapter.d.ts +1 -1
- package/lib/definitions.d.ts +1 -1
- package/lib/iotize-ble-cordova-plugin.d.ts +4 -3
- package/lib/scanner.d.ts +4 -4
- package/package.json +1 -1
- package/plugin.xml +66 -63
- package/public_api.d.ts +5 -5
- package/src/android/.gradle/4.8.1/fileHashes/fileHashes.bin +0 -0
- package/src/android/.gradle/4.8.1/fileHashes/fileHashes.lock +0 -0
- package/src/android/build.gradle +1 -0
- package/src/android/src/ble/BLECom.java +559 -558
- package/src/ios/BLECom.swift +732 -732
- package/src/windows/IoTizeBLE.pdb +0 -0
- package/src/windows/IoTizeBLE.pri +0 -0
- package/src/windows/iotize-ble-com.js +159 -179
- package/www/plugin.js +1 -1
package/src/ios/BLECom.swift
CHANGED
|
@@ -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
|
+
}
|