@iotize/device-com-ble.cordova 3.6.2-alpha.2 → 3.6.4

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 (58) hide show
  1. package/README.md +174 -174
  2. package/bundles/iotize-device-com-ble.cordova.umd.js.map +1 -1
  3. package/bundles/iotize-device-com-ble.cordova.umd.min.js.map +1 -1
  4. package/esm2015/lib/ble-com-protocol.js.map +1 -1
  5. package/esm2015/lib/cordova-ble-error.js.map +1 -1
  6. package/esm2015/lib/cordova-interface.js.map +1 -1
  7. package/esm2015/lib/cordova-service-adapter.js.map +1 -1
  8. package/esm2015/lib/definitions.js.map +1 -1
  9. package/esm2015/lib/iotize-ble-cordova-plugin.js.map +1 -1
  10. package/esm2015/lib/logger.js.map +1 -1
  11. package/esm2015/lib/scanner.js.map +1 -1
  12. package/esm2015/lib/utility.js.map +1 -1
  13. package/esm2015/public_api.js.map +1 -1
  14. package/fesm2015/iotize-device-com-ble.cordova.js.map +1 -1
  15. package/package.json +1 -1
  16. package/plugin.xml +68 -68
  17. package/src/android/.gradle/6.8.2/fileHashes/fileHashes.lock +0 -0
  18. package/src/android/.gradle/6.8.2/gc.properties +0 -0
  19. package/src/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  20. package/src/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  21. package/src/android/.gradle/checksums/checksums.lock +0 -0
  22. package/src/android/.gradle/configuration-cache/gc.properties +0 -0
  23. package/src/android/.gradle/vcs-1/gc.properties +0 -0
  24. package/src/android/.gradle/vcsWorkingDirs/gc.properties +0 -0
  25. package/src/android/.idea/android.iml +9 -0
  26. package/src/android/.idea/gradle.xml +16 -0
  27. package/src/android/.idea/modules.xml +8 -0
  28. package/src/android/.idea/vcs.xml +6 -0
  29. package/src/android/build.gradle +30 -27
  30. package/src/android/src/ble/BLECom.java +5 -3
  31. package/src/android/src/ble/BLEComError.java +119 -119
  32. package/src/android/src/ble/BLEProtocol.java +874 -874
  33. package/src/android/src/ble/BLEScanner.java +283 -283
  34. package/src/android/src/ble/JSONBuilder.java +83 -83
  35. package/src/android/src/ble/PluginResponse.java +129 -129
  36. package/src/android/src/ble/TapUtility.java +26 -26
  37. package/src/android/src/ble/characteristics/AbstractLwM2MRequestCharacteristic.java +48 -48
  38. package/src/android/src/ble/characteristics/CharacteristicAdapter.java +221 -221
  39. package/src/android/src/ble/characteristics/CharacteristicAdapterCallbacks.java +21 -21
  40. package/src/android/src/ble/characteristics/LwM2M20BytesRequestCharacteristicAdapter.java +161 -161
  41. package/src/android/src/ble/characteristics/LwM2MMTURequestCharacteristicAdapter.java +134 -134
  42. package/src/android/src/ble/commands/BLECommand.java +18 -18
  43. package/src/android/src/ble/commands/CharacteristicOperationCompletedNotifier.java +37 -37
  44. package/src/android/src/ble/commands/CommandCompletedNotifier.java +10 -10
  45. package/src/android/src/ble/commands/DescriptorOperationCompletedNotifier.java +36 -36
  46. package/src/android/src/ble/commands/GattOperationCompletedNotifier.java +28 -28
  47. package/src/ios/BLECom.swift +744 -732
  48. package/src/ios/BLEManager.swift +41 -23
  49. package/src/ios/BLETapPeripheral.swift +5 -10
  50. package/src/ios/CBPeripheralConverter.swift +164 -139
  51. package/src/ios/Queue.swift +114 -108
  52. package/src/windows/IoTizeBLE.pdb +0 -0
  53. package/src/windows/IoTizeBLE.pri +0 -0
  54. package/src/windows/iotize-ble-com.js +159 -159
  55. package/www/plugin.js +1 -1
  56. package/src/android/.gradle/4.8.1/fileHashes/fileHashes.bin +0 -0
  57. package/src/android/.gradle/4.8.1/fileHashes/fileHashes.lock +0 -0
  58. /package/src/android/.gradle/{4.8.1 → 6.8.2}/fileChanges/last-build.bin +0 -0
