diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index b112b121..dd421685 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -43,7 +43,6 @@ DD6193752862F6E600E59241 /* ExternalNotificationConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6193742862F6E600E59241 /* ExternalNotificationConfig.swift */; }; DD6193772862F90F00E59241 /* CannedMessagesConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6193762862F90F00E59241 /* CannedMessagesConfig.swift */; }; DD6193792863875F00E59241 /* SerialConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6193782863875F00E59241 /* SerialConfig.swift */; }; - DD6B85A828009258000ACD6B /* ShareChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6B85A728009258000ACD6B /* ShareChannel.swift */; }; DD73FD1128750779000852D6 /* LocationHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD73FD1028750779000852D6 /* LocationHistory.swift */; }; DD8169F9271F1A6100F4AB02 /* MeshLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8169F8271F1A6100F4AB02 /* MeshLogger.swift */; }; DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */; }; @@ -157,7 +156,6 @@ DD6193742862F6E600E59241 /* ExternalNotificationConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalNotificationConfig.swift; sourceTree = ""; }; DD6193762862F90F00E59241 /* CannedMessagesConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CannedMessagesConfig.swift; sourceTree = ""; }; DD6193782863875F00E59241 /* SerialConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerialConfig.swift; sourceTree = ""; }; - DD6B85A728009258000ACD6B /* ShareChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareChannel.swift; sourceTree = ""; }; DD73FD1028750779000852D6 /* LocationHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationHistory.swift; sourceTree = ""; }; DD8169F8271F1A6100F4AB02 /* MeshLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshLogger.swift; sourceTree = ""; }; DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshLog.swift; sourceTree = ""; }; @@ -300,7 +298,6 @@ DD3501882852FC3B000FC853 /* Settings.swift */, DD4A911D2708C65400501B7E /* AppSettings.swift */, DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */, - DD6B85A728009258000ACD6B /* ShareChannel.swift */, DD86D40B287F401000BAEB7A /* SaveChannelQRCode.swift */, DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */, DD0F791A28713C8A00A6FDAD /* AdminMessageList.swift */, @@ -711,7 +708,6 @@ DD4C158C2824A91E0032668E /* module_config.pb.swift in Sources */, DDB6ABE828B141AF00384BA1 /* WiFiModes.swift in Sources */, DD4F23CD28779A3C001D37CB /* TelemetryLog.swift in Sources */, - DD6B85A828009258000ACD6B /* ShareChannel.swift in Sources */, DDB6ABD628AE742000384BA1 /* BluetoothConfig.swift in Sources */, DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */, DDC4D568275499A500A4208E /* Persistence.swift in Sources */, diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 5ced286b..53b9e334 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -29,7 +29,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph @Published var connectedPeripheral: Peripheral! @Published var lastConnectionError: String + @Published var minimumVersion = "1.3.41" @Published var connectedVersion: String + @Published var invalidVersion = false + @Published var preferredPeripheral = false @Published var isSwitchedOn: Bool = false @Published var isScanning: Bool = false @@ -41,6 +44,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph var timeoutTimer: Timer? var timeoutTimerCount = 0 + var configTimeoutTimer: Timer? + var positionTimer: Timer? let broadcastNodeNum: UInt32 = 4294967295 @@ -102,7 +107,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if isSwitchedOn { centralManager.scanForPeripherals(withServices: [meshtasticServiceCBUUID], options: nil) - self.isScanning = self.centralManager.isScanning + isScanning = centralManager.isScanning print("✅ Scanning Started") } @@ -114,7 +119,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if centralManager.isScanning { self.centralManager.stopScan() - self.isScanning = self.centralManager.isScanning + isScanning = centralManager.isScanning print("🛑 Stopped Scanning") } } @@ -155,6 +160,20 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if meshLoggingEnabled { MeshLogger.log("🚨 BLE Connecting 2 Second Timeout Timer Fired \(timeoutTimerCount) Time(s): \(name)") } } } + + // MARK: BLE Connect functions + /// The action after the timeout-timer has fired + /// + /// - Parameters: + /// - timer: The time that fired the event + /// + @objc func configTimeoutTimerFired(timer: Timer) { + + self.lastConnectionError = "🚨 Update your firmware" + self.connectedVersion = "1.2.65" + self.invalidVersion = true + self.timeoutTimer!.invalidate() + } // Connect to a specific peripheral func connectTo(peripheral: CBPeripheral) { @@ -170,7 +189,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph self.disconnectPeripheral() } - self.connectedVersion = "0.0.0" self.centralManager?.connect(peripheral) // Invalidate any existing timer @@ -192,6 +210,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph guard let connectedPeripheral = connectedPeripheral else { return } self.centralManager?.cancelPeripheralConnection(connectedPeripheral.peripheral) self.isConnected = false + self.invalidVersion = false + self.connectedVersion = "0.0.0" } // Called each time a peripheral is discovered @@ -416,10 +436,45 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph } } if (![FROMNUM_characteristic, FROMNUM_characteristic, TORADIO_characteristic].contains(nil)) { + sendWantConfig() + + self.configTimeoutTimer = Timer.scheduledTimer(timeInterval: TimeInterval(7), target: self, selector: #selector(configTimeoutTimerFired), userInfo: context, repeats: false) + RunLoop.current.add(self.configTimeoutTimer!, forMode: .common) } } + func requestDeviceMetadata() { + guard (connectedPeripheral!.peripheral.state == CBPeripheralState.connected) else { return } + + MeshLogger.log("â„šī¸ Requesting Device Metadata for \(connectedPeripheral!.peripheral.name ?? "Unknown")") + + var adminPacket = AdminMessage() + adminPacket.getDeviceMetadataRequest = 0 + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. UIImage { - var qrImage = UIImage(systemName: "xmark.circle") ?? UIImage() - let data = Data(text.utf8) - let filter = CIFilter.qrCodeGenerator() - filter.setValue(data, forKey: "inputMessage") - - let transform = CGAffineTransform(scaleX: 20, y: 20) - if let outputImage = filter.outputImage?.transformed(by: transform) { - if let image = context.createCGImage( - outputImage, - from: outputImage.extent) { - qrImage = UIImage(cgImage: image) - } - } - - return qrImage - } -} - -struct ShareChannel: View { - - @Environment(\.managedObjectContext) var context - @EnvironmentObject var bleManager: BLEManager - @EnvironmentObject var userSettings: UserSettings - - var node: NodeInfoEntity? - - @State private var text = "https://meshtastic.org/E/#test" - var qrCodeImage = QrCodeImage() - - var body: some View { - - VStack { - - GeometryReader { bounds in - - let smallest = min(bounds.size.width, bounds.size.height) - - ScrollView { - - VStack { - Text("Scan the QR code below with the Apple or Android device you would like to share your channel settings with.") - .fixedSize(horizontal: false, vertical: true) - .font(.callout) - - let image = qrCodeImage.generateQRCode(from: text) - Image(uiImage: image) - .resizable() - .scaledToFit() - .frame( - minWidth: smallest * 0.8, - maxWidth: smallest * 0.8, - minHeight: smallest * 0.8, - maxHeight: smallest * 0.8, - alignment: .center - ) - - if node != nil && node!.loRaConfig != nil { - - HStack { - - let preset = ModemPresets(rawValue: Int(node!.loRaConfig!.modemPreset)) - Text("Modem Preset \(preset!.description)").font(.title3) - } - } - VStack { - - Text("Number of Channels: \(node!.myInfo!.maxChannels)").font(.title2) - - ForEach(node!.myInfo!.channels?.array.sorted(by: { ($0 as! ChannelEntity).index < ($1 as! ChannelEntity).index }) as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in - - VStack { - - - Text("Channel: \(channel.index) Name: \(channel.name ?? "")") - } - } - } - } - .frame(width: bounds.size.width, height: bounds.size.height) - } - } - .navigationTitle("Share Channel") - .navigationBarTitleDisplayMode(.automatic) - .navigationBarItems(trailing: - - ZStack { - - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") - }) - .onAppear { - - self.bleManager.context = context - } - } - .navigationViewStyle(StackNavigationViewStyle()) - } -}