mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
V 1.26.5 2 second Connection timeout for bluetooth, preferred peripheral enhancements
This commit is contained in:
parent
d447aa1ca7
commit
15608bb976
6 changed files with 103 additions and 33 deletions
|
|
@ -668,13 +668,13 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.26.4;
|
||||
MARKETING_VERSION = 1.26.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TARGETED_DEVICE_FAMILY = "1,2,6";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -695,13 +695,13 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.26.4;
|
||||
MARKETING_VERSION = 1.26.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TARGETED_DEVICE_FAMILY = "1,2,6";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
@Published var isSwitchedOn = false
|
||||
@Published var peripherals = [Peripheral]()
|
||||
|
||||
var isDisconnectedByUser = false
|
||||
var timeoutTimer: Timer?
|
||||
|
||||
private var meshLoggingEnabled: Bool = true
|
||||
|
||||
private var broadcastNodeId: UInt32 = 4294967295
|
||||
|
|
@ -78,7 +81,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
if isSwitchedOn {
|
||||
|
||||
peripherals.removeAll()
|
||||
centralManager.scanForPeripherals(withServices: [meshtasticServiceCBUUID], options: nil)
|
||||
print("Scanning Started")
|
||||
}
|
||||
|
|
@ -93,15 +95,35 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
print("Stopped Scanning")
|
||||
}
|
||||
}
|
||||
|
||||
/// The action after the timeout-timer has fired
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - timer: The time that fired the event
|
||||
///
|
||||
@objc func timeoutTimerFired(timer: Timer)
|
||||
{
|
||||
timer.invalidate()
|
||||
lastConnectionError = "BLE Connection timed out" //radio \(connectedPeripheral.peripheral.name ?? "Unknown")
|
||||
if connectedPeripheral != nil {
|
||||
self.centralManager?.cancelPeripheralConnection(connectedPeripheral.peripheral)
|
||||
connectedNode = nil
|
||||
connectedPeripheral = nil
|
||||
}
|
||||
print("BLE-Timeout-Timer fired!")
|
||||
Logger.log("BLE-Timeout-Timer fired!")
|
||||
self.startScanning()
|
||||
}
|
||||
|
||||
// Connect to a specific peripheral
|
||||
func connectTo(peripheral: CBPeripheral) {
|
||||
|
||||
stopScanning()
|
||||
if connectedPeripheral != nil && connectedPeripheral.peripheral.state == CBPeripheralState.connected {
|
||||
if self.connectedPeripheral != nil && self.connectedPeripheral.peripheral.state == CBPeripheralState.connected {
|
||||
self.disconnectDevice()
|
||||
}
|
||||
|
||||
self.timeoutTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(timeoutTimerFired), userInfo: nil, repeats: false)
|
||||
self.centralManager?.connect(peripheral)
|
||||
if meshLoggingEnabled { Logger.log("BLE Connecting: \(peripheral.name ?? "Unknown")") }
|
||||
print("BLE Connecting: \(peripheral.name ?? "Unknown")")
|
||||
|
|
@ -125,26 +147,38 @@ 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)
|
||||
print("Adding peripheral: \(peripheralName)");
|
||||
let peripheralIndex = peripherals.firstIndex(where: { $0.id == newPeripheral.id })
|
||||
|
||||
if peripheralIndex != nil {
|
||||
peripherals.remove(at: peripheralIndex!)
|
||||
peripherals.append(newPeripheral)
|
||||
print("Updating peripheral: \(peripheralName)");
|
||||
}
|
||||
else {
|
||||
|
||||
peripherals.append(newPeripheral)
|
||||
print("Adding peripheral: \(peripheralName)");
|
||||
}
|
||||
}
|
||||
|
||||
// called when a peripheral is connected
|
||||
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
|
||||
stopScanning()
|
||||
lastConnectionError = ""
|
||||
timeoutTimer!.invalidate()
|
||||
|
||||
peripheral.delegate = self
|
||||
connectedPeripheral = peripherals.filter({ $0.peripheral.identifier == peripheral.identifier }).first
|
||||
let deviceName = peripheral.name ?? ""
|
||||
|
||||
let peripheralLast4: String = String(deviceName.suffix(4))
|
||||
print(peripheralLast4)
|
||||
|
||||
connectedNode = meshData.nodes.first(where: { $0.user.id.contains(peripheralLast4) })
|
||||
lastConnectedPeripheral = peripheral.identifier.uuidString
|
||||
peripheral.discoverServices([meshtasticServiceCBUUID])
|
||||
if meshLoggingEnabled { Logger.log("BLE Connected: \(peripheral.name ?? "Unknown")") }
|
||||
print("BLE Connected: \(peripheral.name ?? "Unknown")")
|
||||
stopScanning()
|
||||
peripherals.removeAll()
|
||||
}
|
||||
|
||||
|
|
@ -158,16 +192,20 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
let errorCode = (e as NSError).code
|
||||
|
||||
if errorCode == 6 { // The connection has timed out unexpectedly.
|
||||
if errorCode == 6 {
|
||||
|
||||
// Error Code 6: The connection has timed out unexpectedly.
|
||||
// Happens when device is manually reset / powered off
|
||||
lastConnectionError = " \(e.localizedDescription) Will automatically attempt to reconnect to the preferred radio if it reappears quickly."
|
||||
self.connectedNode = nil
|
||||
self.connectedPeripheral = nil
|
||||
self.connectTo(peripheral: peripheral)
|
||||
|
||||
// Happens when device is manually reset / powered off
|
||||
// 2 second delay for device to power back on
|
||||
let _ = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { (timer) in
|
||||
//let _ = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { (timer) in
|
||||
|
||||
//self.connectedPeripheral = nil
|
||||
self.connectedNode = nil
|
||||
self.connectTo(peripheral: peripheral)
|
||||
}
|
||||
|
||||
// }
|
||||
}
|
||||
else if errorCode == 7 { // The specified device has disconnected from us.
|
||||
|
||||
|
|
@ -175,6 +213,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Check if the last connected peripheral is still visible and then reconnect
|
||||
connectedPeripheral = nil
|
||||
connectedNode = nil
|
||||
lastConnectionError = e.localizedDescription
|
||||
|
||||
}
|
||||
else if errorCode == 14 { // Peer error that may require forgetting device in settings
|
||||
|
|
@ -182,7 +221,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Forgetting and reconnecting seems to be necessary so we need to show the user an error telling them to do that
|
||||
connectedPeripheral = nil
|
||||
connectedNode = nil
|
||||
lastConnectionError = (e as NSError).description
|
||||
lastConnectionError = e.localizedDescription
|
||||
}
|
||||
print("Central disconnected because \(e)")
|
||||
if meshLoggingEnabled { Logger.log("BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(e.localizedDescription)") }
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ struct MeshtasticClientApp: App {
|
|||
@ObservedObject private var meshData: MeshData = MeshData()
|
||||
@ObservedObject private var messageData: MessageData = MessageData()
|
||||
@ObservedObject private var bleManager: BLEManager = BLEManager()
|
||||
@ObservedObject private var userSettings: UserSettings = UserSettings()
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
|
|
@ -20,6 +21,7 @@ struct MeshtasticClientApp: App {
|
|||
.environmentObject(meshData)
|
||||
.environmentObject(messageData)
|
||||
.environmentObject(bleManager)
|
||||
.environmentObject(userSettings)
|
||||
.onAppear{
|
||||
meshData.load()
|
||||
messageData.load()
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@ import CoreBluetooth
|
|||
struct Connect: View {
|
||||
|
||||
@EnvironmentObject var meshData: MeshData
|
||||
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
@ObservedObject var userSettings = UserSettings()
|
||||
|
||||
@EnvironmentObject var userSettings: UserSettings
|
||||
|
||||
@State var isPreferredRadio: Bool = false
|
||||
|
||||
|
||||
|
|
@ -30,7 +31,17 @@ struct Connect: View {
|
|||
if bleManager.isSwitchedOn {
|
||||
|
||||
List {
|
||||
if bleManager.lastConnectionError.count > 0 {
|
||||
|
||||
Section(header: Text("Connection Error").font(.title)) {
|
||||
|
||||
Text(bleManager.lastConnectionError).font(.title2).foregroundColor(.red)
|
||||
}
|
||||
.textCase(nil)
|
||||
}
|
||||
|
||||
Section(header: Text("Connected Device").font(.title)) {
|
||||
|
||||
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == .connected {
|
||||
HStack {
|
||||
|
||||
|
|
@ -64,19 +75,20 @@ struct Connect: View {
|
|||
.labelsHidden()
|
||||
.onChange(of: isPreferredRadio) { value in
|
||||
if value {
|
||||
|
||||
if bleManager.connectedNode != nil {
|
||||
let deviceName = "\(bleManager.connectedNode.user.longName) / \(bleManager.connectedPeripheral.peripheral.name ?? "")"
|
||||
UserDefaults.standard.set(deviceName, forKey: "preferredPeripheralName")
|
||||
//userSettings.preferredPeripheralName = "\(bleManager.connectedNode.user.longName) / \(bleManager.connectedPeripheral.peripheral.name ?? "")"
|
||||
|
||||
userSettings.preferredPeripheralName = deviceName
|
||||
} else {
|
||||
UserDefaults.standard.set(bleManager.connectedPeripheral.peripheral.name ?? "Unknown Device", forKey: "preferredPeripheralName")
|
||||
//userSettings.preferredPeripheralName =
|
||||
userSettings.preferredPeripheralName = bleManager.connectedPeripheral.peripheral.name ?? "Unknown Device"
|
||||
}
|
||||
UserDefaults.standard.set(bleManager.connectedPeripheral!.peripheral.identifier.uuidString, forKey: "preferredPeripheralId")
|
||||
|
||||
userSettings.preferredPeripheralId = bleManager.connectedPeripheral!.peripheral.identifier.uuidString
|
||||
|
||||
} else {
|
||||
UserDefaults.standard.set("", forKey: "preferredPeripheralId")
|
||||
UserDefaults.standard.set("", forKey: "preferredPeripheralName")
|
||||
userSettings.preferredPeripheralId = ""
|
||||
userSettings.preferredPeripheralName = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -107,7 +119,8 @@ struct Connect: View {
|
|||
.padding()
|
||||
}
|
||||
|
||||
}.textCase(nil)
|
||||
}
|
||||
.textCase(nil)
|
||||
|
||||
Section(header: Text("Available Devices").font(.title)) {
|
||||
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.rssi > $1.rssi })) { peripheral in
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import SwiftUI
|
|||
struct NodeList: View {
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
@EnvironmentObject var meshData: MeshData
|
||||
|
||||
@State private var selection: String? = nil
|
||||
|
||||
@State private var showLocationOnly = false
|
||||
|
||||
|
|
@ -47,7 +49,11 @@ struct NodeList: View {
|
|||
Text("Nodes with location only")
|
||||
}
|
||||
ForEach(filteredDevices.sorted(by: { $0.lastHeard > $1.lastHeard })) { node in
|
||||
NavigationLink(destination: NodeDetail(node: node)) {
|
||||
|
||||
|
||||
let index = filteredDevices.sorted(by: { $0.lastHeard > $1.lastHeard }).firstIndex(where: { $0.id == node.id })
|
||||
|
||||
NavigationLink(destination: NodeDetail(node: node), tag: String(index!), selection: $selection) {
|
||||
|
||||
if(bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.myInfo != nil) {
|
||||
|
||||
|
|
@ -75,6 +81,15 @@ struct NodeList: View {
|
|||
}
|
||||
}
|
||||
.navigationTitle("All Nodes")
|
||||
.onAppear(
|
||||
perform: {
|
||||
if UIDevice.current.userInterfaceIdiom == .pad {
|
||||
if meshData.nodes.count > 0 {
|
||||
selection = "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
.ignoresSafeArea(.all, edges: [.leading, .trailing])
|
||||
.navigationViewStyle(DoubleColumnNavigationViewStyle())
|
||||
|
|
|
|||
|
|
@ -74,9 +74,10 @@ class UserSettings: ObservableObject {
|
|||
|
||||
struct AppSettings: View {
|
||||
|
||||
@State private var preferredDeviceConnected = false
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
@ObservedObject var userSettings = UserSettings()
|
||||
@EnvironmentObject var userSettings: UserSettings
|
||||
|
||||
@State private var preferredDeviceConnected = false
|
||||
|
||||
var perferredPeripheral: String {
|
||||
UserDefaults.standard.object(forKey: "preferredPeripheralName") as? String ?? ""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue