diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 6cf4d0e2..a0beff25 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -1572,7 +1572,7 @@ CODE_SIGN_ENTITLEMENTS = Meshtastic/Meshtastic.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 842; + CURRENT_PROJECT_VERSION = 843; DEVELOPMENT_ASSET_PATHS = "\"Meshtastic/Preview Content\""; DEVELOPMENT_TEAM = GCH7VS5Y9R; ENABLE_PREVIEWS = YES; @@ -1606,7 +1606,7 @@ CODE_SIGN_ENTITLEMENTS = Meshtastic/Meshtastic.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 842; + CURRENT_PROJECT_VERSION = 843; DEVELOPMENT_ASSET_PATHS = "\"Meshtastic/Preview Content\""; DEVELOPMENT_TEAM = GCH7VS5Y9R; ENABLE_PREVIEWS = YES; diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index abf933a6..8fcc31cb 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -209,7 +209,7 @@ struct Connect: View { }.padding([.bottom, .top]) } } - .confirmationDialog("Connecting to a new radio will clear all local app data on the phone and will reset all app settings.", isPresented: $presentingSwitchPreferredPeripheral, titleVisibility: .visible) { + .confirmationDialog("Connecting to a new radio will clear all local app data on the phone and will reset all app specific settings.", isPresented: $presentingSwitchPreferredPeripheral, titleVisibility: .visible) { Button("Connect to new radio?", role: .destructive) { UserDefaults.preferredPeripheralId = selectedPeripherialId diff --git a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift index 4ffdffca..871c54af 100644 --- a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift +++ b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift @@ -202,6 +202,8 @@ struct NodeListItem: View { } } } - .padding([.top, .bottom]) + .padding(.top, 4) + .padding(.bottom, 4) + //.padding([.top, .bottom]) } } diff --git a/Meshtastic/Views/Settings/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index 3ca281c2..e9a0f352 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -181,7 +181,7 @@ struct LoRaConfig: View { HStack { Image(systemName: "antenna.radiowaves.left.and.right") .foregroundColor(.accentColor) - Stepper("\(txPower)db Transmit Power", value: $txPower, in: 1...30, step: 1) + Stepper("\(txPower)dBm Transmit Power", value: $txPower, in: 1...30, step: 1) .padding(5) } } diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index 8136e865..2ce168ac 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -5,6 +5,7 @@ // Copyright (c) Garth Vander Houwen 9/4/22. // import SwiftUI +import CoreLocation struct MQTTConfig: View { @@ -23,9 +24,9 @@ struct MQTTConfig: View { @State var jsonEnabled = false @State var tlsEnabled = true @State var root = "msh" + @State var selectedTopic = "" @State var mqttConnected: Bool = false - - + @State var nearbyTopics = [String]() var body: some View { VStack { @@ -51,7 +52,7 @@ struct MQTTConfig: View { Toggle(isOn: $proxyToClientEnabled) { Label("mqtt.clientproxy", systemImage: "iphone.radiowaves.left.and.right") - Text("If both MQTT and the client proxy are enabled your mobile device will utilize an available network connection to connect to the specified MQTT server.") + Text("Utilizes the network connection on your phone to connect to MQTT.") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) @@ -69,7 +70,7 @@ struct MQTTConfig: View { Toggle(isOn: $jsonEnabled) { Label("JSON Enabled", systemImage: "ellipsis.curlybraces") - Text("JSON mode is a limited, unencrypted MQTT output that can crash your node it should not be enabled unless you are locally integrating with home assistant") + Text("JSON mode is a limited, unencrypted MQTT output for locally integrating with home assistant") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) @@ -80,7 +81,7 @@ struct MQTTConfig: View { .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } - Section(header: Text("Custom Server")) { + Section(header: Text("Server")) { HStack { Label("Address", systemImage: "server.rack") TextField("Server Address", text: $address) @@ -157,6 +158,7 @@ struct MQTTConfig: View { } .keyboardType(.default) .scrollDismissesKeyboard(.interactively) + .listRowSeparator(/*@START_MENU_TOKEN@*/.visible/*@END_MENU_TOKEN@*/) HStack { Label("Root Topic", systemImage: "tree") TextField("Root Topic", text: $root) @@ -164,8 +166,8 @@ struct MQTTConfig: View { .onChange(of: root, perform: { _ in let totalBytes = root.utf8.count // Only mess with the value if it is too big - if totalBytes > 14 { - let firstNBytes = Data(root.utf8.prefix(14)) + if totalBytes > 15 { + let firstNBytes = Data(root.utf8.prefix(15)) if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) { // Set the shortName back to the last place where it was the right size root = maxBytesString @@ -177,9 +179,23 @@ struct MQTTConfig: View { .keyboardType(.asciiCapable) .scrollDismissesKeyboard(.interactively) .disableAutocorrection(true) - Text("The root topic to use for MQTT messages. Default is \"msh\". This is useful if you want to use a single MQTT server for multiple meshtastic networks and separate them via ACLs") + .listRowSeparator(.hidden) + Text("The root topic to use for MQTT.") .foregroundColor(.gray) .font(.callout) + + if nearbyTopics.count > 0 { + Picker("Nearby Topics", selection: $selectedTopic ) { + ForEach(nearbyTopics, id: \.self) { nt in + Text(nt) + } + } + .pickerStyle(InlinePickerStyle()) + .listRowSeparator(.hidden) + Text("If the default region topic is too busy you can choose a more local topic.") + .foregroundColor(.gray) + .font(.callout) + } } Text("You can set uplink and downlink for each channel.") .font(.callout) @@ -249,6 +265,9 @@ struct MQTTConfig: View { if newRoot != node!.mqttConfig!.root { hasChanges = true } } } + .onChange(of: selectedTopic) { newSelectedTopic in + root = newSelectedTopic + } .onChange(of: enabled) { newEnabled in if node != nil && node?.mqttConfig != nil { if newEnabled != node!.mqttConfig!.enabled { hasChanges = true } @@ -290,6 +309,52 @@ struct MQTTConfig: View { } } func setMqttValues() { + + if #available(iOS 17.0, macOS 14.0, *) { + + nearbyTopics = [] + let geocoder = CLGeocoder() + if LocationsHandler.shared.locationsArray.count > 0 { + geocoder.reverseGeocodeLocation(LocationsHandler.shared.locationsArray.first!, completionHandler: {(placemarks, error) -> Void in + if error != nil { + print("Failed to reverse geocode location") + return + } + + if let placemarks = placemarks, let placemark = placemarks.first { + + /// Country Topic unless you are US + if placemark.isoCountryCode ?? "unknown" != "US" { + let countryTopic = root + "/" + (placemark.isoCountryCode ?? "") + if !countryTopic.isEmpty { + nearbyTopics.append(countryTopic) + } + } + let stateTopic = root + "/" + (placemark.administrativeArea ?? "") + if !stateTopic.isEmpty { + nearbyTopics.append(stateTopic) + } + let countyTopic = root + "/" + (placemark.subAdministrativeArea?.lowercased().replacingOccurrences(of: " ", with: "") ?? "") + if !countyTopic.isEmpty { + nearbyTopics.append(countyTopic) + } + let cityTopic = root + "/" + (placemark.locality?.lowercased().replacingOccurrences(of: " ", with: "") ?? "") + if !cityTopic.isEmpty { + nearbyTopics.append(cityTopic) + } + let neightborhoodTopic = root + "/" + (placemark.subLocality?.lowercased().replacingOccurrences(of: " ", with: "") ?? "") + if !neightborhoodTopic.isEmpty { + nearbyTopics.append(neightborhoodTopic) + } + + } + else + { + print("No Location") + } + }) + } + } self.enabled = (node?.mqttConfig?.enabled ?? false) self.proxyToClientEnabled = (node?.mqttConfig?.proxyToClientEnabled ?? false) self.address = node?.mqttConfig?.address ?? ""