mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
BLE Cleanup
This commit is contained in:
parent
57d1cbc9eb
commit
3827ff816e
5 changed files with 79 additions and 76 deletions
|
|
@ -11,16 +11,16 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
@ObservedObject private var meshData : MeshData
|
||||
@ObservedObject private var messageData : MessageData
|
||||
|
||||
@Published private var centralManager: CBCentralManager!
|
||||
private var centralManager: CBCentralManager!
|
||||
|
||||
@Published var connectedPeripheral: Peripheral!
|
||||
@Published var connectedNode: NodeInfoModel!
|
||||
@Published var lastConnectedNode: String
|
||||
@Published var lastConnectionError: String
|
||||
|
||||
@Published var isSwitchedOn = false
|
||||
@Published var peripherals = [Peripheral]()
|
||||
@Published private var broadcastNodeId: UInt32 = 4294967295
|
||||
|
||||
private var broadcastNodeId: UInt32 = 4294967295
|
||||
|
||||
/* Meshtastic Service Details */
|
||||
var TORADIO_characteristic: CBCharacteristic!
|
||||
var FROMRADIO_characteristic: CBCharacteristic!
|
||||
|
|
@ -33,12 +33,13 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
/* init BLEManager */
|
||||
override init() {
|
||||
|
||||
self.meshData = MeshData()
|
||||
self.messageData = MessageData()
|
||||
self.lastConnectedNode = ""
|
||||
self.lastConnectionError = ""
|
||||
super.init()
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil)
|
||||
//let options = [CBCentralManagerOptionRestoreIdentifierKey: "com.meshtastic.ble-central"]
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil)//, options: options)
|
||||
centralManager.delegate = self
|
||||
meshData.load()
|
||||
messageData.load()
|
||||
|
|
@ -47,9 +48,11 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// called when bluetooth is enabled/disabled for the app
|
||||
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
||||
if central.state == .poweredOn {
|
||||
|
||||
isSwitchedOn = true
|
||||
}
|
||||
else {
|
||||
|
||||
isSwitchedOn = false
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +61,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
func startScanning() {
|
||||
|
||||
if isSwitchedOn {
|
||||
|
||||
peripherals.removeAll()
|
||||
centralManager.scanForPeripherals(withServices: [meshtasticServiceCBUUID], options: nil)
|
||||
print("Scanning Started")
|
||||
|
|
@ -69,11 +73,23 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
if centralManager.isScanning {
|
||||
|
||||
|
||||
self.centralManager.stopScan()
|
||||
print("Stopped Scanning")
|
||||
}
|
||||
}
|
||||
|
||||
// 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")")
|
||||
}
|
||||
|
||||
// Disconnect Device function
|
||||
func disconnectDevice(){
|
||||
|
||||
|
|
@ -81,38 +97,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
self.centralManager?.cancelPeripheralConnection(connectedPeripheral.peripheral)
|
||||
} else {
|
||||
|
||||
connectedNode = nil
|
||||
connectedPeripheral = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to a Device via UUID
|
||||
func connectToDevice(id: String) {
|
||||
|
||||
connectedPeripheral = peripherals.filter({ $0.peripheral.identifier.uuidString == id }).first
|
||||
|
||||
if connectedPeripheral != nil {
|
||||
|
||||
lastConnectedNode = connectedPeripheral.peripheral.identifier.uuidString
|
||||
self.centralManager?.connect(connectedPeripheral!.peripheral)
|
||||
print("Connected to: \(connectedPeripheral.peripheral.name ?? "Unknown")")
|
||||
}
|
||||
else {
|
||||
print("Connection failed connectedPeripheral is nil")
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to a specific peripheral
|
||||
func connectTo(peripheral: CBPeripheral) {
|
||||
|
||||
if connectedPeripheral.peripheral.state == CBPeripheralState.connected {
|
||||
self.disconnectDevice()
|
||||
}
|
||||
connectedPeripheral.peripheral = peripheral
|
||||
self.centralManager?.connect(connectedPeripheral!.peripheral)
|
||||
print("Connected to: \(connectedPeripheral.peripheral.name ?? "Unknown")")
|
||||
}
|
||||
|
||||
// Called each time a peripheral is discovered
|
||||
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
|
||||
|
||||
|
|
@ -134,9 +124,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
|
||||
peripheral.delegate = self
|
||||
connectedPeripheral = peripherals.filter({ $0.peripheral.identifier == peripheral.identifier }).first
|
||||
|
||||
peripheral.discoverServices([meshtasticServiceCBUUID])
|
||||
print("Peripheral connected: " + peripheral.name!)
|
||||
startScanning()
|
||||
}
|
||||
|
||||
// Send Broadcast Message
|
||||
|
|
@ -146,11 +137,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
// Return false if we are not properly connected to a device, handle retry logic in the view for now
|
||||
if connectedPeripheral == nil || connectedPeripheral!.peripheral.state != CBPeripheralState.connected || self.connectedNode == nil {
|
||||
|
||||
if connectedPeripheral != nil && self.connectedNode == nil {
|
||||
self.disconnectDevice()
|
||||
// Lets disconnect and then reconnect a second later when the message retry happens
|
||||
}
|
||||
|
||||
success = false
|
||||
}
|
||||
else if message.count < 1 {
|
||||
|
|
@ -191,7 +178,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Disconnect Peripheral Event
|
||||
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?)
|
||||
{
|
||||
// Start a Scan so the disconnected peripheral is moved to the peripherals[]
|
||||
// Start a Scan so the disconnected peripheral is moved to the peripherals[] if it is awake
|
||||
self.startScanning()
|
||||
|
||||
if let e = error {
|
||||
|
|
@ -199,35 +186,38 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
let errorCode = (e as NSError).code
|
||||
|
||||
if errorCode == 6 { // The connection has timed out unexpectedly.
|
||||
// Happens when device is manually reset / powered off
|
||||
connectedPeripheral = nil
|
||||
connectedNode = nil
|
||||
|
||||
// Happens when device is manually reset / powered off
|
||||
// 2 second delay for device to power back on
|
||||
let _ = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (timer) in
|
||||
|
||||
self.connectTo(peripheral: peripheral)
|
||||
}
|
||||
}
|
||||
else if errorCode == 7 { // The specified device has disconnected from us.
|
||||
|
||||
// Check if the peripheral is still visible and then reconnect
|
||||
// Seems to be what is received when a tbeam sleeps, immediately recconnecting does not work.
|
||||
// Check if the last connected peripheral is still visible and then reconnect
|
||||
connectedPeripheral = nil
|
||||
connectedNode = nil
|
||||
}
|
||||
else if errorCode == 14 { // Peer error that may require forgetting device in settings
|
||||
|
||||
// Forgetting and reconnecting seems to be necessary so we need to show the user an error telling them to do that
|
||||
lastConnectionError = (e as NSError).description
|
||||
// Check if the peripheral is still visible and then reconnect
|
||||
connectedPeripheral = nil
|
||||
connectedNode = nil
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Disconnected without error which indicates user intent to disconnect
|
||||
print("Central disconnected! (no error)")
|
||||
connectedPeripheral = nil
|
||||
connectedNode = nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
print("Peripheral disconnected: " + peripheral.name!)
|
||||
|
||||
}
|
||||
|
||||
// Discover Services Event
|
||||
|
|
@ -307,9 +297,9 @@ 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)
|
||||
//print(stringFromByteArray)
|
||||
let byteArrayFromData: [UInt8] = [UInt8](characteristic.value!)
|
||||
let stringFromByteArray = String(data: Data(_: byteArrayFromData), encoding: .ascii)
|
||||
print("string array data \(stringFromByteArray)")
|
||||
//print(characteristic.value?. ?? "no value")
|
||||
|
||||
|
||||
|
|
@ -347,9 +337,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
connectedNode = meshData.nodes.first(where: {$0.num == myInfoModel.id})
|
||||
|
||||
}
|
||||
// Since the data is from the device itself we save all myInfo objects since they are always the most update
|
||||
if connectedNode != nil && connectedNode.myInfo == nil {
|
||||
// Since the data is from the device itself we save all myInfo objects since they are always the most up to date
|
||||
if connectedNode != nil {
|
||||
connectedNode.myInfo = myInfoModel
|
||||
//connectedNode.update(from: connectedNode.data)
|
||||
let nodeIndex = meshData.nodes.firstIndex(where: { $0.id == decodedInfo.myInfo.myNodeNum })
|
||||
meshData.nodes.remove(at: nodeIndex!)
|
||||
meshData.nodes.append(connectedNode)
|
||||
|
|
@ -367,7 +358,11 @@ 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 nodeMatch?.lastHeard ?? 0 < decodedInfo.nodeInfo.lastHeard {
|
||||
if connectedPeripheral != nil && connectedPeripheral.myInfo?.id == nodeMatch?.num {
|
||||
connectedNode = nodeMatch
|
||||
}
|
||||
|
||||
if nodeMatch?.lastHeard ?? 0 < decodedInfo.nodeInfo.lastHeard && nodeMatch?.user != nil && nodeMatch?.user.longName.count ?? 0 > 0 {
|
||||
// The data coming from the device is newer
|
||||
|
||||
let nodeIndex = meshData.nodes.firstIndex(where: { $0.id == decodedInfo.nodeInfo.num })
|
||||
|
|
@ -380,7 +375,14 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Set the connected node if the nodeInfo is for the connected node.
|
||||
if connectedPeripheral != nil && connectedPeripheral.myInfo?.id == 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,
|
||||
|
|
@ -522,4 +524,5 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
peripheral.readValue(for: FROMRADIO_characteristic)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,3 +17,4 @@ final class Peripheral: Identifiable {
|
|||
self.myInfo = myInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,19 +51,19 @@ struct Connect: View {
|
|||
Text((bleManager.connectedPeripheral!.peripheral.name != nil) ? bleManager.connectedPeripheral!.peripheral.name! : "Unknown").font(.title2)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.swipeActions {
|
||||
Button {
|
||||
|
||||
Button(role: .destructive) {
|
||||
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected
|
||||
{
|
||||
|
||||
bleManager.disconnectDevice()
|
||||
bleManager.disconnectDevice()
|
||||
}
|
||||
} label: {
|
||||
Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash")
|
||||
Label("Delete", systemImage: "antenna.radiowaves.left.and.right.slash")
|
||||
}
|
||||
.tint(.red)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
else {
|
||||
HStack{
|
||||
|
|
@ -90,7 +90,7 @@ struct Connect: View {
|
|||
{
|
||||
self.bleManager.disconnectDevice()
|
||||
}
|
||||
self.bleManager.connectToDevice(id: peripheral.id)
|
||||
self.bleManager.connectTo(peripheral: peripheral.peripheral)
|
||||
}) {
|
||||
Text(peripheral.name).font(.title3)
|
||||
}
|
||||
|
|
@ -140,16 +140,14 @@ struct Connect: View {
|
|||
.navigationTitle("Bluetooth Radios")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
VStack(alignment: .trailing) {
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedNode != nil) ? bleManager.connectedNode.user.shortName : ((bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.name : "Unknown") )
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedNode != nil) ? bleManager.connectedNode.user.shortName : ((bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.name : "Unknown") )
|
||||
}
|
||||
)
|
||||
}.navigationViewStyle(StackNavigationViewStyle())
|
||||
.onAppear{
|
||||
bleManager.startScanning()
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
.onAppear(perform: { bleManager.startScanning() } )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ import SwiftUI
|
|||
import CoreBluetooth
|
||||
|
||||
struct Channels: View {
|
||||
// Message Data and Bluetooth
|
||||
@EnvironmentObject var messageData: MessageData
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
|
|
@ -31,6 +34,7 @@ struct Channels: View {
|
|||
}
|
||||
.navigationTitle("Channels")
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,18 +91,15 @@ struct Messages: View {
|
|||
typingMessage = ""
|
||||
}
|
||||
else {
|
||||
if bleManager.lastConnectedNode.count > 10 {
|
||||
if bleManager.peripherals.contains(where: { $0.id == bleManager.lastConnectedNode }) {
|
||||
bleManager.connectToDevice(id: bleManager.lastConnectedNode)
|
||||
let timer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { (timer) in
|
||||
|
||||
if bleManager.sendMessage(message: typingMessage) {
|
||||
typingMessage = ""
|
||||
}
|
||||
|
||||
if bleManager.connectedPeripheral != nil {
|
||||
let timer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { (timer) in
|
||||
|
||||
if bleManager.sendMessage(message: typingMessage) {
|
||||
typingMessage = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} ) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue