From 9e84d53a82157d22c35b6f66cc070312ea918c26 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 18 Oct 2022 19:50:42 -0700 Subject: [PATCH 1/4] Hook together SaveChannelQRCode View --- Meshtastic/Helpers/BLEManager.swift | 37 ++++++++++++++++ Meshtastic/MeshtasticApp.swift | 4 +- .../Views/Settings/Config/DeviceConfig.swift | 17 +++----- .../Views/Settings/SaveChannelQRCode.swift | 43 ++++++++----------- 4 files changed, 61 insertions(+), 40 deletions(-) diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 6f03dbe1..a70c8ac8 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -1057,6 +1057,43 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph return false } + public func connectToPreferredPeripheral() -> Bool { + + var success = false + // 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.disconnectPeripheral() + self.startScanning() + + // Try and connect to the preferredPeripherial first + let preferredPeripheral = peripherals.filter({ $0.peripheral.identifier.uuidString == UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? "" }).first + if preferredPeripheral != nil && preferredPeripheral?.peripheral != nil { + connectTo(peripheral: preferredPeripheral!.peripheral) + success = true + } + } else if connectedPeripheral != nil && isSubscribed { + success = true + } + return success + } + + public func saveChannelSet(base64String: String) -> Bool { + + if isConnected { + var decodedString = base64String.base64urlToBase64() + if let decodedData = Data(base64Encoded: decodedString) { + do { + var channelSet: ChannelSet = try ChannelSet(serializedData: decodedData) + print(channelSet) + } catch { + print("Invalid Meshtastic QR Code Link") + } + } + } + return false + } + public func saveUser(config: User, fromUser: UserEntity, toUser: UserEntity) -> Int64 { var adminPacket = AdminMessage() diff --git a/Meshtastic/MeshtasticApp.swift b/Meshtastic/MeshtasticApp.swift index a15663e4..46ea6c3a 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -24,12 +24,10 @@ struct MeshtasticAppleApp: App { .environmentObject(bleManager) .environmentObject(userSettings) .sheet(isPresented: $saveChannels) { - - SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL") + SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL", bleManager: bleManager) .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) } - .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in print("URL received \(userActivity)") diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index 241f828c..841d6b4b 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -16,7 +16,6 @@ struct DeviceConfig: View { @State private var isPresentingNodeDBResetConfirm = false @State private var isPresentingFactoryResetConfirm = false @State private var isPresentingSaveConfirm = false - @State var initialLoad: Bool = true @State var hasChanges = false @State var deviceRole = 0 @@ -166,17 +165,11 @@ struct DeviceConfig: View { ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { - - if self.initialLoad{ - - self.bleManager.context = context - - self.deviceRole = Int(node?.deviceConfig?.role ?? 0) - self.serialEnabled = (node?.deviceConfig?.serialEnabled ?? true) - self.debugLogEnabled = node?.deviceConfig?.debugLogEnabled ?? false - self.hasChanges = false - self.initialLoad = false - } + self.bleManager.context = context + self.deviceRole = Int(node?.deviceConfig?.role ?? 0) + self.serialEnabled = (node?.deviceConfig?.serialEnabled ?? true) + self.debugLogEnabled = node?.deviceConfig?.debugLogEnabled ?? false + self.hasChanges = false } .onChange(of: deviceRole) { newRole in diff --git a/Meshtastic/Views/Settings/SaveChannelQRCode.swift b/Meshtastic/Views/Settings/SaveChannelQRCode.swift index 8d5e3f5c..29c77a19 100644 --- a/Meshtastic/Views/Settings/SaveChannelQRCode.swift +++ b/Meshtastic/Views/Settings/SaveChannelQRCode.swift @@ -8,7 +8,9 @@ import SwiftUI struct SaveChannelQRCode: View { var channelHash: String - + var bleManager: BLEManager + @State var connectedToDevice = false + var body: some View { VStack { Text("Save Channel Settings?") @@ -17,32 +19,23 @@ struct SaveChannelQRCode: View { .foregroundColor(.gray) .font(.callout) .padding() - Text(channelHash) - .font(.caption2) - .foregroundColor(.gray) - .padding() - Button { - - } label: { - - Label("Save", systemImage: "square.and.arrow.down") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding() - } - .onChange(of: channelHash) { newSettings in - var decodedString = newSettings.base64urlToBase64() - if let decodedData = Data(base64Encoded: decodedString) { - do { - var channelSet: ChannelSet = try ChannelSet(serializedData: decodedData) - print(channelSet) - } catch { - print("Invalid Meshtastic QR Code Link") + + Button { + let success = bleManager.saveChannelSet(base64String: channelHash) + + } label: { + Label("Save", systemImage: "square.and.arrow.down") } - } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding() + .disabled(!connectedToDevice) + + } + .onAppear { + connectedToDevice = bleManager.connectToPreferredPeripheral() } } } From 09847f34561659a6d9114b5da9667b48664c0916 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 18 Oct 2022 20:25:11 -0700 Subject: [PATCH 2/4] Trim down peripheral now that we have the connected node on the bluetooth view --- Meshtastic/Helpers/BLEManager.swift | 16 +++------------- Meshtastic/MeshtasticApp.swift | 2 +- Meshtastic/Model/PeripheralModel.swift | 10 +--------- Meshtastic/Views/Bluetooth/Connect.swift | 9 +++------ .../Views/Settings/SaveChannelQRCode.swift | 4 ++-- 5 files changed, 10 insertions(+), 31 deletions(-) diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index a70c8ac8..0fb69f5a 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -195,13 +195,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) { var peripheralName: String = peripheral.name ?? "Unknown" - let last4Code: String = (peripheral.name != nil ? String(peripheral.name!.suffix(4)) : "Unknown") if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String { peripheralName = name } - let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: last4Code, longName: peripheralName, lastFourCode: last4Code, firmwareVersion: "Unknown", rssi: RSSI.intValue, bitrate: nil, channelUtilization: nil, airTime: nil, lastUpdate: Date(), peripheral: peripheral) + let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: "????", longName: peripheralName, firmwareVersion: "Unknown", rssi: RSSI.intValue, lastUpdate: Date(), peripheral: peripheral) let peripheralIndex = peripherals.firstIndex(where: { $0.id == newPeripheral.id }) if peripheralIndex != nil && newPeripheral.peripheral.state != CBPeripheralState.connected { @@ -517,10 +516,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph self.userSettings?.preferredNodeNum = myInfo?.myNodeNum ?? 0 if myInfo != nil { - - self.connectedPeripheral.bitrate = myInfo!.bitrate self.connectedPeripheral.num = myInfo!.myNodeNum - self.connectedPeripheral.firmwareVersion = myInfo!.firmwareVersion ?? "Unknown" self.connectedPeripheral.name = myInfo!.bleName ?? "Unknown" self.connectedPeripheral.longName = myInfo!.bleName ?? "Unknown" @@ -534,14 +530,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph let nodeInfo = nodeInfoPacket(nodeInfo: decodedInfo.nodeInfo, context: context!) if nodeInfo != nil { - - self.connectedPeripheral.channelUtilization = decodedInfo.nodeInfo.deviceMetrics.channelUtilization - self.connectedPeripheral.airTime = decodedInfo.nodeInfo.deviceMetrics.airUtilTx - if self.connectedPeripheral != nil && self.connectedPeripheral.num == nodeInfo!.num { - if nodeInfo!.user != nil { - connectedPeripheral.shortName = nodeInfo!.user!.shortName ?? "????" connectedPeripheral.longName = nodeInfo!.user!.longName ?? "Unknown" } @@ -1078,10 +1068,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph return success } - public func saveChannelSet(base64String: String) -> Bool { + public func saveChannelSet(base64UrlString: String) -> Bool { if isConnected { - var decodedString = base64String.base64urlToBase64() + var decodedString = base64UrlString.base64urlToBase64() if let decodedData = Data(base64Encoded: decodedString) { do { var channelSet: ChannelSet = try ChannelSet(serializedData: decodedData) diff --git a/Meshtastic/MeshtasticApp.swift b/Meshtastic/MeshtasticApp.swift index 46ea6c3a..0eae4e88 100644 --- a/Meshtastic/MeshtasticApp.swift +++ b/Meshtastic/MeshtasticApp.swift @@ -24,7 +24,7 @@ struct MeshtasticAppleApp: App { .environmentObject(bleManager) .environmentObject(userSettings) .sheet(isPresented: $saveChannels) { - SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL", bleManager: bleManager) + SaveChannelQRCode(channelSetLink: channelSettings ?? "Empty Channel URL", bleManager: bleManager) .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) } diff --git a/Meshtastic/Model/PeripheralModel.swift b/Meshtastic/Model/PeripheralModel.swift index 4b4cb3db..758dc8e8 100644 --- a/Meshtastic/Model/PeripheralModel.swift +++ b/Meshtastic/Model/PeripheralModel.swift @@ -7,27 +7,19 @@ struct Peripheral: Identifiable { var name: String var shortName: String var longName: String - var lastFourCode: String var firmwareVersion: String var rssi: Int - var bitrate: Float? - var channelUtilization: Float? - var airTime: Float? var lastUpdate: Date var peripheral: CBPeripheral - init(id: String, num: Int64, name: String, shortName: String, longName: String, lastFourCode: String, firmwareVersion: String, rssi: Int, bitrate: Float?, channelUtilization: Float?, airTime: Float?, lastUpdate: Date, peripheral: CBPeripheral) { + init(id: String, num: Int64, name: String, shortName: String, longName: String, firmwareVersion: String, rssi: Int, lastUpdate: Date, peripheral: CBPeripheral) { self.id = id self.num = num self.name = name self.shortName = shortName self.longName = longName - self.lastFourCode = lastFourCode self.firmwareVersion = firmwareVersion self.rssi = rssi - self.bitrate = bitrate - self.channelUtilization = channelUtilization - self.airTime = airTime self.lastUpdate = lastUpdate self.peripheral = peripheral } diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index 964a6918..37acf87d 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -101,13 +101,10 @@ struct Connect: View { if node != nil { Text("Num: \(String(node!.num))") - Text("Short Name: \(bleManager.connectedPeripheral.shortName)") - Text("Long Name: \(bleManager.connectedPeripheral.longName)") - Text("Unique Code: \(bleManager.connectedPeripheral.lastFourCode)") + Text("Short Name: \(node?.user?.shortName ?? "????")") + Text("Long Name: \(node?.user?.longName ?? "Unknown")") Text("Max Channels: \(String(node!.myInfo!.maxChannels))") - Text("Bitrate: \(String(format: "%.2f", bleManager.connectedPeripheral.bitrate ?? 0.00))") - Text("Ch. Utilization: \(String(format: "%.2f", bleManager.connectedPeripheral.channelUtilization ?? 0.00))") - Text("Air Time: \(String(format: "%.2f", bleManager.connectedPeripheral.airTime ?? 0.00))") + Text("Bitrate: \(String(format: "%.2f", node?.myInfo?.bitrate ?? 0.00))") Text("BLE RSSI: \(bleManager.connectedPeripheral.rssi)") } diff --git a/Meshtastic/Views/Settings/SaveChannelQRCode.swift b/Meshtastic/Views/Settings/SaveChannelQRCode.swift index 29c77a19..85a47be3 100644 --- a/Meshtastic/Views/Settings/SaveChannelQRCode.swift +++ b/Meshtastic/Views/Settings/SaveChannelQRCode.swift @@ -7,7 +7,7 @@ import SwiftUI struct SaveChannelQRCode: View { - var channelHash: String + var channelSetLink: String var bleManager: BLEManager @State var connectedToDevice = false @@ -22,7 +22,7 @@ struct SaveChannelQRCode: View { Button { - let success = bleManager.saveChannelSet(base64String: channelHash) + let success = bleManager.saveChannelSet(base64UrlString: channelSetLink) } label: { Label("Save", systemImage: "square.and.arrow.down") From 08db942dc6be293fbe0b8fc27e652da5f06bc0ec Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 19 Oct 2022 07:33:46 -0700 Subject: [PATCH 3/4] Update protos --- Meshtastic/Helpers/BLEManager.swift | 10 +--------- Meshtastic/Protobufs/deviceonly.pb.swift | 10 ++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 0fb69f5a..e1240147 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -324,14 +324,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let e = error { - MeshLogger.log("🚫 BLE didDiscoverCharacteristicsFor error by \(peripheral.name ?? "Unknown") \(e)") } - + guard let characteristics = service.characteristics else { return } for characteristic in characteristics { - switch characteristic.uuid { case TORADIO_UUID: @@ -339,13 +337,11 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph TORADIO_characteristic = characteristic case FROMRADIO_UUID: - MeshLogger.log("✅ BLE did discover FROMRADIO characteristic for Meshtastic by \(peripheral.name ?? "Unknown")") FROMRADIO_characteristic = characteristic peripheral.readValue(for: FROMRADIO_characteristic) case FROMNUM_UUID: - MeshLogger.log("✅ BLE did discover FROMNUM (Notify) characteristic for Meshtastic by \(peripheral.name ?? "Unknown")") FROMNUM_characteristic = characteristic peripheral.setNotifyValue(true, for: characteristic) @@ -367,7 +363,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph DFURESULT_characteristic = characteristic case DFUREGION_UUID: - MeshLogger.log("✅ BLE did discover DFU Region characteristic for Meshtastic DFU by \(peripheral.name ?? "Unknown")") DFUREGION_characteristic = characteristic @@ -376,7 +371,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph } } if (![FROMNUM_characteristic, TORADIO_characteristic].contains(nil)) { - sendWantConfig() } } @@ -394,7 +388,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph meshPacket.priority = MeshPacket.Priority.reliable meshPacket.wantAck = true - var dataMessage = DataMessage() dataMessage.payload = try! adminPacket.serializedData() dataMessage.portnum = PortNum.adminApp @@ -937,7 +930,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph context!.rollback() let nsError = error as NSError MeshLogger.log("💥 Error Inserting New Core Data MessageEntity: \(nsError)") - print() } } return false diff --git a/Meshtastic/Protobufs/deviceonly.pb.swift b/Meshtastic/Protobufs/deviceonly.pb.swift index 6c263ad2..7e5e0d33 100644 --- a/Meshtastic/Protobufs/deviceonly.pb.swift +++ b/Meshtastic/Protobufs/deviceonly.pb.swift @@ -216,6 +216,10 @@ struct OEMStore { /// Use this font for the OEM text. var oemText: String = String() + /// + /// The default device encryption key, 16 or 32 byte + var oemAesKey: Data = Data() + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} @@ -408,6 +412,7 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB 3: .standard(proto: "oem_icon_bits"), 4: .standard(proto: "oem_font"), 5: .standard(proto: "oem_text"), + 6: .standard(proto: "oem_aes_key"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -421,6 +426,7 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB case 3: try { try decoder.decodeSingularBytesField(value: &self.oemIconBits) }() case 4: try { try decoder.decodeSingularEnumField(value: &self.oemFont) }() case 5: try { try decoder.decodeSingularStringField(value: &self.oemText) }() + case 6: try { try decoder.decodeSingularBytesField(value: &self.oemAesKey) }() default: break } } @@ -442,6 +448,9 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB if !self.oemText.isEmpty { try visitor.visitSingularStringField(value: self.oemText, fieldNumber: 5) } + if !self.oemAesKey.isEmpty { + try visitor.visitSingularBytesField(value: self.oemAesKey, fieldNumber: 6) + } try unknownFields.traverse(visitor: &visitor) } @@ -451,6 +460,7 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB if lhs.oemIconBits != rhs.oemIconBits {return false} if lhs.oemFont != rhs.oemFont {return false} if lhs.oemText != rhs.oemText {return false} + if lhs.oemAesKey != rhs.oemAesKey {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } From 78eee04a1fdb051acc3f5bf9f24ac3ddd2314412 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 19 Oct 2022 14:11:36 -0700 Subject: [PATCH 4/4] Save serial on nerf --- Meshtastic/Helpers/BLEManager.swift | 3 ++ .../Settings/Config/Module/SerialConfig.swift | 30 +++++++------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index e1240147..299a394e 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -1067,6 +1067,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if let decodedData = Data(base64Encoded: decodedString) { do { var channelSet: ChannelSet = try ChannelSet(serializedData: decodedData) + + + print(channelSet) } catch { print("Invalid Meshtastic QR Code Link") diff --git a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift index fd4e5d8e..3c21b899 100644 --- a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift @@ -14,7 +14,6 @@ struct SerialConfig: View { var node: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false - @State var initialLoad: Bool = true @State var hasChanges = false @State var enabled = false @@ -115,7 +114,7 @@ struct SerialConfig: View { Label("Save", systemImage: "square.and.arrow.down") } - .disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node!.myInfo?.hasWifi ?? false)) + .disabled(bleManager.connectedPeripheral == nil || !hasChanges) .buttonStyle(.bordered) .buttonBorderShape(.capsule) .controlSize(.large) @@ -140,7 +139,6 @@ struct SerialConfig: View { let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: node!.user!, toUser: node!.user!) if adminMessageId > 0 { - // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save hasChanges = false @@ -155,26 +153,20 @@ struct SerialConfig: View { .navigationBarItems(trailing: ZStack { - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { + + self.bleManager.context = context + self.enabled = node?.serialConfig?.enabled ?? false + self.echo = node?.serialConfig?.echo ?? false + self.rxd = Int(node?.serialConfig?.rxd ?? 0) + self.txd = Int(node?.serialConfig?.txd ?? 0) + self.baudRate = Int(node?.serialConfig?.baudRate ?? 0) + self.timeout = Int(node?.serialConfig?.timeout ?? 0) + self.mode = Int(node?.serialConfig?.mode ?? 0) + self.hasChanges = false - if self.initialLoad{ - - self.bleManager.context = context - - self.enabled = node?.serialConfig?.enabled ?? false - self.echo = node?.serialConfig?.echo ?? false - self.rxd = Int(node?.serialConfig?.rxd ?? 0) - self.txd = Int(node?.serialConfig?.txd ?? 0) - self.baudRate = Int(node?.serialConfig?.baudRate ?? 0) - self.timeout = Int(node?.serialConfig?.timeout ?? 0) - self.mode = Int(node?.serialConfig?.mode ?? 0) - - self.hasChanges = false - self.initialLoad = false - } } .onChange(of: enabled) { newEnabled in