@@ -13,6 +13,10 @@ typealias Completion = (IoTizeBleError?) -> ()
13
13
  //Callback type, methods with returning values
14
14
  typealias CompletionWithResponse = (Any? , IoTizeBleError?) -> ()
15
15
 
16
+ struct BLEConstants {
17
+ static let serviceUUID = CBUUID(string: "6C7B16C2-2A5B-8C9F-CF42-D31425470E7B")
18
+ }
19
+
16
20
  //Central manager handling devices and ble callbacks.
17
21
  class BLEManager: NSObject, CBCentralManagerDelegate
18
22
  {
@@ -20,7 +24,6 @@ class BLEManager: NSObject, CBCentralManagerDelegate
20
24
  private var centralManager: CBCentralManager!
21
25
 
22
26
  //IoTize devices are filtered using the UUID of the service used for data exchange
23
- let serviceUUID = CBUUID(string: "6C7B16C2-2A5B-8C9F-CF42-D31425470E7B")
24
27
 
25
28
  var blestateChangeCompletion: Completion? //callback called when the ble state is changing
26
29
  var connectionChangeCompletion: CompletionWithResponse? //callback called when the ble connection states is changing
@@ -29,7 +32,7 @@ class BLEManager: NSObject, CBCentralManagerDelegate
29
32
 
30
33
  var useBLETapPeripheral: Bool = false
31
34
 
32
- var discoveredPeripherals = [CBPeripheral]() //list of discovered devices
35
+ var discoveredPeripherals = [ExtendedCBPeripheral]() //list of discovered devices
33
36
 
34
37
  //currently connected device
35
38
  private var bleTapPeripheral: BLETapPeripheral?
@@ -50,14 +53,15 @@ class BLEManager: NSObject, CBCentralManagerDelegate
50
53
  }
51
54
 
52
55
 
53
- // Start Scanning Iotize devices
54
- func beginScan(completion: @escaping CompletionWithResponse){
56
+ // Start Scanning BLE devices
57
+ func beginScan(completion: @escaping CompletionWithResponse, serviceUUIDs: [CBUUID]?){
55
58
  printBLE("--> Start Scanning")
56
59
  if #available(iOS 10.0, *) {
57
60
  if (centralManager.state == CBManagerState.poweredOn){
58
61
  discoveryCompletion = completion
59
62
  discoveredPeripherals.removeAll()
60
- centralManager.scanForPeripherals(withServices: [serviceUUID], options: nil)
63
+ let actualServiceUUIDs = serviceUUIDs ?? [BLEConstants.serviceUUID]
64
+ centralManager.scanForPeripherals(withServices: serviceUUIDs, options: nil)
61
65
 
62
66
 
63
67
  discoveryCompletion!("Ok", nil)
@@ -118,16 +122,19 @@ class BLEManager: NSObject, CBCentralManagerDelegate
118
122
 
119
123
  //in ios the device should be scanned in order
120
124
  //to enable connection
121
- for item : CBPeripheral in discoveredPeripherals{
125
+ for item : ExtendedCBPeripheral in discoveredPeripherals{
122
126
 
123
- let name = item.identifier.uuidString
127
+ let name = item.peripheral.identifier.uuidString
124
128
 
125
129
  if (name == device){
126
- connect(item)
127
- break;
130
+ connect(item.peripheral)
131
+ return;
128
132
 
129
133
  }
130
134
  }
135
+
136
+ connectionChangeCompletion?(nil, IoTizeBleError.NoDeviceConnected())
137
+ connectionChangeCompletion = nil
131
138
  }
132
139
 
133
140
  // Disconnect from the currently selected device
@@ -189,17 +196,29 @@ class BLEManager: NSObject, CBCentralManagerDelegate
189
196
 
190
197
  //Called when a new device has been detected
191
198
  func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){
192
- //do we know this device
193
- if (!(discoveredPeripherals.contains(peripheral))){
199
+ //get element from discoveredPeripherals
200
+ if let registeredPeripheral = discoveredPeripherals.first(where: {$0.peripheral.identifier == peripheral.identifier}) {
201
+ // we update its values
202
+
203
+ } else
204
+ // if (!(discoveredPeripherals.contains(where peripheral)))
205
+ {
194
206
  //do we have a name
195
- if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String{
207
+ if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
196
208
  printBLE("### Did discover \(name)")
197
- //add peripheral to the table
198
- discoveredPeripherals.append(peripheral)
209
+ //store manufacturer data in peripheral if any
210
+ let extendedPeripheral = ExtendedCBPeripheral(peripheral: peripheral)
211
+ let manufacturerData = advertisementData[CBAdvertisementDataManufacturerDataKey] ?? nil
212
+ let txPower = advertisementData[CBAdvertisementDataTxPowerLevelKey] ?? nil
213
+ // if (!(discoveredPeripherals.contains(where peripheral))) {
214
+ if (!(discoveredPeripherals.contains(where: {$0.peripheral.identifier == peripheral.identifier}))) {
215
+ //add peripheral to the table
216
+ discoveredPeripherals.append(extendedPeripheral)
217
+ }
199
218
  //call the discovery callback
200
219
  if ( discoveryCompletion != nil){
201
220
  discoveryCompletion!(
202
- CBPeripheralConverter.toDiscoveredDeviceType(device: peripheral, rssi: RSSI as? Int)
221
+ CBPeripheralConverter.toDiscoveredDeviceType(device: peripheral, rssi: RSSI as? Int, txPower: txPower as? Int, scanRecord: manufacturerData as? NSData)
203
222
  , nil)
204
223
  }
205
224
  }
@@ -211,16 +230,15 @@ class BLEManager: NSObject, CBCentralManagerDelegate
211
230
 
212
231
  printBLE("### Did connect \(String(describing: peripheral.name))")
213
232
  if ( connectionChangeCompletion != nil){
214
-
215
233
  if (useBLETapPeripheral) {
216
- bleTapPeripheral?.connect(device: peripheral, manager: self, connectionChangeCompletion: connectionChangeCompletion)
234
+ bleTapPeripheral?.connect(device: peripheral, manager: self)
217
235
  } else {
218
236
  bleGenericPeripheral?.connect(device: peripheral, manager: self)
219
237
  }
220
238
 
221
239
  //callback without error
222
240
 
223
- // connectionChangeCompletion!("CONNECTED", nil) callback moved to didDiscoverCharacteristics
241
+ connectionChangeCompletion!("CONNECTED", nil)
224
242
  // connectionChangeCompletion = nil
225
243
 
226
244
  }
@@ -254,9 +272,10 @@ class BLEManager: NSObject, CBCentralManagerDelegate
254
272
  //callback without error, if we have requested this disconnection
255
273
  if ( disconnectionCompletion != nil){
256
274
  disconnectionCompletion!(nil)
275
+ disconnectionCompletion = nil
276
+ connectionChangeCompletion = nil
277
+ return
257
278
  }
258
- disconnectionCompletion = nil
259
- connectionChangeCompletion = nil
260
279
 
261
280
  if (bleGenericPeripheral != nil) {
262
281
  bleGenericPeripheral!.connectedDevice = nil
@@ -264,8 +283,7 @@ class BLEManager: NSObject, CBCentralManagerDelegate
264
283
  }
265
284
  if (bleTapPeripheral != nil) {
266
285
  bleTapPeripheral!.bleDevice = nil
267
- }
268
- }
286
+ } }
269
287
 
270
288
  func checkConnection(completion: @escaping Completion){
271
289
  if (useBLETapPeripheral) {
@@ -311,7 +329,7 @@ class BLEManager: NSObject, CBCentralManagerDelegate
311
329
  func isConnected(_ deviceUUID: String) throws -> Bool {
312
330
 
313
331
  // check if device is in the scan list
314
- guard let device = discoveredPeripherals.first(where: {$0.identifier.uuidString == deviceUUID}) else {
332
+ guard let device = discoveredPeripherals.first(where: {$0.peripheral.identifier.uuidString == deviceUUID})?.peripheral else {
315
333
  throw CordovaBLEError.InternalError("Peripheral does not exist")
316
334
  }
317
335
  if (useBLETapPeripheral) {
@@ -66,12 +66,6 @@ class BLETapPeripheral: NSObject, CBPeripheralDelegate{
66
66
  private static var LEN_PACKET = 19 // MTU = 23 - 3 - 1 num packet
67
67
  private let requestQueueManagementDelay = 0.002
68
68
 
69
- var connectionStateCompletion: CompletionWithResponse?
70
-
71
- init(connectionState: CompletionWithResponse?) {
72
- connectionStateCompletion = connectionState
73
- }
74
-
75
69
  override init(){
76
70
  super.init()
77
71
  DispatchQueue.global(qos: .background).async {
@@ -79,12 +73,12 @@ class BLETapPeripheral: NSObject, CBPeripheralDelegate{
79
73
  }
80
74
  }
81
75
 
82
- func connect( device: CBPeripheral, manager: BLEManager, connectionChangeCompletion: CompletionWithResponse?){
76
+ func connect( device: CBPeripheral, manager: BLEManager){
83
77
  bleManager = manager
84
78
  lastError = nil
85
79
  bleDevice = device
86
80
  bleDevice.delegate = self
87
- connectionStateCompletion = connectionChangeCompletion
81
+ printBLE("Discover Services of connected device")
88
82
  bleDevice.discoverServices([UUID_UPGRADE_SERVICE, SPPoverLE_SERVICE_UUID, SPPoverLE_SERVICE_UUID_FAST])
89
83
  }
90
84
 
@@ -92,7 +86,7 @@ class BLETapPeripheral: NSObject, CBPeripheralDelegate{
92
86
 
93
87
  //cleanup
94
88
  self.cancelRequests()
95
-
89
+ self.isReady = false
96
90
  bleDevice = nil
97
91
  bleManager = nil
98
92
  }
@@ -107,6 +101,8 @@ class BLETapPeripheral: NSObject, CBPeripheralDelegate{
107
101
  return
108
102
  }
109
103
 
104
+ printBLE("discovered services")
105
+
110
106
  for service in peripheral.services!{
111
107
  if service.uuid == UUID_UPGRADE_SERVICE{
112
108
  peripheral.discoverCharacteristics([UUID_UPGRADE_APP_INFO], for: service)
@@ -162,7 +158,6 @@ class BLETapPeripheral: NSObject, CBPeripheralDelegate{
162
158
  lastError = IoTizeBleError.CharacteristicSPPNotFound(peripheral: peripheral)
163
159
  } else {
164
160
  self.isReady = true
165
- connectionStateCompletion?("CONNECTED", nil)
166
161
  }
167
162
  }
168
163
 
@@ -1,139 +1,164 @@
1
- //
2
- // Copyright 2018 IoTize SAS Inc. Licensed under the MIT license.
3
- //
4
- // CBPeripheralConverter.swift
5
- // device-com-ble.cordova BLE Cordova Plugin
6
- //
7
-
8
- import CoreBluetooth
9
-
10
- struct DiscoveredDeviceType : Codable{
11
- public var name: String = ""
12
- public var address: String = ""
13
- public var rssi: Int?
14
-
15
- init(newName: String, newAddress: String, newRssi: Int?) {
16
- name = newName
17
- address = newAddress
18
- if (newRssi != nil) {
19
- rssi = newRssi
20
- }
21
- }
22
-
23
- func ToJSON() -> [AnyHashable: Any] {
24
- if self.rssi == nil {
25
- return ["name": name, "address": address]
26
- }
27
- return ["name": name, "address": address, "rssi": rssi!]
28
- }
29
-
30
- func toJSONString() throws -> String {
31
- let jsonEncoder = JSONEncoder()
32
- let jsonData = try jsonEncoder.encode(self)
33
-
34
- return String(data: jsonData, encoding: .utf8)!
35
-
36
- }
37
- }
38
-
39
-
40
- import Foundation
41
-
42
- class CBPeripheralConverter {
43
-
44
- public static func toDiscoveredDeviceType(device: CBPeripheral, rssi: Int? = nil) -> DiscoveredDeviceType {
45
- return DiscoveredDeviceType(newName: device.name!, newAddress: device.identifier.uuidString as String, newRssi: rssi)
46
- }
47
-
48
- public static func toJSONObject(device: CBPeripheral) -> [AnyHashable: Any] {
49
- return toDiscoveredDeviceType(device: device).ToJSON()
50
- }
51
- public static func toJSONString(device: CBPeripheral) throws -> String {
52
- return try toDiscoveredDeviceType(device: device).toJSONString()
53
- }
54
- public static func toServiceDescriptionsJSON(device: CBPeripheral) -> [[AnyHashable: Any]] {
55
- if let services = device.services {
56
- var serviceDescriptions: [ServiceDescription] = []
57
- for service in services {
58
- serviceDescriptions.append(ServiceDescription(service: service))
59
- }
60
-
61
- return serviceDescriptions.map {$0.toDictionary()}
62
-
63
- }
64
- return []
65
-
66
- }
67
- }
68
-
69
- struct DescriptorDescription: Codable {
70
- var uuid: String
71
- var permissions: UInt
72
-
73
- init (descriptor: CBDescriptor) {
74
- uuid = descriptor.uuid.uuidString
75
- permissions = descriptor.characteristic!.properties.rawValue
76
- }
77
- func toDictionary() -> [AnyHashable: Any] {
78
- return ["uuid": uuid, "permissions": permissions]
79
- }
80
- }
81
-
82
- struct CharacteristicDescription: Codable {
83
- var uuid: String
84
- var descriptors: [DescriptorDescription]?
85
-
86
- init(characteristic: CBCharacteristic) {
87
- uuid = characteristic.uuid.uuidString
88
- if let characteristicDescriptors = characteristic.descriptors {
89
- descriptors = []
90
- for desc in characteristicDescriptors {
91
- descriptors?.append( DescriptorDescription(descriptor: desc) )
92
- }
93
- }
94
- }
95
- func toDictionary() -> [AnyHashable: Any] {
96
- return ["uuid": uuid, "descriptors": descriptors?.map {$0.toDictionary()} ?? [] ]
97
- }
98
- }
99
-
100
- struct ServiceDescription: Codable {
101
- var uuid: String
102
- var characteristics: [CharacteristicDescription]?
103
-
104
- init(service: CBService) {
105
- uuid = service.uuid.uuidString
106
- if let serviceCharacteristics = service.characteristics {
107
- characteristics = []
108
- for char in serviceCharacteristics {
109
- characteristics?.append( CharacteristicDescription(characteristic: char) )
110
- }
111
- }
112
- }
113
-
114
- func toDictionary() -> [AnyHashable: Any] {
115
- return ["uuid": uuid, "characteristics": characteristics?.map {$0.toDictionary()} ?? [] ]
116
- }
117
- }
118
-
119
- struct CBUUIDHelper {
120
-
121
- static let UUID_BASE = "0000XXXX-0000-1000-8000-00805f9b34fb";
122
-
123
- static func fromString(_ string: String) -> CBUUID? {
124
-
125
- let stringUUID:UUID?
126
- if (string.count == 4) {
127
- let actualUUID = UUID_BASE.replacingOccurrences(of: "XXXX", with: string)
128
- printBLE(">>>Short UUID \(string) replaced by \(actualUUID)")
129
- stringUUID = UUID(uuidString: actualUUID)
130
- } else {
131
- stringUUID = UUID(uuidString: string)
132
- }
133
- if (stringUUID == nil) {
134
- return nil
135
- }
136
- return CBUUID(nsuuid: stringUUID!)
137
-
138
- }
139
- }
1
+ //
2
+ // Copyright 2018 IoTize SAS Inc. Licensed under the MIT license.
3
+ //
4
+ // CBPeripheralConverter.swift
5
+ // device-com-ble.cordova BLE Cordova Plugin
6
+ //
7
+
8
+ import CoreBluetooth
9
+
10
+ struct DiscoveredDeviceType : Codable{
11
+ public var name: String = ""
12
+ public var address: String = ""
13
+ public var rssi: Int?
14
+ public var txPower: Int?
15
+ public var scanRecord: [UInt8]?
16
+
17
+ init(newName: String, newAddress: String, newRssi: Int?, newTxPower: Int?, newScanRecord: NSData?) {
18
+ name = newName
19
+ address = newAddress
20
+ if (newRssi != nil) {
21
+ rssi = newRssi
22
+ }
23
+ if (newTxPower != nil) {
24
+ txPower = newTxPower
25
+ }
26
+ if let record = newScanRecord {
27
+ scanRecord = [UInt8](record)
28
+ }
29
+ }
30
+
31
+ func ToJSON() -> [AnyHashable: Any] {
32
+ var result: NSMutableDictionary = ["name": name, "address": address]
33
+ if let rssi = self.rssi {
34
+ result.setValue(rssi, forKey: "rssi")
35
+ }
36
+ if let txPower = self.txPower {
37
+ result.setValue(txPower, forKey: "txPower")
38
+ }
39
+ if let scanRecord = self.scanRecord {
40
+ result.setValue(scanRecord, forKey: "scanRecord")
41
+ }
42
+ return result as! [AnyHashable: Any]
43
+ }
44
+
45
+ func toJSONString() throws -> String {
46
+ let jsonEncoder = JSONEncoder()
47
+ let jsonData = try jsonEncoder.encode(self)
48
+
49
+ return String(data: jsonData, encoding: .utf8)!
50
+
51
+ }
52
+ }
53
+
54
+
55
+ import Foundation
56
+
57
+ class CBPeripheralConverter {
58
+
59
+ public static func toDiscoveredDeviceType(device: CBPeripheral, rssi: Int? = nil, txPower: Int? = nil, scanRecord: NSData? = nil) -> DiscoveredDeviceType {
60
+ return DiscoveredDeviceType(newName: device.name!, newAddress: device.identifier.uuidString as String, newRssi: rssi, newTxPower: txPower, newScanRecord: scanRecord)
61
+ }
62
+
63
+ public static func toJSONObject(device: CBPeripheral) -> [AnyHashable: Any] {
64
+ return toDiscoveredDeviceType(device: device).ToJSON()
65
+ }
66
+ public static func toJSONString(device: CBPeripheral) throws -> String {
67
+ return try toDiscoveredDeviceType(device: device).toJSONString()
68
+ }
69
+ public static func toServiceDescriptionsJSON(device: CBPeripheral) -> [[AnyHashable: Any]] {
70
+ if let services = device.services {
71
+ var serviceDescriptions: [ServiceDescription] = []
72
+ for service in services {
73
+ serviceDescriptions.append(ServiceDescription(service: service))
74
+ }
75
+
76
+ return serviceDescriptions.map {$0.toDictionary()}
77
+
78
+ }
79
+ return []
80
+
81
+ }
82
+ }
83
+
84
+ struct DescriptorDescription: Codable {
85
+ var uuid: String
86
+ var permissions: UInt
87
+
88
+ init (descriptor: CBDescriptor) {
89
+ uuid = descriptor.uuid.uuidString
90
+ permissions = descriptor.characteristic!.properties.rawValue
91
+ }
92
+ func toDictionary() -> [AnyHashable: Any] {
93
+ return ["uuid": uuid, "permissions": permissions]
94
+ }
95
+ }
96
+
97
+ struct CharacteristicDescription: Codable {
98
+ var uuid: String
99
+ var descriptors: [DescriptorDescription]?
100
+
101
+ init(characteristic: CBCharacteristic) {
102
+ uuid = characteristic.uuid.uuidString
103
+ if let characteristicDescriptors = characteristic.descriptors {
104
+ descriptors = []
105
+ for desc in characteristicDescriptors {
106
+ descriptors?.append( DescriptorDescription(descriptor: desc) )
107
+ }
108
+ }
109
+ }
110
+ func toDictionary() -> [AnyHashable: Any] {
111
+ return ["uuid": uuid, "descriptors": descriptors?.map {$0.toDictionary()} ?? [] ]
112
+ }
113
+ }
114
+
115
+ struct ServiceDescription: Codable {
116
+ var uuid: String
117
+ var characteristics: [CharacteristicDescription]?
118
+
119
+ init(service: CBService) {
120
+ uuid = service.uuid.uuidString
121
+ if let serviceCharacteristics = service.characteristics {
122
+ characteristics = []
123
+ for char in serviceCharacteristics {
124
+ characteristics?.append( CharacteristicDescription(characteristic: char) )
125
+ }
126
+ }
127
+ }
128
+
129
+ func toDictionary() -> [AnyHashable: Any] {
130
+ return ["uuid": uuid, "characteristics": characteristics?.map {$0.toDictionary()} ?? [] ]
131
+ }
132
+ }
133
+
134
+ struct CBUUIDHelper {
135
+
136
+ static let UUID_BASE = "0000XXXX-0000-1000-8000-00805f9b34fb";
137
+
138
+ static func fromString(_ string: String) -> CBUUID? {
139
+
140
+ let stringUUID:UUID?
141
+ if (string.count == 4) {
142
+ let actualUUID = UUID_BASE.replacingOccurrences(of: "XXXX", with: string)
143
+ printBLE(">>>Short UUID \(string) replaced by \(actualUUID)")
144
+ stringUUID = UUID(uuidString: actualUUID)
145
+ } else {
146
+ stringUUID = UUID(uuidString: string)
147
+ }
148
+ if (stringUUID == nil) {
149
+ return nil
150
+ }
151
+ return CBUUID(nsuuid: stringUUID!)
152
+
153
+ }
154
+ }
155
+
156
+ class ExtendedCBPeripheral {
157
+ public var peripheral: CBPeripheral
158
+ public var manufacturerData: NSData?
159
+ public var rssi: Int?
160
+
161
+ init(peripheral: CBPeripheral) {
162
+ self.peripheral = peripheral
163
+ }
164
+ }