diff --git a/Localizable.xcstrings b/Localizable.xcstrings index eb4cd488..66552059 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -6366,6 +6366,9 @@ } } } + }, + "Currently showing modules that may not be supported by this node." : { + }, "Currently the recommended way to update ESP32 devices is using the web flasher on a desktop computer from a chrome based browser. It does not work on mobile devices or over BLE." : { "localizations" : { @@ -30358,6 +30361,9 @@ } } } + }, + "This node does not support any configurable modules." : { + }, "This will disable fixed position and remove the currently set position." : { "localizations" : { diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index b6c8db17..a52580df 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -226,6 +226,7 @@ func deviceMetadataPacket (metadata: DeviceMetadata, fromNum: Int64, sessionPass newMetadata.hasEthernet = metadata.hasEthernet_p newMetadata.role = Int32(metadata.role.rawValue) newMetadata.positionFlags = Int32(metadata.positionFlags) + newMetadata.excludedModules = Int32(metadata.excludedModules) // Swift does strings weird, this does work to get the version without the github hash let lastDotIndex = metadata.firmwareVersion.lastIndex(of: ".") var version = metadata.firmwareVersion[...(lastDotIndex ?? String.Index(utf16Offset: 6, in: metadata.firmwareVersion))] diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 50.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 50.xcdatamodel/contents index 3eb01148..9578507a 100644 --- a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 50.xcdatamodel/contents +++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 50.xcdatamodel/contents @@ -76,6 +76,7 @@ + diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 8e0dcfc3..28a69c92 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -8,6 +8,7 @@ import SwiftUI import OSLog import TipKit +import MeshtasticProtobufs struct Settings: View { @Environment(\.managedObjectContext) var context @@ -25,10 +26,21 @@ struct Settings: View { @State private var selectedNode: Int = 0 @State private var preferredNodeNum: Int = 0 + @State private var moduleOverride: Bool = false @ObservedObject var router: Router + // MARK: Helper + + private func isModuleSupported(_ module: ExcludedModules) -> Bool { + return moduleOverride || Int(nodes.first(where: { $0.num == preferredNodeNum })?.metadata?.excludedModules ?? Int32.zero) & module.rawValue == 0 + } + + private func isAnySupported(_ modules: [ExcludedModules]) -> Bool { + return modules.map(isModuleSupported).contains(true) + } + // MARK: Views var radioConfigurationSection: some View { @@ -153,57 +165,70 @@ struct Settings: View { } var moduleConfigurationSection: some View { - Section("module.configuration") { - NavigationLink(value: SettingsNavigationState.ambientLighting) { - Label { - Text("Ambient Lighting") - } icon: { - Image(systemName: "light.max") + Section { + if isModuleSupported(.ambientlightingConfig) { + NavigationLink(value: SettingsNavigationState.ambientLighting) { + Label { + Text("Ambient Lighting") + } icon: { + Image(systemName: "light.max") + } } } - NavigationLink(value: SettingsNavigationState.cannedMessages) { - Label { - Text("Canned Messages") - } icon: { - Image(systemName: "list.bullet.rectangle.fill") + if isModuleSupported(.cannedmsgConfig) { + NavigationLink(value: SettingsNavigationState.cannedMessages) { + Label { + Text("Canned Messages") + } icon: { + Image(systemName: "list.bullet.rectangle.fill") + } } } - NavigationLink(value: SettingsNavigationState.detectionSensor) { - Label { - Text("detection.sensor") - } icon: { - Image(systemName: "sensor") - } - } - - NavigationLink(value: SettingsNavigationState.externalNotification) { - Label { - Text("external.notification") - } icon: { - Image(systemName: "megaphone") - } - } - - NavigationLink(value: SettingsNavigationState.mqtt) { - Label { - Text("mqtt") - } icon: { - Image(systemName: "dot.radiowaves.up.forward") - } - } - - NavigationLink(value: SettingsNavigationState.rangeTest) { - Label { - Text("range.test") - } icon: { - Image(systemName: "point.3.connected.trianglepath.dotted") + if isModuleSupported(.detectionsensorConfig) { + NavigationLink(value: SettingsNavigationState.detectionSensor) { + Label { + Text("detection.sensor") + } icon: { + Image(systemName: "sensor") + } } } if let node = nodes.first(where: { $0.num == preferredNodeNum }), - node.metadata?.hasWifi ?? false { + node.metadata?.hasWifi ?? false, isModuleSupported(.extnotifConfig) { + NavigationLink(value: SettingsNavigationState.externalNotification) { + Label { + Text("external.notification") + } icon: { + Image(systemName: "megaphone") + } + } + } + + if isModuleSupported(.mqttConfig) { + NavigationLink(value: SettingsNavigationState.mqtt) { + Label { + Text("mqtt") + } icon: { + Image(systemName: "dot.radiowaves.up.forward") + } + } + } + + if isModuleSupported(.rangetestConfig) { + NavigationLink(value: SettingsNavigationState.rangeTest) { + Label { + Text("range.test") + } icon: { + Image(systemName: "point.3.connected.trianglepath.dotted") + } + } + } + + if let node = nodes.first(where: { $0.num == preferredNodeNum }), + node.metadata?.hasWifi ?? false, isModuleSupported(.paxcounterConfig) { NavigationLink(value: SettingsNavigationState.paxCounter) { Label { Text("config.module.paxcounter.settings") @@ -213,37 +238,62 @@ struct Settings: View { } } - NavigationLink(value: SettingsNavigationState.ringtone) { - Label { - Text("ringtone") - } icon: { - Image(systemName: "music.note.list") + if isModuleSupported(.audioConfig) { + NavigationLink(value: SettingsNavigationState.ringtone) { + Label { + Text("ringtone") + } icon: { + Image(systemName: "music.note.list") + } } } - NavigationLink(value: SettingsNavigationState.serial) { - Label { - Text("serial") - } icon: { - Image(systemName: "terminal") + if let node = nodes.first(where: { $0.num == preferredNodeNum }), + node.metadata?.hasWifi ?? false, isModuleSupported(.serialConfig) { + NavigationLink(value: SettingsNavigationState.serial) { + Label { + Text("serial") + } icon: { + Image(systemName: "terminal") + } } } - NavigationLink(value: SettingsNavigationState.storeAndForward) { - Label { - Text("Store & Forward") - } icon: { - Image(systemName: "envelope.arrow.triangle.branch") + if isModuleSupported(.storeforwardConfig) { + NavigationLink(value: SettingsNavigationState.storeAndForward) { + Label { + Text("Store & Forward") + } icon: { + Image(systemName: "envelope.arrow.triangle.branch") + } } } - NavigationLink(value: SettingsNavigationState.telemetry) { - Label { - Text("telemetry") - } icon: { - Image(systemName: "chart.xyaxis.line") + if isModuleSupported(.telemetryConfig) { + NavigationLink(value: SettingsNavigationState.telemetry) { + Label { + Text("telemetry") + } icon: { + Image(systemName: "chart.xyaxis.line") + } } } + + // Update this list with the modules that are shown above. If all are not supported + // Then show a message. + if !isAnySupported([.ambientlightingConfig, .cannedmsgConfig, + .detectionsensorConfig, .extnotifConfig, + .mqttConfig, .rangetestConfig, .paxcounterConfig, + .audioConfig, .serialConfig, .storeforwardConfig, + .telemetryConfig]) { + Text("This node does not support any configurable modules.") + } + } header: { + Text("module.configuration") + } footer: { + if moduleOverride { + Text("Currently showing modules that may not be supported by this node.") + } } } @@ -497,7 +547,10 @@ struct Settings: View { } .navigationTitle("settings") .navigationBarItems( - leading: MeshtasticLogo() + leading: MeshtasticLogo().onLongPressGesture(minimumDuration: 1.0) { + self.moduleOverride.toggle() + UIImpactFeedbackGenerator(style: .medium).impactOccurred() + } ) } }