diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 31.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 31.xcdatamodel/contents
index 9852b36b..16c3d91a 100644
--- a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 31.xcdatamodel/contents
+++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV 31.xcdatamodel/contents
@@ -189,6 +189,8 @@
+
+
diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift
index 41920890..f2933922 100644
--- a/Meshtastic/Persistence/UpdateCoreData.swift
+++ b/Meshtastic/Persistence/UpdateCoreData.swift
@@ -1119,6 +1119,9 @@ func upsertMqttModuleConfigPacket(config: Meshtastic.ModuleConfig.MQTTConfig, no
newMQTTConfig.encryptionEnabled = config.encryptionEnabled
newMQTTConfig.jsonEnabled = config.jsonEnabled
newMQTTConfig.tlsEnabled = config.tlsEnabled
+ newMQTTConfig.mapReportingEnabled = config.mapReportingEnabled
+ newMQTTConfig.mapPositionPrecision = Int32(config.mapReportSettings.positionPrecision)
+ newMQTTConfig.mapPublishIntervalSecs = Int32(config.mapReportSettings.publishIntervalSecs)
fetchedNode[0].mqttConfig = newMQTTConfig
} else {
fetchedNode[0].mqttConfig?.enabled = config.enabled
@@ -1130,6 +1133,9 @@ func upsertMqttModuleConfigPacket(config: Meshtastic.ModuleConfig.MQTTConfig, no
fetchedNode[0].mqttConfig?.encryptionEnabled = config.encryptionEnabled
fetchedNode[0].mqttConfig?.jsonEnabled = config.jsonEnabled
fetchedNode[0].mqttConfig?.tlsEnabled = config.tlsEnabled
+ fetchedNode[0].mqttConfig?.mapReportingEnabled = config.mapReportingEnabled
+ fetchedNode[0].mqttConfig?.mapPositionPrecision = Int32(config.mapReportSettings.positionPrecision)
+ fetchedNode[0].mqttConfig?.mapPublishIntervalSecs = Int32(config.mapReportSettings.publishIntervalSecs)
}
do {
try context.save()
diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift
index 8191aec9..10563eb3 100644
--- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift
+++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift
@@ -28,6 +28,12 @@ struct MQTTConfig: View {
@State var mqttConnected: Bool = false
@State var defaultTopic = "msh/US"
@State var nearbyTopics = [String]()
+ @State var mapReportingEnabled = false
+ @State var mapPublishIntervalSecs = 3600
+ @State var preciseLocation: Bool = false
+ @State var mapPositionPrecision: Double = 13.0
+
+
let locale = Locale.current
var body: some View {
@@ -58,7 +64,7 @@ struct MQTTConfig: View {
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
- if enabled && proxyToClientEnabled {
+ if enabled && proxyToClientEnabled && node!.mqttConfig!.proxyToClientEnabled == true {
Toggle(isOn: $mqttConnected) {
Label(mqttConnected ? "mqtt.disconnect".localized : "mqtt.connect".localized, systemImage: "server.rack")
}
@@ -75,14 +81,95 @@ struct MQTTConfig: View {
Text("JSON mode is a limited, unencrypted MQTT output for locally integrating with home assistant")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
+ }
+
+ Section(header: Text("Map Report")) {
- Toggle(isOn: $tlsEnabled) {
- Label("TLS Enabled", systemImage: "checkmark.shield.fill")
- Text("Your MQTT Server must support TLS.")
+ Toggle(isOn: $mapReportingEnabled) {
+ Label("enabled", systemImage: "map")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
-
+ if mapReportingEnabled {
+ Picker("Map Publish Interval", selection: $mapPublishIntervalSecs ) {
+ ForEach(UpdateIntervals.allCases) { ui in
+ if ui.rawValue >= 3600 {
+ Text(ui.description)
+ }
+ }
+ }
+ .pickerStyle(DefaultPickerStyle())
+
+ VStack(alignment: .leading) {
+ Toggle(isOn: $preciseLocation) {
+ Label("Precise Location", systemImage: "scope")
+ }
+ .toggleStyle(SwitchToggleStyle(tint: .accentColor))
+ .listRowSeparator(.visible)
+ .onChange(of: preciseLocation) { pl in
+ if pl == false {
+ mapPositionPrecision = 12
+ } else {
+ mapPositionPrecision = 32
+ }
+ }
+ }
+
+ if !preciseLocation {
+ VStack(alignment: .leading) {
+ Label("Approximate Location", systemImage: "location.slash.circle.fill")
+ Slider(value: $mapPositionPrecision, in: 11...16, step: 1) {
+ } minimumValueLabel: {
+ Image(systemName: "minus")
+ } maximumValueLabel: {
+ Image(systemName: "plus")
+ }
+ Text(PositionPrecision(rawValue: Int(mapPositionPrecision))?.description ?? "")
+ .foregroundColor(.gray)
+ .font(.callout)
+ }
+ }
+ }
}
+ Section(header: Text("Root Topic")) {
+ HStack {
+ Label("Root Topic", systemImage: "tree")
+ TextField("Root Topic", text: $root)
+ .foregroundColor(.gray)
+ .onChange(of: root, perform: { _ in
+ let totalBytes = root.utf8.count
+ // Only mess with the value if it is too big
+ if totalBytes > 30 {
+ let firstNBytes = Data(root.utf8.prefix(30))
+ 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
+ }
+ }
+ })
+ .foregroundColor(.gray)
+ }
+ .keyboardType(.asciiCapable)
+ .scrollDismissesKeyboard(.interactively)
+ .disableAutocorrection(true)
+ .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)
+ }
+ }
+
Section(header: Text("Server")) {
HStack {
Label("Address", systemImage: "server.rack")
@@ -161,45 +248,13 @@ 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)
- .foregroundColor(.gray)
- .onChange(of: root, perform: { _ in
- let totalBytes = root.utf8.count
- // Only mess with the value if it is too big
- if totalBytes > 30 {
- let firstNBytes = Data(root.utf8.prefix(30))
- 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
- }
- }
- })
- .foregroundColor(.gray)
- }
- .keyboardType(.asciiCapable)
- .scrollDismissesKeyboard(.interactively)
- .disableAutocorrection(true)
- .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)
+ Toggle(isOn: $tlsEnabled) {
+ Label("TLS Enabled", systemImage: "checkmark.shield.fill")
+ Text("Your MQTT Server must support TLS.")
}
+ .toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
- Text("You can set uplink and downlink for each channel.")
+ Text("For all Mqtt functionality other than the map report you must also set uplink and downlink for each channel you want to brige over Mqtt.")
.font(.callout)
}
.scrollDismissesKeyboard(.interactively)
@@ -219,6 +274,9 @@ struct MQTTConfig: View {
mqtt.encryptionEnabled = self.encryptionEnabled
mqtt.jsonEnabled = self.jsonEnabled
mqtt.tlsEnabled = self.tlsEnabled
+ mqtt.mapReportingEnabled = self.mapReportingEnabled
+ mqtt.mapReportSettings.positionPrecision = UInt32(self.mapPositionPrecision)
+ mqtt.mapReportSettings.publishIntervalSecs = UInt32(self.mapPublishIntervalSecs)
let adminMessageId = bleManager.saveMQTTConfig(config: mqtt, 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
@@ -233,20 +291,6 @@ struct MQTTConfig: View {
ZStack {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?", mqttProxyConnected: bleManager.mqttProxyConnected)
})
- .onAppear {
- if self.bleManager.context == nil {
- self.bleManager.context = context
- }
- setMqttValues()
- // Need to request a TelemetryModuleConfig from the remote node before allowing changes
- if bleManager.connectedPeripheral != nil && node?.mqttConfig == nil {
- print("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)
- }
- }
- }
.onChange(of: address) { newAddress in
if node != nil && node?.mqttConfig != nil {
if newAddress != node!.mqttConfig!.address { hasChanges = true }
@@ -315,6 +359,33 @@ struct MQTTConfig: View {
}
}
}
+ .onChange(of: mapReportingEnabled) { newMapReportingEnabled in
+ if node != nil && node?.mqttConfig != nil {
+ if newMapReportingEnabled != node!.mqttConfig!.mapReportingEnabled { hasChanges = true }
+ }
+ }
+ .onChange(of: preciseLocation) { _ in
+ hasChanges = true
+ }
+ .onChange(of: mapPublishIntervalSecs) { newMapPublishIntervalSecs in
+ if node != nil && node?.mqttConfig != nil {
+ if newMapPublishIntervalSecs != node!.mqttConfig!.mapPublishIntervalSecs { hasChanges = true }
+ }
+ }
+ .onAppear {
+ if self.bleManager.context == nil {
+ self.bleManager.context = context
+ }
+ setMqttValues()
+ // Need to request a TelemetryModuleConfig from the remote node before allowing changes
+ if bleManager.connectedPeripheral != nil && node?.mqttConfig == nil {
+ print("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)
+ }
+ }
+ }
}
func setMqttValues() {
@@ -367,16 +438,23 @@ struct MQTTConfig: View {
})
}
}
- self.enabled = (node?.mqttConfig?.enabled ?? false)
- self.proxyToClientEnabled = (node?.mqttConfig?.proxyToClientEnabled ?? false)
+ self.enabled = node?.mqttConfig?.enabled ?? false
+ self.proxyToClientEnabled = node?.mqttConfig?.proxyToClientEnabled ?? false
self.address = node?.mqttConfig?.address ?? ""
self.username = node?.mqttConfig?.username ?? ""
self.password = node?.mqttConfig?.password ?? ""
self.root = node?.mqttConfig?.root ?? "msh"
- self.encryptionEnabled = (node?.mqttConfig?.encryptionEnabled ?? false)
- self.jsonEnabled = (node?.mqttConfig?.jsonEnabled ?? false)
- self.tlsEnabled = (node?.mqttConfig?.tlsEnabled ?? false)
+ self.encryptionEnabled = node?.mqttConfig?.encryptionEnabled ?? false
+ self.jsonEnabled = node?.mqttConfig?.jsonEnabled ?? false
+ self.tlsEnabled = node?.mqttConfig?.tlsEnabled ?? false
self.mqttConnected = bleManager.mqttProxyConnected
+ self.mapReportingEnabled = node?.mqttConfig?.mapReportingEnabled ?? false
+ self.mapPublishIntervalSecs = Int(node?.mqttConfig?.mapPublishIntervalSecs ?? 3600)
+ self.mapPositionPrecision = Double(node?.mqttConfig?.mapPositionPrecision ?? 12)
+ if mapPositionPrecision == 0.0 {
+ self.mapPositionPrecision = 12
+ }
+ self.preciseLocation = mapPositionPrecision == 32
self.hasChanges = false
}
}