From 9d911a8d2c1360a3e3a25a70c8190df350721d64 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 3 Sep 2024 18:01:32 -0700 Subject: [PATCH 01/11] hook up session passkey to bluetooth config --- Localizable.xcstrings | 3 --- Meshtastic/Helpers/BLEManager.swift | 3 +++ Meshtastic/Helpers/MeshPackets.swift | 4 +++- Meshtastic/Views/Messages/UserList.swift | 2 ++ .../Settings/Config/BluetoothConfig.swift | 23 +++++++++---------- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index df568dc1..1c7ebdc7 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -5431,9 +5431,6 @@ }, "Device is managed by a mesh administrator." : { - }, - "Device Logging Enabled" : { - }, "Device Metrics" : { diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 08b53801..87551c4f 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -2564,6 +2564,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate var adminPacket = AdminMessage() adminPacket.getConfigRequest = AdminMessage.ConfigType.bluetoothConfig + if UserDefaults.enableAdministration { + adminPacket.sessionPasskey = toUser.userNode?.sessionPasskey ?? Data() + } var meshPacket: MeshPacket = MeshPacket() meshPacket.to = UInt32(toUser.num) meshPacket.from = UInt32(fromUser.num) diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index efd80d72..9f3186db 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -50,6 +50,7 @@ func generateMessageMarkdown (message: String) -> String { func localConfig (config: Config, context: NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) { + let remote = nodeNum != UserDefaults.preferredPeripheralNum if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) { upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: nodeNum, context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) { @@ -496,7 +497,8 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) { } else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getConfigResponse(adminMessage.getConfigResponse) { let config = adminMessage.getConfigResponse if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) { - upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), context: context) + upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) + /// upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) { upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) { diff --git a/Meshtastic/Views/Messages/UserList.swift b/Meshtastic/Views/Messages/UserList.swift index 3a2c4a47..44b92621 100644 --- a/Meshtastic/Views/Messages/UserList.swift +++ b/Meshtastic/Views/Messages/UserList.swift @@ -46,6 +46,7 @@ struct UserList: View { NSSortDescriptor(key: "userNode.favorite", ascending: false), NSSortDescriptor(key: "pkiEncrypted", ascending: false), NSSortDescriptor(key: "longName", ascending: true)], + predicate: NSPredicate(format: "hwModelId != nil"), animation: .default ) private var users: FetchedResults @@ -95,6 +96,7 @@ struct UserList: View { Text(user.longName ?? "unknown".localized) .font(.headline) .allowsTightening(true) + Text(user.hwModel ?? "") Spacer() if user.userNode?.favorite ?? false { Image(systemName: "star.fill") diff --git a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index 75132df1..2ec96942 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -19,7 +19,6 @@ struct BluetoothConfig: View { @State var mode = 0 @State var fixedPin = "123456" @State var shortPin = false - @State var deviceLoggingEnabled = false var pinLength: Int = 6 let numberFormatter: NumberFormatter = { let formatter = NumberFormatter() @@ -70,10 +69,6 @@ struct BluetoothConfig: View { .foregroundColor(.red) } } - Toggle(isOn: $deviceLoggingEnabled) { - Label("Device Logging Enabled", systemImage: "ladybug") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } } .disabled(self.bleManager.connectedPeripheral == nil || node?.bluetoothConfig == nil) @@ -85,7 +80,6 @@ struct BluetoothConfig: View { bc.enabled = enabled bc.mode = BluetoothModes(rawValue: mode)?.protoEnumValue() ?? Config.BluetoothConfig.PairingMode.randomPin bc.fixedPin = UInt32(fixedPin) ?? 123456 - bc.deviceLoggingEnabled = deviceLoggingEnabled let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true @@ -106,13 +100,22 @@ struct BluetoothConfig: View { ) } ) - .onAppear { + .onFirstAppear { // Need to request a BluetoothConfig from the remote node before allowing changes if let connectedPeripheral = bleManager.connectedPeripheral, let node, node.bluetoothConfig == nil { Logger.mesh.info("empty bluetooth config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - _ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.bluetoothConfig == nil { + _ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } } } } @@ -125,15 +128,11 @@ struct BluetoothConfig: View { .onChange(of: fixedPin) { newFixedPin in if newFixedPin != String(node?.bluetoothConfig?.fixedPin ?? -1) { hasChanges = true } } - .onChange(of: deviceLoggingEnabled) { - if $0 != node?.bluetoothConfig?.deviceLoggingEnabled { hasChanges = true } - } } func setBluetoothValues() { self.enabled = node?.bluetoothConfig?.enabled ?? true self.mode = Int(node?.bluetoothConfig?.mode ?? 0) self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456) - self.deviceLoggingEnabled = node?.bluetoothConfig?.deviceLoggingEnabled ?? false self.hasChanges = false } } From a4fe551e039edc29d7cc2eb740dfd6dd313d76a4 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 4 Sep 2024 10:06:34 -0700 Subject: [PATCH 02/11] Update several config sections to use the new pki admin structures --- Localizable.xcstrings | 22 ++------ Meshtastic/Extensions/View.swift | 4 +- Meshtastic/Helpers/MeshPackets.swift | 13 ++--- Meshtastic/Persistence/UpdateCoreData.swift | 2 - .../Settings/Config/BluetoothConfig.swift | 2 +- .../Views/Settings/Config/ConfigHeader.swift | 5 +- .../Views/Settings/Config/DeviceConfig.swift | 21 +++++-- .../Views/Settings/Config/DisplayConfig.swift | 21 +++++-- .../Views/Settings/Config/LoRaConfig.swift | 19 +++++-- .../Settings/Config/SecurityConfig.swift | 55 +++++++++---------- 10 files changed, 88 insertions(+), 76 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 1c7ebdc7..1857e7d1 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -109,7 +109,7 @@ "%@ Channels?" : { }, - "%@ config data was requested over the admin channel but no response has been returned from the remote node. You can check the status of admin message requests in the admin message log." : { + "%@ config data was requested over the admin channel but no response has been returned from the remote node." : { }, "%@ dB" : { @@ -1865,9 +1865,6 @@ } } } - }, - "Bluetooth Logs" : { - }, "bluetooth.config" : { "localizations" : { @@ -5070,6 +5067,9 @@ }, "Debug Log" : { + }, + "Debug Logs" : { + }, "Debug Logs%@" : { @@ -5361,9 +5361,6 @@ } } } - }, - "Developer" : { - }, "Developers" : { @@ -16073,7 +16070,7 @@ "Other data sources" : { }, - "Output live debug logging over serial." : { + "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth." : { }, "Output pin buzzer GPIO " : { @@ -19273,9 +19270,6 @@ }, "Serial Console over the Stream API." : { - }, - "Serial Debug Logs" : { - }, "serial.config" : { "localizations" : { @@ -22508,12 +22502,6 @@ }, "Via Mqtt" : { - }, - "View and export position-redacted device logs over Bluetooth" : { - - }, - "View Logs" : { - }, "voltage" : { "localizations" : { diff --git a/Meshtastic/Extensions/View.swift b/Meshtastic/Extensions/View.swift index 7349f36d..cec5b003 100644 --- a/Meshtastic/Extensions/View.swift +++ b/Meshtastic/Extensions/View.swift @@ -8,13 +8,13 @@ import SwiftUI public extension View { - func onFirstAppear(_ action: @escaping () -> ()) -> some View { + func onFirstAppear(_ action: @escaping () -> Void) -> some View { modifier(FirstAppear(action: action)) } } private struct FirstAppear: ViewModifier { - let action: () -> () + let action: () -> Void // Use this to only fire your block one time @State private var hasAppeared = false diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 9f3186db..261ffcf2 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -498,19 +498,18 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) { let config = adminMessage.getConfigResponse if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) { upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) - /// upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) { - upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), context: context) + upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) { - upsertDisplayConfigPacket(config: config.display, nodeNum: Int64(packet.from), context: context) + upsertDisplayConfigPacket(config: config.display, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) { - upsertLoRaConfigPacket(config: config.lora, nodeNum: Int64(packet.from), context: context) + upsertLoRaConfigPacket(config: config.lora, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) { - upsertNetworkConfigPacket(config: config.network, nodeNum: Int64(packet.from), context: context) + upsertNetworkConfigPacket(config: config.network, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) { - upsertPositionConfigPacket(config: config.position, nodeNum: Int64(packet.from), context: context) + upsertPositionConfigPacket(config: config.position, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.power(config.power) { - upsertPowerConfigPacket(config: config.power, nodeNum: Int64(packet.from), context: context) + upsertPowerConfigPacket(config: config.power, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) } else if config.payloadVariant == Config.OneOf_PayloadVariant.security(config.security) { upsertSecurityConfigPacket(config: config.security, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context) } diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index 7c43448b..b3e4dba6 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -409,13 +409,11 @@ func upsertBluetoothConfigPacket(config: Config.BluetoothConfig, nodeNum: Int64, newBluetoothConfig.enabled = config.enabled newBluetoothConfig.mode = Int32(config.mode.rawValue) newBluetoothConfig.fixedPin = Int32(config.fixedPin) - newBluetoothConfig.deviceLoggingEnabled = config.deviceLoggingEnabled fetchedNode[0].bluetoothConfig = newBluetoothConfig } else { fetchedNode[0].bluetoothConfig?.enabled = config.enabled fetchedNode[0].bluetoothConfig?.mode = Int32(config.mode.rawValue) fetchedNode[0].bluetoothConfig?.fixedPin = Int32(config.fixedPin) - fetchedNode[0].bluetoothConfig?.deviceLoggingEnabled = config.deviceLoggingEnabled } if sessionPasskey != nil { fetchedNode[0].sessionPasskey = sessionPasskey diff --git a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index 2ec96942..1fdd3a89 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -102,7 +102,7 @@ struct BluetoothConfig: View { ) .onFirstAppear { // Need to request a BluetoothConfig from the remote node before allowing changes - if let connectedPeripheral = bleManager.connectedPeripheral, let node, node.bluetoothConfig == nil { + if let connectedPeripheral = bleManager.connectedPeripheral, let node { Logger.mesh.info("empty bluetooth config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { diff --git a/Meshtastic/Views/Settings/Config/ConfigHeader.swift b/Meshtastic/Views/Settings/Config/ConfigHeader.swift index 3f59a01a..d1af3a6a 100644 --- a/Meshtastic/Views/Settings/Config/ConfigHeader.swift +++ b/Meshtastic/Views/Settings/Config/ConfigHeader.swift @@ -17,8 +17,9 @@ struct ConfigHeader: View { } else if node != nil && node?.num ?? 0 != bleManager.connectedPeripheral?.num ?? 0 { // Let users know what is going on if they are using remote admin and don't have the config yet - if node?[keyPath: config] == nil { - Text("\(title) config data was requested over the admin channel but no response has been returned from the remote node. You can check the status of admin message requests in the admin message log.") + let expiration = node?.sessionExpiration ?? Date() + if node?[keyPath: config] == nil || expiration < node?.sessionExpiration ?? Date() { + Text("\(title) config data was requested over the admin channel but no response has been returned from the remote node.") .font(.callout) .foregroundColor(.orange) } else { diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index 13d3aa83..ea01e66f 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -242,13 +242,24 @@ struct DeviceConfig: View { ) } ) - .onAppear { + .onFirstAppear { // Need to request a DeviceConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.deviceConfig == nil { + if let connectedPeripheral = bleManager.connectedPeripheral, let node { Logger.mesh.info("empty device config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? -1, context: context) - if node != nil && connectedNode != nil && connectedNode?.user != nil { - _ = bleManager.requestDeviceConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.deviceConfig == nil { + _ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + if node.deviceConfig == nil { + /// Legacy Administration + _ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/DisplayConfig.swift b/Meshtastic/Views/Settings/Config/DisplayConfig.swift index 1f3f6de4..0ef44bc1 100644 --- a/Meshtastic/Views/Settings/Config/DisplayConfig.swift +++ b/Meshtastic/Views/Settings/Config/DisplayConfig.swift @@ -163,13 +163,22 @@ struct DisplayConfig: View { ) } ) - .onAppear { - // Need to request a LoRaConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.displayConfig == nil { + .onFirstAppear { + // Need to request a DisplayConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { Logger.mesh.info("empty display config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestDisplayConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.displayConfig == nil { + _ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } } } } diff --git a/Meshtastic/Views/Settings/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index dad7c1a4..b9926b8a 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -232,13 +232,22 @@ struct LoRaConfig: View { ) } ) - .onAppear { + .onFirstAppear { // Need to request a LoRaConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.loRaConfig == nil { + if let connectedPeripheral = bleManager.connectedPeripheral, let node { Logger.mesh.info("empty lora config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestLoRaConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.loRaConfig == nil { + _ = bleManager.requestLoRaConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestLoRaConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } } } } diff --git a/Meshtastic/Views/Settings/Config/SecurityConfig.swift b/Meshtastic/Views/Settings/Config/SecurityConfig.swift index e07ed945..5576ac6f 100644 --- a/Meshtastic/Views/Settings/Config/SecurityConfig.swift +++ b/Meshtastic/Views/Settings/Config/SecurityConfig.swift @@ -30,7 +30,6 @@ struct SecurityConfig: View { @State var isManaged = false @State var serialEnabled = false @State var debugLogApiEnabled = false - @State var bluetoothLoggingEnabled = false @State var adminChannelEnabled = false var body: some View { @@ -71,10 +70,15 @@ struct SecurityConfig: View { } } Section(header: Text("Logs")) { - Toggle(isOn: $bluetoothLoggingEnabled) { - Label("Bluetooth Logs", systemImage: "dot.radiowaves.right") - Text("View and export position-redacted device logs over Bluetooth") - Link("View Logs", destination: URL(string: "meshtastic:///settings/debugLogs")!) + Toggle(isOn: $serialEnabled) { + Label("Serial Console", systemImage: "terminal") + Text("Serial Console over the Stream API.") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + + Toggle(isOn: $debugLogApiEnabled) { + Label("Debug Logs", systemImage: "ant.fill") + Text("Output live debug logging over serial, view and export position-redacted device logs over Bluetooth.") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } @@ -92,20 +96,6 @@ struct SecurityConfig: View { } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } - Section(header: Text("Developer")) { - Toggle(isOn: $serialEnabled) { - Label("Serial Console", systemImage: "terminal") - Text("Serial Console over the Stream API.") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - if serialEnabled { - Toggle(isOn: $debugLogApiEnabled) { - Label("Serial Debug Logs", systemImage: "ant.fill") - Text("Output live debug logging over serial.") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - } - } } } .scrollDismissesKeyboard(.immediately) @@ -126,9 +116,6 @@ struct SecurityConfig: View { .onChange(of: debugLogApiEnabled) { if $0 != node?.securityConfig?.debugLogApiEnabled { hasChanges = true } } - .onChange(of: bluetoothLoggingEnabled) { - if $0 != node?.securityConfig?.bluetoothLoggingEnabled { hasChanges = true } - } .onChange(of: adminChannelEnabled) { if $0 != node?.securityConfig?.adminChannelEnabled { hasChanges = true } } @@ -162,11 +149,23 @@ struct SecurityConfig: View { hasChanges = true } .onFirstAppear { - // Need to request a Power config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.securityConfig == nil { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestSecurityConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + // Need to request a DeviceConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty security config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.securityConfig == nil { + _ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + if node.deviceConfig == nil { + /// Legacy Administration + _ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } @@ -190,7 +189,6 @@ struct SecurityConfig: View { config.isManaged = isManaged config.serialEnabled = serialEnabled config.debugLogApiEnabled = debugLogApiEnabled - config.bluetoothLoggingEnabled = bluetoothLoggingEnabled config.adminChannelEnabled = adminChannelEnabled let adminMessageId = bleManager.saveSecurityConfig( @@ -215,7 +213,6 @@ struct SecurityConfig: View { self.isManaged = node?.securityConfig?.isManaged ?? false self.serialEnabled = node?.securityConfig?.serialEnabled ?? false self.debugLogApiEnabled = node?.securityConfig?.debugLogApiEnabled ?? false - self.bluetoothLoggingEnabled = node?.securityConfig?.bluetoothLoggingEnabled ?? false self.adminChannelEnabled = node?.securityConfig?.adminChannelEnabled ?? false self.hasChanges = false } From 44d65d8185dc50d66f860df673b89573c36cb687 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 4 Sep 2024 10:27:06 -0700 Subject: [PATCH 03/11] Additional config sections --- Meshtastic.xcodeproj/project.pbxproj | 2 +- .../Views/Settings/Config/NetworkConfig.swift | 19 +++++++++++ .../Settings/Config/PositionConfig.swift | 23 +++++++------ .../Views/Settings/Config/PowerConfig.swift | 32 ++++++++++++++++--- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 83fac71b..43f27393 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -719,8 +719,8 @@ DD41582528582E9B009B0E59 /* DeviceConfig.swift */, DD8EBF42285058FA00426DCA /* DisplayConfig.swift */, DD2553562855B02500E55709 /* LoRaConfig.swift */, - DD2553582855B52700E55709 /* PositionConfig.swift */, DD8ED9C42898D51F00B3B0AB /* NetworkConfig.swift */, + DD2553582855B52700E55709 /* PositionConfig.swift */, D93068DA2B81C85E0066FBC8 /* PowerConfig.swift */, DD1BD0F22C63C65E008C0C70 /* SecurityConfig.swift */, DD61937B2863877A00E59241 /* Module */, diff --git a/Meshtastic/Views/Settings/Config/NetworkConfig.swift b/Meshtastic/Views/Settings/Config/NetworkConfig.swift index 0554c766..dd767b6c 100644 --- a/Meshtastic/Views/Settings/Config/NetworkConfig.swift +++ b/Meshtastic/Views/Settings/Config/NetworkConfig.swift @@ -128,6 +128,25 @@ struct NetworkConfig: View { } } } + .onFirstAppear { + // Need to request a NetworkConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty network config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.networkConfig == nil { + _ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } + } + } .onChange(of: wifiEnabled) { if $0 != node?.networkConfig?.wifiEnabled { hasChanges = true } } diff --git a/Meshtastic/Views/Settings/Config/PositionConfig.swift b/Meshtastic/Views/Settings/Config/PositionConfig.swift index 0f71b379..392486da 100644 --- a/Meshtastic/Views/Settings/Config/PositionConfig.swift +++ b/Meshtastic/Views/Settings/Config/PositionConfig.swift @@ -376,18 +376,23 @@ struct PositionConfig: View { ) } ) - .onAppear { + .onFirstAppear { supportedVersion = bleManager.connectedVersion == "0.0.0" || self.minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedAscending || minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedSame - // Need to request a PositionConfig from the remote node before allowing changes - if let connectedPeripheral = bleManager.connectedPeripheral, node?.positionConfig == nil { + // Need to request a NetworkConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { Logger.mesh.info("empty position config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) - if let node, let connectedNode { - _ = bleManager.requestPositionConfig( - fromUser: connectedNode.user!, - toUser: node.user!, - adminIndex: connectedNode.myInfo?.adminIndex ?? 0 - ) + if let connectedNode { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.positionConfig == nil { + _ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } } } } diff --git a/Meshtastic/Views/Settings/Config/PowerConfig.swift b/Meshtastic/Views/Settings/Config/PowerConfig.swift index 42b6a534..cf213f8e 100644 --- a/Meshtastic/Views/Settings/Config/PowerConfig.swift +++ b/Meshtastic/Views/Settings/Config/PowerConfig.swift @@ -1,5 +1,6 @@ import SwiftUI import MeshtasticProtobufs +import OSLog struct PowerConfig: View { @Environment(\.managedObjectContext) private var context @@ -118,6 +119,17 @@ struct PowerConfig: View { } } .onAppear { + + // Need to request a Power config from the remote node before allowing changes + if bleManager.connectedPeripheral != nil && node?.powerConfig == nil { + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) + if node != nil && connectedNode != nil { + _ = bleManager.requestPowerConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + } + } + } + + .onFirstAppear { Api().loadDeviceHardwareData { (hw) in for device in hw { let currentHardware = node?.user?.hwModel ?? "UNSET" @@ -127,11 +139,21 @@ struct PowerConfig: View { } } } - // Need to request a Power config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.powerConfig == nil { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestPowerConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + // Need to request a NetworkConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty power config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.positionConfig == nil { + _ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestPowerConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } } } } From e294a2480c59120853ac49f44658c738d5b5928a Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 4 Sep 2024 12:22:25 -0700 Subject: [PATCH 04/11] Remove debugging hardware version --- Meshtastic/Views/Messages/UserList.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Meshtastic/Views/Messages/UserList.swift b/Meshtastic/Views/Messages/UserList.swift index 44b92621..4e09859f 100644 --- a/Meshtastic/Views/Messages/UserList.swift +++ b/Meshtastic/Views/Messages/UserList.swift @@ -96,7 +96,6 @@ struct UserList: View { Text(user.longName ?? "unknown".localized) .font(.headline) .allowsTightening(true) - Text(user.hwModel ?? "") Spacer() if user.userNode?.favorite ?? false { Image(systemName: "star.fill") From 23d62e8e1237e4e0a52e44f5c26519b2c31ff65f Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 4 Sep 2024 18:02:17 -0700 Subject: [PATCH 05/11] Set public key on upsert of existing node --- Meshtastic/Persistence/UpdateCoreData.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index b3e4dba6..f58a0a64 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -269,6 +269,8 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext) fetchedNode[0].user!.role = Int32(nodeInfoMessage.user.role.rawValue) fetchedNode[0].user!.hwModel = String(describing: nodeInfoMessage.user.hwModel).uppercased() fetchedNode[0].user!.hwModelId = Int32(nodeInfoMessage.user.hwModel.rawValue) + fetchedNode[0].user!.pkiEncrypted = packet.pkiEncrypted + fetchedNode[0].user!.publicKey = packet.publicKey Task { Api().loadDeviceHardwareData { (hw) in let dh = hw.first(where: { $0.hwModel == fetchedNode[0].user?.hwModelId ?? 0 }) From 1853afde73e29e7c2381b4ae63af28f596f61866 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 4 Sep 2024 18:13:35 -0700 Subject: [PATCH 06/11] allow retry of pki failed --- Meshtastic/Enums/RoutingError.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Meshtastic/Enums/RoutingError.swift b/Meshtastic/Enums/RoutingError.swift index 108fedd2..8b50de89 100644 --- a/Meshtastic/Enums/RoutingError.swift +++ b/Meshtastic/Enums/RoutingError.swift @@ -95,7 +95,7 @@ enum RoutingError: Int, CaseIterable, Identifiable { case .notAuthorized: return true case .pkiFailed: - return false + return true case .pkiUnknownPubkey: return false } From 6e6027263a2ef9a9bbd02fa68cf75254fab1e1a0 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 5 Sep 2024 10:39:54 -0700 Subject: [PATCH 07/11] Log node info packet json --- Localizable.xcstrings | 5 +---- Meshtastic/Helpers/BLEManager.swift | 1 + Meshtastic/Helpers/MeshPackets.swift | 2 +- Meshtastic/Persistence/UpdateCoreData.swift | 7 +++++-- .../Views/Settings/Config/DeviceConfig.swift | 16 ---------------- .../Views/Settings/Config/SecurityConfig.swift | 3 +-- 6 files changed, 9 insertions(+), 25 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 1857e7d1..b6673742 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -5426,7 +5426,7 @@ "Device GPS" : { }, - "Device is managed by a mesh administrator." : { + "Device is managed by a mesh administrator, the user is unable to access any of the device settings." : { }, "Device Metrics" : { @@ -6923,9 +6923,6 @@ }, "Enabling Ethernet will disable the bluetooth connection to the app." : { - }, - "Enabling Managed mode will restrict access to all radio configurations, such as short/long names, regions, channels, modules, etc. and will only be accessible through the Admin channel. To avoid being locked out, make sure the Admin channel is working properly before enabling it." : { - }, "Enabling WiFi will disable the bluetooth connection to the app." : { diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 87551c4f..11597647 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -766,6 +766,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate case .waypointApp: waypointPacket(packet: decodedInfo.packet, context: context) case .nodeinfoApp: + MeshLogger.log("🕸️ MESH PACKET received for Node Info App for PKI LOCK debugging \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure")") if !invalidVersion { upsertNodeInfoPacket(packet: decodedInfo.packet, context: context) } case .routingApp: if !invalidVersion { routingPacket(packet: decodedInfo.packet, connectedNodeNum: self.connectedPeripheral.num, context: context) } diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 261ffcf2..3b6b2b65 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -366,7 +366,7 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje fetchedNode[0].user = UserEntity(context: context) } // Set the public key for a user if it is empty, don't update - if fetchedNode[0].user?.publicKey?.isEmpty == nil && !nodeInfo.user.publicKey.isEmpty { + if fetchedNode[0].user?.publicKey == nil && !nodeInfo.user.publicKey.isEmpty { fetchedNode[0].user?.pkiEncrypted = true fetchedNode[0].user?.publicKey = nodeInfo.user.publicKey } diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index f58a0a64..039b654e 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -269,8 +269,11 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext) fetchedNode[0].user!.role = Int32(nodeInfoMessage.user.role.rawValue) fetchedNode[0].user!.hwModel = String(describing: nodeInfoMessage.user.hwModel).uppercased() fetchedNode[0].user!.hwModelId = Int32(nodeInfoMessage.user.hwModel.rawValue) - fetchedNode[0].user!.pkiEncrypted = packet.pkiEncrypted - fetchedNode[0].user!.publicKey = packet.publicKey + + if !packet.publicKey.isEmpty { + fetchedNode[0].user!.pkiEncrypted = packet.pkiEncrypted + fetchedNode[0].user!.publicKey = packet.publicKey + } Task { Api().loadDeviceHardwareData { (hw) in let dh = hw.first(where: { $0.hwModel == fetchedNode[0].user?.hwModelId ?? 0 }) diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index ea01e66f..9382b297 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -29,7 +29,6 @@ struct DeviceConfig: View { @State var nodeInfoBroadcastSecs = 10800 @State var doubleTapAsButtonPress = false @State var ledHeartbeatEnabled = true - @State var isManaged = false @State var tzdef = "" var body: some View { @@ -62,12 +61,6 @@ struct DeviceConfig: View { } .pickerStyle(DefaultPickerStyle()) - Toggle(isOn: $isManaged) { - Label("Managed Device", systemImage: "gearshape.arrow.triangle.2.circlepath") - Text("Enabling Managed mode will restrict access to all radio configurations, such as short/long names, regions, channels, modules, etc. and will only be accessible through the Admin channel. To avoid being locked out, make sure the Admin channel is working properly before enabling it.") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Picker("Node Info Broadcast Interval", selection: $nodeInfoBroadcastSecs ) { ForEach(UpdateIntervals.allCases) { ui in if ui.rawValue >= 3600 { @@ -213,13 +206,8 @@ struct DeviceConfig: View { dc.rebroadcastMode = RebroadcastModes(rawValue: rebroadcastMode)?.protoEnumValue() ?? RebroadcastModes.all.protoEnumValue() dc.nodeInfoBroadcastSecs = UInt32(nodeInfoBroadcastSecs) dc.doubleTapAsButtonPress = doubleTapAsButtonPress - dc.isManaged = isManaged dc.tzdef = tzdef dc.ledHeartbeatDisabled = !ledHeartbeatEnabled - if isManaged { - serialEnabled = false - debugLogEnabled = false - } let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true @@ -287,9 +275,6 @@ struct DeviceConfig: View { .onChange(of: doubleTapAsButtonPress) { if $0 != node?.deviceConfig?.doubleTapAsButtonPress { hasChanges = true } } - .onChange(of: isManaged) { - if $0 != node?.deviceConfig?.isManaged { hasChanges = true } - } .onChange(of: tzdef) { newTzdef in if newTzdef != node?.deviceConfig?.tzdef { hasChanges = true } } @@ -312,7 +297,6 @@ struct DeviceConfig: View { } self.doubleTapAsButtonPress = node?.deviceConfig?.doubleTapAsButtonPress ?? false self.ledHeartbeatEnabled = node?.deviceConfig?.ledHeartbeatEnabled ?? true - self.isManaged = node?.deviceConfig?.isManaged ?? false self.tzdef = node?.deviceConfig?.tzdef ?? "" if self.tzdef.isEmpty { self.tzdef = TimeZone.current.posixDescription diff --git a/Meshtastic/Views/Settings/Config/SecurityConfig.swift b/Meshtastic/Views/Settings/Config/SecurityConfig.swift index 5576ac6f..6388ea6e 100644 --- a/Meshtastic/Views/Settings/Config/SecurityConfig.swift +++ b/Meshtastic/Views/Settings/Config/SecurityConfig.swift @@ -75,7 +75,6 @@ struct SecurityConfig: View { Text("Serial Console over the Stream API.") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Toggle(isOn: $debugLogApiEnabled) { Label("Debug Logs", systemImage: "ant.fill") Text("Output live debug logging over serial, view and export position-redacted device logs over Bluetooth.") @@ -86,7 +85,7 @@ struct SecurityConfig: View { if adminKey.length > 0 || adminChannelEnabled { Toggle(isOn: $isManaged) { Label("Managed Device", systemImage: "gearshape.arrow.triangle.2.circlepath") - Text("Device is managed by a mesh administrator.") + Text("Device is managed by a mesh administrator, the user is unable to access any of the device settings.") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } From b32cabec54e7dba50cdbc947570b57f0f5b1601d Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 5 Sep 2024 13:42:46 -0700 Subject: [PATCH 08/11] set keys on create user catch --- Meshtastic/Persistence/UpdateCoreData.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index 039b654e..624dbb20 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -209,6 +209,8 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext) } else { if packet.from > Constants.minimumNodeNum { let newUser = createUser(num: Int64(packet.from), context: context) + newNode.user?.pkiEncrypted = packet.pkiEncrypted + newNode.user?.publicKey = packet.publicKey newNode.user = newUser } } From d95cf2d1901e45151d0fdbabef764c82511f9f72 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 5 Sep 2024 14:07:40 -0700 Subject: [PATCH 09/11] Add lock to node list --- Meshtastic/Views/Nodes/Helpers/NodeListItem.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift index 63aff338..481666a1 100644 --- a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift +++ b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift @@ -30,8 +30,22 @@ struct NodeListItem: View { } VStack(alignment: .leading) { HStack { + if node.user?.pkiEncrypted ?? false { + if !(node.user?.keyMatch ?? false) { + /// Public Key on the User and the Public Key on the Last Message don't match + Image(systemName: "key.slash") + .foregroundColor(.red) + } else { + Image(systemName: "lock.fill") + .foregroundColor(.green) + } + } else { + Image(systemName: "lock.open.fill") + .foregroundColor(.yellow) + } Text(node.user?.longName ?? "unknown".localized) .font(.headline) + .fontWeight(.regular) .allowsTightening(true) if node.favorite { Spacer() From d0e10ef3301b5485c8210398d44b433b705c33a4 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 5 Sep 2024 19:31:29 -0700 Subject: [PATCH 10/11] Finish up the admin, make the admin dropdown a navigationlink so you can read the full long name --- Localizable.xcstrings | 3 -- Meshtastic/Views/Settings/Channels.swift | 9 +++--- .../Views/Settings/Channels/ChannelForm.swift | 26 ++++++++--------- .../Settings/Config/BluetoothConfig.swift | 16 +++++----- .../Views/Settings/Config/DeviceConfig.swift | 22 +++++++------- .../Views/Settings/Config/DisplayConfig.swift | 16 +++++----- .../Views/Settings/Config/LoRaConfig.swift | 16 +++++----- .../Config/Module/AmbientLightingConfig.swift | 23 +++++++++++---- .../Config/Module/CannedMessagesConfig.swift | 23 +++++++++++---- .../Config/Module/DetectionSensorConfig.swift | 25 +++++++++++----- .../Module/ExternalNotificationConfig.swift | 27 ++++++++++++----- .../Settings/Config/Module/MQTTConfig.swift | 23 +++++++++++---- .../Config/Module/PaxCounterConfig.swift | 25 ++++++++++++---- .../Config/Module/RangeTestConfig.swift | 25 +++++++++++----- .../Settings/Config/Module/RtttlConfig.swift | 25 ++++++++++++---- .../Settings/Config/Module/SerialConfig.swift | 25 +++++++++++----- .../Config/Module/StoreForwardConfig.swift | 25 +++++++++++----- .../Config/Module/TelemetryConfig.swift | 21 ++++++++++---- .../Views/Settings/Config/NetworkConfig.swift | 16 +++++----- .../Settings/Config/PositionConfig.swift | 16 +++++----- .../Views/Settings/Config/PowerConfig.swift | 29 +++++++------------ .../Settings/Config/SecurityConfig.swift | 22 +++++++------- Meshtastic/Views/Settings/Settings.swift | 6 ++-- 23 files changed, 296 insertions(+), 168 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index b6673742..05c2bbb8 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -4581,9 +4581,6 @@ }, "Configure" : { - }, - "Configuring Node" : { - }, "Connect to a Node" : { diff --git a/Meshtastic/Views/Settings/Channels.swift b/Meshtastic/Views/Settings/Channels.swift index 61cddcea..f039534c 100644 --- a/Meshtastic/Views/Settings/Channels.swift +++ b/Meshtastic/Views/Settings/Channels.swift @@ -95,7 +95,6 @@ struct Channels: View { if channelKey == "AQ==" { positionPrecision = 13 preciseLocation = false - positionsEnabled = true } } else if !supportedVersion && channelRole == 2 { positionPrecision = 0 @@ -104,7 +103,7 @@ struct Channels: View { } else { if channelKey == "AQ==" { preciseLocation = false - if positionPrecision < 10 || positionPrecision > 16 { + if (positionPrecision > 0 && positionPrecision < 10) || positionPrecision > 16 { positionPrecision = 13 } } else if positionPrecision == 32 { @@ -226,7 +225,7 @@ struct Channels: View { } label: { Label("save", systemImage: "square.and.arrow.down") } - .disabled(bleManager.connectedPeripheral == nil || !hasChanges || !hasValidKey) + .disabled(bleManager.connectedPeripheral == nil)// || !hasChanges)// !hasValidKey) .buttonStyle(.bordered) .buttonBorderShape(.capsule) .controlSize(.large) @@ -259,10 +258,9 @@ struct Channels: View { channelKey = key positionsEnabled = false preciseLocation = false - positionPrecision = 13 + positionPrecision = 0 uplink = false downlink = false - hasChanges = true let newChannel = ChannelEntity(context: context) newChannel.id = channelIndex @@ -274,6 +272,7 @@ struct Channels: View { newChannel.psk = Data(base64Encoded: channelKey) ?? Data() newChannel.positionPrecision = Int32(positionPrecision) selectedChannel = newChannel + hasChanges = true } label: { Label("Add Channel", systemImage: "plus.square") diff --git a/Meshtastic/Views/Settings/Channels/ChannelForm.swift b/Meshtastic/Views/Settings/Channels/ChannelForm.swift index d0a111e5..d21e0f42 100644 --- a/Meshtastic/Views/Settings/Channels/ChannelForm.swift +++ b/Meshtastic/Views/Settings/Channels/ChannelForm.swift @@ -130,7 +130,6 @@ struct ChannelForm: View { } Section(header: Text("position")) { - VStack(alignment: .leading) { Toggle(isOn: $positionsEnabled) { Label(channelRole == 1 ? "Positions Enabled" : "Allow Position Requests", systemImage: positionsEnabled ? "mappin" : "mappin.slash") @@ -140,20 +139,21 @@ struct ChannelForm: View { } if positionsEnabled { - VStack(alignment: .leading) { - Toggle(isOn: $preciseLocation) { - Label("Precise Location", systemImage: "scope") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .disabled(!supportedVersion) - .listRowSeparator(.visible) - .onChange(of: preciseLocation) { pl in - if pl == false { - positionPrecision = 13 + if channelKey != "AQ==" && channelRole > 0 { + VStack(alignment: .leading) { + Toggle(isOn: $preciseLocation) { + Label("Precise Location", systemImage: "scope") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + .disabled(!supportedVersion) + .listRowSeparator(.visible) + .onChange(of: preciseLocation) { pl in + if pl == false { + positionPrecision = 13 + } } } } - if !preciseLocation { VStack(alignment: .leading) { Label("Approximate Location", systemImage: "location.slash.circle.fill") @@ -213,7 +213,7 @@ struct ChannelForm: View { } .onChange(of: preciseLocation) { loc in if loc == true { - if channelKey == "AQ==" && channelRole == 0 { + if channelKey == "AQ==" { preciseLocation = false } else { positionPrecision = 32 diff --git a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index 1fdd3a89..46211dac 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -106,15 +106,17 @@ struct BluetoothConfig: View { Logger.mesh.info("empty bluetooth config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.bluetoothConfig == nil { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.bluetoothConfig == nil { + _ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration _ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } - } else { - /// Legacy Administration - _ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } } } diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index 9382b297..dc17446e 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -236,16 +236,18 @@ struct DeviceConfig: View { Logger.mesh.info("empty device config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.deviceConfig == nil { - _ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) - } - } else { - if node.deviceConfig == nil { - /// Legacy Administration - _ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.deviceConfig == nil { + _ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + if node.deviceConfig == nil { + /// Legacy Administration + _ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } } } } diff --git a/Meshtastic/Views/Settings/Config/DisplayConfig.swift b/Meshtastic/Views/Settings/Config/DisplayConfig.swift index 0ef44bc1..1e9781a6 100644 --- a/Meshtastic/Views/Settings/Config/DisplayConfig.swift +++ b/Meshtastic/Views/Settings/Config/DisplayConfig.swift @@ -169,15 +169,17 @@ struct DisplayConfig: View { Logger.mesh.info("empty display config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.displayConfig == nil { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.displayConfig == nil { + _ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration _ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } - } else { - /// Legacy Administration - _ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } } } diff --git a/Meshtastic/Views/Settings/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index b9926b8a..43729f86 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -238,15 +238,17 @@ struct LoRaConfig: View { Logger.mesh.info("empty lora config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.loRaConfig == nil { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.loRaConfig == nil { + _ = bleManager.requestLoRaConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration _ = bleManager.requestLoRaConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } - } else { - /// Legacy Administration - _ = bleManager.requestLoRaConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } } } diff --git a/Meshtastic/Views/Settings/Config/Module/AmbientLightingConfig.swift b/Meshtastic/Views/Settings/Config/Module/AmbientLightingConfig.swift index 76c98752..fe3faa51 100644 --- a/Meshtastic/Views/Settings/Config/Module/AmbientLightingConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/AmbientLightingConfig.swift @@ -6,6 +6,7 @@ // import MeshtasticProtobufs import SwiftUI +import OSLog @available(iOS 17.0, macOS 14.0, *) struct AmbientLightingConfig: View { @@ -85,12 +86,24 @@ struct AmbientLightingConfig: View { ) } ) - .onAppear { + .onFirstAppear { // Need to request a Ambient Lighting Config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.ambientLightingConfig == nil { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestAmbientLightingConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty ambient lighting config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.ambientLightingConfig == nil { + _ = bleManager.requestAmbientLightingConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestAmbientLightingConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift index b4ec0b63..5b94e8c3 100644 --- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift @@ -233,13 +233,24 @@ struct CannedMessagesConfig: View { ) } ) - .onAppear { + .onFirstAppear { // Need to request a CannedMessagesModuleConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.cannedMessageConfig == nil { - Logger.mesh.info("empty canned messages module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestCannedMessagesModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty canned message config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.cannedMessageConfig == nil { + _ = bleManager.requestCannedMessagesModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestCannedMessagesModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/DetectionSensorConfig.swift b/Meshtastic/Views/Settings/Config/Module/DetectionSensorConfig.swift index 1ff1ed86..e67898eb 100644 --- a/Meshtastic/Views/Settings/Config/Module/DetectionSensorConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/DetectionSensorConfig.swift @@ -189,13 +189,24 @@ struct DetectionSensorConfig: View { ) } ) - .onAppear { - // Need to request a Detection Sensor Module Config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.detectionSensorConfig == nil { - Logger.mesh.info("empty detection sensor module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestDetectionSensorModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + .onFirstAppear { + // Need to request a DetectionSensorModuleConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty detection sensor config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.detectionSensorConfig == nil { + _ = bleManager.requestDetectionSensorModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestDetectionSensorModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift index 32cacbd3..57c3a672 100644 --- a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift @@ -199,13 +199,24 @@ struct ExternalNotificationConfig: View { ) } ) - .onAppear { - // Need to request a TelemetryModuleConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.externalNotificationConfig == nil { - Logger.mesh.info("empty external notification module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestExternalNotificationModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + .onFirstAppear { + // Need to request a ExternalNotificationModuleConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty external notificaiton module config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.externalNotificationConfig == nil { + _ = bleManager.requestExternalNotificationModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestExternalNotificationModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } @@ -279,7 +290,7 @@ struct ExternalNotificationConfig: View { if newNagTimeout != node!.externalNotificationConfig!.nagTimeout { hasChanges = true } } } - .onChange(of: useI2SAsBuzzer) { + .onChange(of: useI2SAsBuzzer) { if let val = node?.externalNotificationConfig?.useI2SAsBuzzer { hasChanges = $0 != val } diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index 8ef411ea..d6cbbf2b 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -347,13 +347,24 @@ struct MQTTConfig: View { if newMapPublishIntervalSecs != node!.mqttConfig!.mapPublishIntervalSecs { hasChanges = true } } } - .onAppear { - // Need to request a TelemetryModuleConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.mqttConfig == nil { + .onFirstAppear { + // Need to request a MqttModuleConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { Logger.mesh.info("empty mqtt module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestMqttModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.mqttConfig == nil { + _ = bleManager.requestMqttModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestMqttModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift b/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift index 6e7bef08..1141bc7d 100644 --- a/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift @@ -7,6 +7,7 @@ import MeshtasticProtobufs import SwiftUI +import OSLog struct PaxCounterConfig: View { @Environment(\.managedObjectContext) private var context @@ -57,12 +58,24 @@ struct PaxCounterConfig: View { name: "\(bleManager.connectedPeripheral?.shortName ?? "?")" ) }) - .onAppear { - // Need to request a PAX Counter module config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.paxCounterConfig == nil { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestPaxCounterModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + .onFirstAppear { + // Need to request a PaxCounterModuleConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty pax counter module config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.paxCounterConfig == nil { + _ = bleManager.requestPaxCounterModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestPaxCounterModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift index 001ad2b1..872294d8 100644 --- a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift @@ -81,13 +81,24 @@ struct RangeTestConfig: View { ) } ) - .onAppear { - // Need to request a RangeTestModule Config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.rangeTestConfig == nil { - Logger.mesh.debug("empty range test module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestRangeTestModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + .onFirstAppear { + // Need to request a RangeTestModuleConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty range test module config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.rangeTestConfig == nil { + _ = bleManager.requestRangeTestModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestRangeTestModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/RtttlConfig.swift b/Meshtastic/Views/Settings/Config/Module/RtttlConfig.swift index 95f237a3..46b02848 100644 --- a/Meshtastic/Views/Settings/Config/Module/RtttlConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RtttlConfig.swift @@ -6,6 +6,7 @@ // import SwiftUI +import OSLog struct RtttlConfig: View { @Environment(\.managedObjectContext) var context @@ -71,12 +72,24 @@ struct RtttlConfig: View { ) } ) - .onAppear { - // Need to request a Rtttl Config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && (node?.rtttlConfig == nil || node?.rtttlConfig?.ringtone?.count ?? 0 == 0) { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestRtttlConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + .onFirstAppear { + // Need to request a RtttlConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty range test module config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.rtttlConfig == nil { + _ = bleManager.requestRtttlConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestRtttlConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift index c7243a87..893ddca1 100644 --- a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift @@ -136,20 +136,31 @@ struct SerialConfig: View { ) } ) - .onAppear { + .onFirstAppear { // Need to request a SerialModuleConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.serialConfig == nil { - Logger.mesh.debug("empty serial module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestSerialModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty serial module config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.serialConfig == nil { + _ = bleManager.requestSerialModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestSerialModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } .onChange(of: enabled) { if $0 != node?.serialConfig?.enabled { hasChanges = true } } - .onChange(of: echo) { + .onChange(of: echo) { if $0 != node?.serialConfig?.echo { hasChanges = true } } .onChange(of: rxd) { newRxd in diff --git a/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift b/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift index 4829a5fa..8fff8979 100644 --- a/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift @@ -146,13 +146,24 @@ struct StoreForwardConfig: View { ) } ) - .onAppear { - // Need to request a Detection Sensor Module Config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.storeForwardConfig == nil { - Logger.mesh.debug("empty store and forward module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestStoreAndForwardModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + .onFirstAppear { + // Need to request a StoreForwardModuleConfig from the remote node before allowing changes + if let connectedPeripheral = bleManager.connectedPeripheral, let node { + Logger.mesh.info("empty store & forward module config") + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.storeForwardConfig == nil { + _ = bleManager.requestStoreAndForwardModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestStoreAndForwardModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift index df811677..afef5727 100644 --- a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift @@ -134,13 +134,24 @@ struct TelemetryConfig: View { ) } ) - .onAppear { + .onFirstAppear { // Need to request a TelemetryModuleConfig from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.telemetryConfig == nil { + if let connectedPeripheral = bleManager.connectedPeripheral, let node { Logger.mesh.info("empty telemetry module config") - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestTelemetryModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) + if let connectedNode { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration && node.num != connectedNode.num { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.telemetryConfig == nil { + _ = bleManager.requestTelemetryModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestTelemetryModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } } } diff --git a/Meshtastic/Views/Settings/Config/NetworkConfig.swift b/Meshtastic/Views/Settings/Config/NetworkConfig.swift index dd767b6c..928bad57 100644 --- a/Meshtastic/Views/Settings/Config/NetworkConfig.swift +++ b/Meshtastic/Views/Settings/Config/NetworkConfig.swift @@ -134,15 +134,17 @@ struct NetworkConfig: View { Logger.mesh.info("empty network config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.networkConfig == nil { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.networkConfig == nil { + _ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration _ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } - } else { - /// Legacy Administration - _ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } } } diff --git a/Meshtastic/Views/Settings/Config/PositionConfig.swift b/Meshtastic/Views/Settings/Config/PositionConfig.swift index 392486da..4497c1f7 100644 --- a/Meshtastic/Views/Settings/Config/PositionConfig.swift +++ b/Meshtastic/Views/Settings/Config/PositionConfig.swift @@ -383,15 +383,17 @@ struct PositionConfig: View { Logger.mesh.info("empty position config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.positionConfig == nil { + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.positionConfig == nil { + _ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration _ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } - } else { - /// Legacy Administration - _ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } } } diff --git a/Meshtastic/Views/Settings/Config/PowerConfig.swift b/Meshtastic/Views/Settings/Config/PowerConfig.swift index cf213f8e..9ba0fe0a 100644 --- a/Meshtastic/Views/Settings/Config/PowerConfig.swift +++ b/Meshtastic/Views/Settings/Config/PowerConfig.swift @@ -118,17 +118,6 @@ struct PowerConfig: View { .font(.subheadline) } } - .onAppear { - - // Need to request a Power config from the remote node before allowing changes - if bleManager.connectedPeripheral != nil && node?.powerConfig == nil { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) - if node != nil && connectedNode != nil { - _ = bleManager.requestPowerConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) - } - } - } - .onFirstAppear { Api().loadDeviceHardwareData { (hw) in for device in hw { @@ -144,15 +133,17 @@ struct PowerConfig: View { Logger.mesh.info("empty power config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.positionConfig == nil { - _ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.powerConfig == nil { + _ = bleManager.requestPowerConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + /// Legacy Administration + _ = bleManager.requestPowerConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } - } else { - /// Legacy Administration - _ = bleManager.requestPowerConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) } } } diff --git a/Meshtastic/Views/Settings/Config/SecurityConfig.swift b/Meshtastic/Views/Settings/Config/SecurityConfig.swift index 6388ea6e..e58de058 100644 --- a/Meshtastic/Views/Settings/Config/SecurityConfig.swift +++ b/Meshtastic/Views/Settings/Config/SecurityConfig.swift @@ -153,16 +153,18 @@ struct SecurityConfig: View { Logger.mesh.info("empty security config") let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context) if let connectedNode { - if UserDefaults.enableAdministration { - /// 2.5 Administration with session passkey - let expiration = node.sessionExpiration ?? Date() - if expiration < Date() || node.securityConfig == nil { - _ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) - } - } else { - if node.deviceConfig == nil { - /// Legacy Administration - _ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + if node.num != connectedNode.num { + if UserDefaults.enableAdministration { + /// 2.5 Administration with session passkey + let expiration = node.sessionExpiration ?? Date() + if expiration < Date() || node.securityConfig == nil { + _ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } else { + if node.deviceConfig == nil { + /// Legacy Administration + _ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } } } } diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index e88816ab..481fb29d 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -346,7 +346,7 @@ struct Settings: View { if bleManager.connectedPeripheral != nil { Section("Configure") { if node?.canRemoteAdmin ?? false { - Picker("Configuring Node", selection: $selectedNode) { + Picker("Node", selection: $selectedNode) { if selectedNode == 0 { Text("Connect to a Node").tag(0) } @@ -365,6 +365,7 @@ struct Settings: View { } icon: { Image(systemName: "av.remote") } + .font(.caption2) .tag(Int(node.num)) } else if !UserDefaults.enableAdministration && node.metadata != nil { /// Nodes using the old admin system Label { @@ -390,8 +391,7 @@ struct Settings: View { } } } - .pickerStyle(.automatic) - .labelsHidden() + .pickerStyle(.navigationLink) .onChange(of: selectedNode) { newValue in if selectedNode > 0 { let node = nodes.first(where: { $0.num == newValue }) From d8cb04ddcc7dd1aee7ddc1f0cdf1c9cb25c1d1cc Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 5 Sep 2024 19:38:28 -0700 Subject: [PATCH 11/11] Remove json logging --- Meshtastic/Helpers/BLEManager.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 11597647..87551c4f 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -766,7 +766,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate case .waypointApp: waypointPacket(packet: decodedInfo.packet, context: context) case .nodeinfoApp: - MeshLogger.log("🕸️ MESH PACKET received for Node Info App for PKI LOCK debugging \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure")") if !invalidVersion { upsertNodeInfoPacket(packet: decodedInfo.packet, context: context) } case .routingApp: if !invalidVersion { routingPacket(packet: decodedInfo.packet, connectedNodeNum: self.connectedPeripheral.num, context: context) }