diff --git a/Localizable.xcstrings b/Localizable.xcstrings index ca923323..9a6c28c1 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -29004,18 +29004,18 @@ }, "Standard" : { "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Predefinito" - } - }, "he" : { "stringUnit" : { "state" : "translated", "value" : "סטנדרטי" } }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Predefinito" + } + }, "pl" : { "stringUnit" : { "state" : "translated", diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index b19ea46d..81f0ff70 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -59,8 +59,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate private var wantConfigTimer: Timer? private var wantConfigRetryCount = 0 - private let maxWantConfigRetries = 3 - private let wantConfigTimeoutInterval: TimeInterval = 6.0 + private let maxWantConfigRetries = 2 + private let wantConfigTimeoutInterval: TimeInterval = 5.0 // MARK: init private override init() { @@ -193,7 +193,12 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate if self.mqttProxyConnected { self.mqttManager.mqttClientProxy?.disconnect() } - self.wantConfigTimer?.invalidate() + self.isWaitingForWantConfigResponse = false + if wantConfigTimer != nil { + self.wantConfigTimer?.invalidate() + } + self.wantConfigTimer = nil + self.wantConfigRetryCount = 0 self.automaticallyReconnect = reconnect self.centralManager?.cancelPeripheralConnection(connectedPeripheral.peripheral) self.FROMRADIO_characteristic = nil @@ -506,22 +511,22 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate } return success } - + func sendWantConfig() { isWaitingForWantConfigResponse = true - + guard connectedPeripheral?.peripheral.state ?? CBPeripheralState.disconnected == CBPeripheralState.connected else { return } - + if FROMRADIO_characteristic == nil { Logger.mesh.error("🚨 \("Unsupported Firmware Version Detected, unable to connect to device.".localized, privacy: .public)") invalidVersion = true return } else { - + let nodeName = connectedPeripheral?.peripheral.name ?? "Unknown".localized let logString = String.localizedStringWithFormat("Issuing Want Config to %@".localized, nodeName) Logger.mesh.info("🛎️ \(logString, privacy: .public)") - + // BLE Characteristics discovered, issue wantConfig var toRadio: ToRadio = ToRadio() configNonce = UInt32(NONCE_ONLY_DB) @@ -533,11 +538,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate return } connectedPeripheral!.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse) - // Either Read the config complete value or from num notify value guard connectedPeripheral != nil else { return } connectedPeripheral!.peripheral.readValue(for: FROMRADIO_characteristic) - // Start timeout timer startWantConfigTimeout() } @@ -546,7 +549,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate private func startWantConfigTimeout() { // Cancel any existing timer wantConfigTimer?.invalidate() - // Start new timer wantConfigTimer = Timer.scheduledTimer(withTimeInterval: wantConfigTimeoutInterval, repeats: false) { [weak self] _ in self?.handleWantConfigTimeout() @@ -555,9 +557,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate private func handleWantConfigTimeout() { guard isWaitingForWantConfigResponse else { return } - wantConfigRetryCount += 1 - if wantConfigRetryCount < maxWantConfigRetries { Logger.mesh.warning("⏰ Want Config timeout, retrying... (attempt \(self.wantConfigRetryCount + 1)/\(self.maxWantConfigRetries))") sendWantConfig() @@ -577,15 +577,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate } private func forceDisconnect() { - isWaitingForWantConfigResponse = false - wantConfigTimer?.invalidate() - wantConfigTimer = nil - wantConfigRetryCount = 0 - disconnectPeripheral(reconnect: false) - - lastConnectionError = "Bluetooth connection timeout, keep your node closer.".localized - + lastConnectionError = "Bluetooth connection timeout, keep your node closer or reboot your radio if the problem continues.".localized Logger.mesh.error("💥 [BLE] Forced disconnect due to Want Config timeout") } diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index 4e114bb9..5e73270e 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -90,40 +90,7 @@ struct Connect: View { .foregroundColor(Color.gray) .padding([.top]) .swipeActions { - Button(role: .destructive) { - if let connectedPeripheral = bleManager.connectedPeripheral, - connectedPeripheral.peripheral.state == .connected { - bleManager.disconnectPeripheral(reconnect: false) - } - } label: { - Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") - } - } - .contextMenu { - - if node != nil { - #if !targetEnvironment(macCatalyst) - Button { - if !liveActivityStarted { - #if canImport(ActivityKit) - Logger.services.info("Start live activity.") - startNodeActivity() - #endif - } else { - #if canImport(ActivityKit) - Logger.services.info("Stop live activity.") - endActivity() - #endif - } - } label: { - Label("Mesh Live Activity", systemImage: liveActivityStarted ? "stop" : "play") - } - #endif - Text("Num: \(String(node!.num))") - Text("Short Name: \(node?.user?.shortName ?? "?")") - Text("Long Name: \(node?.user?.longName?.addingVariationSelectors ?? "Unknown".localized)") - Text("BLE RSSI: \(connectedPeripheral.rssi)") - + if bleManager.isSubscribed { Button(role: .destructive) { if let connectedPeripheral = bleManager.connectedPeripheral, connectedPeripheral.peripheral.state == .connected { @@ -132,13 +99,51 @@ struct Connect: View { } label: { Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") } - Button { - if !bleManager.sendShutdown(fromUser: node!.user!, toUser: node!.user!) { - Logger.mesh.error("Shutdown Failed") - } + } + } + .contextMenu { - } label: { - Label("Power Off", systemImage: "power") + if node != nil { + #if !targetEnvironment(macCatalyst) + if bleManager.isSubscribed { + Button { + if !liveActivityStarted { + #if canImport(ActivityKit) + Logger.services.info("Start live activity.") + startNodeActivity() + #endif + } else { + #if canImport(ActivityKit) + Logger.services.info("Stop live activity.") + endActivity() + #endif + } + } label: { + Label("Mesh Live Activity", systemImage: liveActivityStarted ? "stop" : "play") + } + } + #endif + Text("Num: \(String(node!.num))") + Text("Short Name: \(node?.user?.shortName ?? "?")") + Text("Long Name: \(node?.user?.longName?.addingVariationSelectors ?? "Unknown".localized)") + Text("BLE RSSI: \(connectedPeripheral.rssi)") + if bleManager.isSubscribed { + Button(role: .destructive) { + if let connectedPeripheral = bleManager.connectedPeripheral, + connectedPeripheral.peripheral.state == .connected { + bleManager.disconnectPeripheral(reconnect: false) + } + } label: { + Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") + } + Button { + if !bleManager.sendShutdown(fromUser: node!.user!, toUser: node!.user!) { + Logger.mesh.error("Shutdown Failed") + } + + } label: { + Label("Power Off", systemImage: "power") + } } } } @@ -154,7 +159,6 @@ struct Connect: View { } } } else { - if bleManager.isConnecting { HStack { Image(systemName: "antenna.radiowaves.left.and.right")