mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Start of connection timer UI
This commit is contained in:
parent
c3bd5a7300
commit
5790839022
5 changed files with 85 additions and 55 deletions
|
|
@ -36,6 +36,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
@Published var isSwitchedOn: Bool = false
|
||||
@Published var isScanning: Bool = false
|
||||
@Published var isConnecting: Bool = false
|
||||
@Published var isConnected: Bool = false
|
||||
|
||||
/// Used to make sure we never get foold by old BLE packets
|
||||
|
|
@ -44,7 +45,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
var timeoutTimer: Timer?
|
||||
var timeoutTimerCount = 0
|
||||
var positionTimer: Timer?
|
||||
|
||||
let broadcastNodeNum: UInt32 = 4294967295
|
||||
|
||||
/* Meshtastic Service Details */
|
||||
|
|
@ -133,6 +133,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
let name: String = timerContext["name", default: "Unknown"]
|
||||
|
||||
self.timeoutTimerCount += 1
|
||||
self.isConnecting = true
|
||||
self.lastConnectionError = ""
|
||||
|
||||
if timeoutTimerCount == 10 {
|
||||
|
||||
|
|
@ -141,17 +143,20 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
self.centralManager?.cancelPeripheralConnection(connectedPeripheral.peripheral)
|
||||
}
|
||||
connectedPeripheral = nil
|
||||
self.isConnected = false
|
||||
|
||||
self.lastConnectionError = "🚨 BLE Connection Timeout after making \(timeoutTimerCount) attempts to connect to \(name)."
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log(self.lastConnectionError + " This can occur when a device has been taken out of BLE range, or if a device is already connected to another phone, tablet or computer.") }
|
||||
|
||||
self.timeoutTimerCount = 0
|
||||
if self.timeoutTimer != nil {
|
||||
|
||||
self.timeoutTimer!.invalidate()
|
||||
}
|
||||
self.isConnected = false
|
||||
self.isConnecting = false
|
||||
|
||||
self.lastConnectionError = "🚨 BLE Connection Timeout after making \(timeoutTimerCount) attempts to connect to \(name). If you continue to get this message you may need to forget your device under settings > bluetooth."
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🚨 BLE Connection Timeout after making \(timeoutTimerCount) attempts to connect to \(name). If you continue to get this message you may need to forget your device under settings > bluetooth.") }
|
||||
|
||||
self.timeoutTimerCount = 0
|
||||
self.startScanning()
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -165,6 +170,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
if meshLoggingEnabled { MeshLogger.log("✅ BLE Connecting: \(peripheral.name ?? "Unknown")") }
|
||||
|
||||
stopScanning()
|
||||
self.isConnecting = true
|
||||
self.lastConnectionError = ""
|
||||
|
||||
|
||||
if self.connectedPeripheral != nil {
|
||||
|
|
@ -184,7 +191,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Use a timer to keep track of connecting peripherals, context to pass the radio name with the timer and the RunLoop to prevent
|
||||
// the timer from running on the main UI thread
|
||||
let context = ["name": "@\(peripheral.name ?? "Unknown")"]
|
||||
self.timeoutTimer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(timeoutTimerFired), userInfo: context, repeats: true)
|
||||
self.timeoutTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(timeoutTimerFired), userInfo: context, repeats: true)
|
||||
RunLoop.current.add(self.timeoutTimer!, forMode: .common)
|
||||
}
|
||||
|
||||
|
|
@ -235,6 +242,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Called when a peripheral is connected
|
||||
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
|
||||
self.isConnecting = false
|
||||
self.isConnected = true
|
||||
|
||||
if userSettings?.preferredPeripheralId.count ?? 0 < 1 {
|
||||
|
|
@ -287,6 +295,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Start a scan so the disconnected peripheral is moved to the peripherals[] if it is awake
|
||||
self.startScanning()
|
||||
self.connectedPeripheral = nil
|
||||
self.isConnecting = false
|
||||
|
||||
if let e = error {
|
||||
|
||||
|
|
@ -378,9 +387,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
for characteristic in characteristics {
|
||||
|
||||
switch characteristic.uuid {
|
||||
case EOL_FROMRADIO_UUID:
|
||||
if meshLoggingEnabled { MeshLogger.log("🚨 BLE did discover EOL_TORADIO characteristic for Meshtastic by \(peripheral.name ?? "Unknown")") }
|
||||
invalidVersion = true
|
||||
|
||||
case TORADIO_UUID:
|
||||
|
||||
|
|
@ -474,6 +480,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
guard (connectedPeripheral!.peripheral.state == CBPeripheralState.connected) else { return }
|
||||
|
||||
if FROMRADIO_characteristic == nil {
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🚨 Unsupported Firmware Version Detected, unable to connect to device.") }
|
||||
invalidVersion = true
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,12 @@ struct MeshtasticAppleApp: App {
|
|||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||
.environmentObject(bleManager)
|
||||
.environmentObject(userSettings)
|
||||
.sheet(isPresented: $saveChannels) {
|
||||
|
||||
SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL", validUrl: true)
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
|
||||
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
|
||||
|
||||
|
|
@ -41,12 +47,7 @@ struct MeshtasticAppleApp: App {
|
|||
print("User wants to open Channel Settings URL: \(String(describing: incomingUrl!.relativeString))")
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $saveChannels) {
|
||||
|
||||
SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL", validUrl: true)
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
|
||||
.onOpenURL(perform: { (url) in
|
||||
|
||||
print("Some sort of URL was received \(url)")
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ struct Connect: View {
|
|||
|
||||
Section(header: Text("Connection Error").font(.title)) {
|
||||
|
||||
Text(bleManager.lastConnectionError).font(.title3).foregroundColor(.red)
|
||||
Text(bleManager.lastConnectionError).font(.callout).foregroundColor(.red)
|
||||
}
|
||||
.textCase(nil)
|
||||
}
|
||||
|
||||
|
||||
Section(header: Text("Connected Radio").font(.title)) {
|
||||
|
||||
|
||||
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == .connected {
|
||||
|
||||
HStack {
|
||||
|
|
@ -65,10 +65,10 @@ struct Connect: View {
|
|||
.font(.caption).foregroundColor(Color.gray)
|
||||
}
|
||||
if bleManager.connectedPeripheral.subscribed {
|
||||
Text("Properly Subscribed").font(.caption)
|
||||
Text("Subscribed to mesh").font(.caption)
|
||||
.foregroundColor(.green)
|
||||
} else {
|
||||
Text("Attempting to connect. . . ").font(.caption)
|
||||
Text("Communicating with device. . . ").font(.caption)
|
||||
.foregroundColor(.orange)
|
||||
|
||||
}
|
||||
|
|
@ -135,20 +135,44 @@ struct Connect: View {
|
|||
}
|
||||
|
||||
} else {
|
||||
HStack {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right.slash")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.imageScale(.large).foregroundColor(.red)
|
||||
.padding(.trailing)
|
||||
Text("No device connected").font(.title3)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
if bleManager.isConnecting {
|
||||
HStack {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.imageScale(.large).foregroundColor(.orange)
|
||||
.padding(.trailing)
|
||||
if bleManager.timeoutTimerCount == 0 {
|
||||
Text("Connecting . . .")
|
||||
.font(.title3)
|
||||
.foregroundColor(.orange)
|
||||
} else {
|
||||
VStack {
|
||||
|
||||
Text("Connection Attempt \(bleManager.timeoutTimerCount) of 10")
|
||||
.font(.callout)
|
||||
.foregroundColor(.orange)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
|
||||
} else {
|
||||
|
||||
HStack {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right.slash")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.imageScale(.large).foregroundColor(.red)
|
||||
.padding(.trailing)
|
||||
Text("No device connected").font(.title3)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
.textCase(nil)
|
||||
|
||||
if bleManager.peripherals.count > 0 {
|
||||
if self.bleManager.isScanning {
|
||||
Section(header: Text("Available Radios").font(.title)) {
|
||||
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.rssi > $1.rssi })) { peripheral in
|
||||
HStack {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ struct Contacts: View {
|
|||
// Display Contacts for DM's on the Primary Channel
|
||||
// Display Contacts for the rest of the non admin channels
|
||||
|
||||
|
||||
List(users) { (user: UserEntity) in
|
||||
List {
|
||||
ForEach(users) { (user: UserEntity) in
|
||||
|
||||
let connectedNodeNum = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.num : 0
|
||||
|
||||
|
|
@ -131,6 +131,7 @@ struct Contacts: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Contacts")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarItems(leading:
|
||||
|
|
@ -140,9 +141,3 @@ struct Contacts: View {
|
|||
.listStyle(PlainListStyle())
|
||||
}
|
||||
}
|
||||
|
||||
struct Contacts_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Contacts()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ struct ShareChannels: View {
|
|||
.font(.caption)
|
||||
.fontWeight(.bold)
|
||||
.padding(.trailing)
|
||||
Text("Channel Name")
|
||||
Text("Channel")
|
||||
.font(.caption)
|
||||
.fontWeight(.bold)
|
||||
.padding(.trailing)
|
||||
|
|
@ -96,57 +96,59 @@ struct ShareChannels: View {
|
|||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 1)
|
||||
Text((channel.name!.isEmpty ? "primary" : channel.name) ?? "primary")
|
||||
Text((channel.name!.isEmpty ? "Primary" : channel.name) ?? "Primary")
|
||||
} else if channel.index == 1 {
|
||||
Toggle("Channel 1 Included", isOn: $includeChannel1)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 0)
|
||||
Text((channel.name!.isEmpty ? "channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)")
|
||||
Text((channel.name!.isEmpty ? "Channel\(channel.index)" : channel.name) ?? "Channel\(channel.index)")
|
||||
} else if channel.index == 2 {
|
||||
Toggle("Channel 2 Included", isOn: $includeChannel2)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 0)
|
||||
Text((channel.name!.isEmpty ? "channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)")
|
||||
Text((channel.name!.isEmpty ? "Channel\(channel.index)" : channel.name) ?? "Channel\(channel.index)")
|
||||
} else if channel.index == 3 {
|
||||
Toggle("Channel 3 Included", isOn: $includeChannel3)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 0)
|
||||
Text((channel.name!.isEmpty ? "channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)")
|
||||
Text((channel.name!.isEmpty ? "Channel\(channel.index)" : channel.name) ?? "Channel\(channel.index)")
|
||||
} else if channel.index == 4 {
|
||||
Toggle("Channel 4 Included", isOn: $includeChannel4)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 0)
|
||||
Text((channel.name!.isEmpty ? "channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)")
|
||||
Text((channel.name!.isEmpty ? "Channel\(channel.index)" : channel.name) ?? "Channel\(channel.index)")
|
||||
} else if channel.index == 5 {
|
||||
Toggle("Channel 5 Included", isOn: $includeChannel5)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 0)
|
||||
Text((channel.name!.isEmpty ? "channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)")
|
||||
Text((channel.name!.isEmpty ? "Channel\(channel.index)" : channel.name) ?? "Channel\(channel.index)")
|
||||
} else if channel.index == 6 {
|
||||
Toggle("Channel 6 Included", isOn: $includeChannel6)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 0)
|
||||
Text((channel.name!.isEmpty ? "channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)")
|
||||
Text((channel.name!.isEmpty ? "Channel\(channel.index)" : channel.name) ?? "Channel\(channel.index)")
|
||||
} else if channel.index == 7 {
|
||||
Toggle("Channel 7 Included", isOn: $includeChannel7)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
.disabled(channel.role == 0)
|
||||
Text((channel.name!.isEmpty ? "channel \(channel.index)" : channel.name) ?? "Channel \(channel.index)")
|
||||
Text((channel.name!.isEmpty ? "Channel\(channel.index)" : channel.name) ?? "Channel\(channel.index)")
|
||||
}
|
||||
if channel.role > 0 {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
} else {
|
||||
|
||||
if channel.role == 0 {
|
||||
Image(systemName: "lock.slash")
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
else if channel.role > 0 {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
|
@ -285,7 +287,7 @@ struct ShareChannels: View {
|
|||
|
||||
var channelSettings = ChannelSettings()
|
||||
channelSettings.name = ch.name!
|
||||
channelSettings.psk = ch.psk ?? Data()
|
||||
channelSettings.psk = ch.psk!
|
||||
channelSettings.id = UInt32(ch.id)
|
||||
channelSettings.uplinkEnabled = ch.uplinkEnabled
|
||||
channelSettings.downlinkEnabled = ch.downlinkEnabled
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue