From 6feefbc6017d27800890ba1eb2ef8713eab144fd Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 14 Oct 2021 20:36:06 -0700 Subject: [PATCH] Update BLE --- MeshtasticClient/Helpers/BLEManager.swift | 93 +++++++++++--------- MeshtasticClient/Model/MyInfoModel.swift | 15 ++-- MeshtasticClient/Model/PeripheralModel.swift | 2 +- MeshtasticClient/Views/Nodes/NodeList.swift | 2 +- 4 files changed, 57 insertions(+), 55 deletions(-) diff --git a/MeshtasticClient/Helpers/BLEManager.swift b/MeshtasticClient/Helpers/BLEManager.swift index 849486b4..e542be7c 100644 --- a/MeshtasticClient/Helpers/BLEManager.swift +++ b/MeshtasticClient/Helpers/BLEManager.swift @@ -19,6 +19,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph @Published var isSwitchedOn = false @Published var peripherals = [Peripheral]() + @Published var peripherals2 = [CBPeripheral]() + private var broadcastNodeId: UInt32 = 4294967295 /* Meshtastic Service Details */ @@ -38,8 +40,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph self.messageData = MessageData() self.lastConnectionError = "" super.init() - //let options = [CBCentralManagerOptionRestoreIdentifierKey: "com.meshtastic.ble-central"] - centralManager = CBCentralManager(delegate: self, queue: nil)//, options: options) + let options = [CBCentralManagerOptionRestoreIdentifierKey: "com.meshtastic.ble-central"] + centralManager = CBCentralManager(delegate: self, queue: nil, options: options) centralManager.delegate = self meshData.load() messageData.load() @@ -63,6 +65,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if isSwitchedOn { peripherals.removeAll() + peripherals2.removeAll() centralManager.scanForPeripherals(withServices: [meshtasticServiceCBUUID], options: nil) print("Scanning Started") } @@ -73,7 +76,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if centralManager.isScanning { - self.centralManager.stopScan() print("Stopped Scanning") } @@ -81,11 +83,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph // Connect to a specific peripheral func connectTo(peripheral: CBPeripheral) { + stopScanning() if connectedPeripheral != nil && connectedPeripheral.peripheral.state == CBPeripheralState.connected { self.disconnectDevice() } - //connectedPeripheral.peripheral = peripheral + self.centralManager?.connect(peripheral) print("Connected to: \(peripheral.name ?? "Unknown")") } @@ -96,17 +99,11 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if connectedPeripheral != nil && connectedPeripheral.peripheral.state == CBPeripheralState.connected { self.centralManager?.cancelPeripheralConnection(connectedPeripheral.peripheral) - } else { - - connectedNode = nil - connectedPeripheral = nil } } // Called each time a peripheral is discovered func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { - - peripheral.delegate = self var peripheralName: String = peripheral.name ?? "Unknown" @@ -115,21 +112,26 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph } let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, name: peripheralName, rssi: RSSI.intValue, peripheral: peripheral, myInfo: nil) - + peripherals.append(newPeripheral) + peripherals2.append(peripheral) print("Adding peripheral: \(peripheralName)"); } // called when a peripheral is connected func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { - - peripheral.delegate = self + connectedPeripheral = peripherals.filter({ $0.peripheral.identifier == peripheral.identifier }).first - - peripheral.discoverServices([meshtasticServiceCBUUID]) + connectedPeripheral.peripheral.discoverServices(nil)//[meshtasticServiceCBUUID]) print("Peripheral connected: " + peripheral.name!) } + func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) { + print("willRestoreState: \(dict)") + let restoredPeripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] + print("restoredPeripherals: \(String(describing: restoredPeripherals))") + } + // Send Broadcast Message public func sendMessage(message: String) -> Bool { @@ -238,6 +240,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if (service.uuid == meshtasticServiceCBUUID) { print ("Meshtastic service OK") + //peripheral.discoverCharacteristics(nil, for: service) peripheral.discoverCharacteristics([TORADIO_UUID, FROMRADIO_UUID, FROMNUM_UUID], for: service) } } @@ -298,7 +301,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph case FROMNUM_UUID: peripheral.readValue(for: FROMNUM_characteristic) let byteArrayFromData: [UInt8] = [UInt8](characteristic.value!) - let stringFromByteArray = String(data: Data(_: byteArrayFromData), encoding: .ascii) + let stringFromByteArray = String(data: Data(_: byteArrayFromData), encoding: .utf8) print("string array data \(stringFromByteArray)") //print(characteristic.value?. ?? "no value") @@ -308,9 +311,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph { return } - print(characteristic.value ?? "no value") + //print(characteristic.value ?? "no value") - // print(characteristic.value?.hexDescription ?? "no value") + print(characteristic.value?.hexDescription ?? "no value") var decodedInfo = FromRadio() decodedInfo = try! FromRadio(serializedData: characteristic.value!) @@ -322,6 +325,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph // Create a MyInfoModel let myInfoModel = MyInfoModel( + id: connectedPeripheral.peripheral.identifier, myNodeNum: decodedInfo.myInfo.myNodeNum, hasGps: decodedInfo.myInfo.hasGps_p, numBands: decodedInfo.myInfo.numBands, @@ -334,7 +338,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if connectedPeripheral != nil { connectedPeripheral.myInfo = myInfoModel // Save it to the connected node - connectedNode = meshData.nodes.first(where: {$0.num == myInfoModel.id}) + connectedNode = meshData.nodes.first(where: {$0.num == myInfoModel.myNodeNum}) } // Since the data is from the device itself we save all myInfo objects since they are always the most up to date @@ -358,7 +362,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph // Found a matching node lets update it let nodeMatch = meshData.nodes.first(where: { $0.id == decodedInfo.nodeInfo.num }) - if connectedPeripheral != nil && connectedPeripheral.myInfo?.id == nodeMatch?.num { + if connectedPeripheral != nil && connectedPeripheral.myInfo?.myNodeNum == nodeMatch?.num { connectedNode = nodeMatch } @@ -376,35 +380,38 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph } } // Set the connected node if the nodeInfo is for the connected node. - if connectedPeripheral != nil && connectedPeripheral.myInfo?.id == decodedInfo.nodeInfo.num { + if connectedPeripheral != nil && connectedPeripheral.myInfo?.myNodeNum == decodedInfo.nodeInfo.num { let nodeMatch = meshData.nodes.first(where: { $0.id == decodedInfo.nodeInfo.num }) if nodeMatch != nil { connectedNode = nodeMatch } } - meshData.nodes.append( - NodeInfoModel( - num: decodedInfo.nodeInfo.num, - user: NodeInfoModel.User( - id: decodedInfo.nodeInfo.user.id, - longName: decodedInfo.nodeInfo.user.longName, - shortName: decodedInfo.nodeInfo.user.shortName, - //macaddr: decodedInfo.nodeInfo.user.macaddr, - hwModel: String(describing: decodedInfo.nodeInfo.user.hwModel) - .uppercased()), - - position: NodeInfoModel.Position( - latitudeI: decodedInfo.nodeInfo.position.latitudeI, - longitudeI: decodedInfo.nodeInfo.position.longitudeI, - altitude: decodedInfo.nodeInfo.position.altitude, - batteryLevel: decodedInfo.nodeInfo.position.batteryLevel, - time: decodedInfo.nodeInfo.position.time), - - lastHeard: decodedInfo.nodeInfo.lastHeard, - snr: decodedInfo.nodeInfo.snr) - ) - meshData.save() + if decodedInfo.nodeInfo.hasUser { + + meshData.nodes.append( + NodeInfoModel( + num: decodedInfo.nodeInfo.num, + user: NodeInfoModel.User( + id: decodedInfo.nodeInfo.user.id, + longName: decodedInfo.nodeInfo.user.longName, + shortName: decodedInfo.nodeInfo.user.shortName, + //macaddr: decodedInfo.nodeInfo.user.macaddr, + hwModel: String(describing: decodedInfo.nodeInfo.user.hwModel) + .uppercased()), + + position: NodeInfoModel.Position( + latitudeI: decodedInfo.nodeInfo.position.latitudeI, + longitudeI: decodedInfo.nodeInfo.position.longitudeI, + altitude: decodedInfo.nodeInfo.position.altitude, + batteryLevel: decodedInfo.nodeInfo.position.batteryLevel, + time: decodedInfo.nodeInfo.position.time), + + lastHeard: decodedInfo.nodeInfo.lastHeard, + snr: decodedInfo.nodeInfo.snr) + ) + meshData.save() + } } // Handle assorted app packets if decodedInfo.packet.id != 0 { diff --git a/MeshtasticClient/Model/MyInfoModel.swift b/MeshtasticClient/Model/MyInfoModel.swift index f32de882..ba4d7631 100644 --- a/MeshtasticClient/Model/MyInfoModel.swift +++ b/MeshtasticClient/Model/MyInfoModel.swift @@ -1,15 +1,10 @@ -// -// MyInfoModel.swift -// MeshtasticClient -// -// Created by Garth Vander Houwen on 9/16/21. -// - import Foundation struct MyInfoModel: Identifiable, Codable { - let id: UInt32 + // Uses the BLE Peripheral identifier as the ID + // So myInfo can map between Peripherals and Nodes + var id: UUID var myNodeNum: UInt32 var hasGps: Bool var numBands: UInt32 @@ -18,9 +13,9 @@ struct MyInfoModel: Identifiable, Codable { var messageTimeoutMsec: UInt32 var minAppVersion: UInt32 - init(myNodeNum: UInt32, hasGps: Bool, numBands: UInt32, maxChannels: UInt32, firmwareVersion: String, messageTimeoutMsec: UInt32, minAppVersion: UInt32) { + init(id: UUID, myNodeNum: UInt32, hasGps: Bool, numBands: UInt32, maxChannels: UInt32, firmwareVersion: String, messageTimeoutMsec: UInt32, minAppVersion: UInt32) { - self.id = myNodeNum + self.id = id self.myNodeNum = myNodeNum self.hasGps = hasGps self.numBands = numBands diff --git a/MeshtasticClient/Model/PeripheralModel.swift b/MeshtasticClient/Model/PeripheralModel.swift index 5f04b3f5..64a90024 100644 --- a/MeshtasticClient/Model/PeripheralModel.swift +++ b/MeshtasticClient/Model/PeripheralModel.swift @@ -1,7 +1,7 @@ import Foundation import CoreBluetooth -final class Peripheral: Identifiable { +struct Peripheral: Identifiable { var id: String var name: String var rssi: Int diff --git a/MeshtasticClient/Views/Nodes/NodeList.swift b/MeshtasticClient/Views/Nodes/NodeList.swift index 2f5df8f8..ea803764 100644 --- a/MeshtasticClient/Views/Nodes/NodeList.swift +++ b/MeshtasticClient/Views/Nodes/NodeList.swift @@ -48,7 +48,7 @@ struct NodeList: View { if(bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.myInfo != nil) { - let connected: Bool = (bleManager.connectedPeripheral.myInfo!.id == node.id) + let connected: Bool = (bleManager.connectedPeripheral.myInfo!.myNodeNum == node.id) NodeRow(node: node, connected: connected) } else {