diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index e3fc9e1e..4a34a19a 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -280,6 +280,7 @@ DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionConfigEnums.swift; sourceTree = ""; }; DDB6ABE328B13FFF00384BA1 /* DisplayEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayEnums.swift; sourceTree = ""; }; DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoraConfigEnums.swift; sourceTree = ""; }; + DDB759E12A04B264006ED576 /* MeshtasticDataModelV12.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV12.xcdatamodel; sourceTree = ""; }; DDBA45EC299ED78100DEEDDC /* MeshtasticDataModelV8.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV8.xcdatamodel; sourceTree = ""; }; DDC2E15426CE248E0042C5E4 /* Meshtastic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Meshtastic.app; sourceTree = BUILT_PRODUCTS_DIR; }; DDC2E15726CE248E0042C5E4 /* MeshtasticApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticApp.swift; sourceTree = ""; }; @@ -1545,6 +1546,7 @@ DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + DDB759E12A04B264006ED576 /* MeshtasticDataModelV12.xcdatamodel */, DDDEE5E229DBE43E00A8E078 /* MeshtasticDataModelV11.xcdatamodel */, DDC94FC329CED7280082EA6E /* MeshtasticDataModelV10.xcdatamodel */, DDDD527729B5B83F0045BC3C /* MeshtasticDataModelV9.xcdatamodel */, @@ -1557,7 +1559,7 @@ DD5D0A9A2931AD6B00F7EA61 /* MeshtasticDataModelV2.xcdatamodel */, DD3CC6BB28E366DF00FA9159 /* MeshtasticDataModel.xcdatamodel */, ); - currentVersion = DDDEE5E229DBE43E00A8E078 /* MeshtasticDataModelV11.xcdatamodel */; + currentVersion = DDB759E12A04B264006ED576 /* MeshtasticDataModelV12.xcdatamodel */; name = Meshtastic.xcdatamodeld; path = Meshtastic/Meshtastic.xcdatamodeld; sourceTree = ""; diff --git a/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion b/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion index f9b5a5e7..cfa704c4 100644 --- a/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion +++ b/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - MeshtasticDataModelV11.xcdatamodel + MeshtasticDataModelV12.xcdatamodel diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV12.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV12.xcdatamodel/contents new file mode 100644 index 00000000..7110885f --- /dev/null +++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV12.xcdatamodel/contents @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index c1f5c1b8..0a4b06a3 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -775,16 +775,20 @@ func upsertMqttModuleConfigPacket(config: Meshtastic.ModuleConfig.MQTTConfig, no newMQTTConfig.address = config.address newMQTTConfig.username = config.username newMQTTConfig.password = config.password + newMQTTConfig.root = config.root newMQTTConfig.encryptionEnabled = config.encryptionEnabled newMQTTConfig.jsonEnabled = config.jsonEnabled + newMQTTConfig.tlsEnabled = config.tlsEnabled fetchedNode[0].mqttConfig = newMQTTConfig } else { fetchedNode[0].mqttConfig?.enabled = config.enabled fetchedNode[0].mqttConfig?.address = config.address fetchedNode[0].mqttConfig?.username = config.username fetchedNode[0].mqttConfig?.password = config.password + fetchedNode[0].mqttConfig?.root = config.root fetchedNode[0].mqttConfig?.encryptionEnabled = config.encryptionEnabled fetchedNode[0].mqttConfig?.jsonEnabled = config.jsonEnabled + fetchedNode[0].mqttConfig?.tlsEnabled = config.tlsEnabled } do { try context.save() diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index 4cefda0c..fd7078b8 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -20,6 +20,9 @@ struct MQTTConfig: View { @State var password = "" @State var encryptionEnabled = false @State var jsonEnabled = false + @State var tlsEnabled = true + @State var root = "msh" + var body: some View { @@ -63,11 +66,18 @@ struct MQTTConfig: View { } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + Toggle(isOn: $tlsEnabled) { + + Label("TLS Enabled", systemImage: "checkmark.shield.fill") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) Toggle(isOn: $jsonEnabled) { Label("JSON Enabled", systemImage: "ellipsis.curlybraces") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + Text("JSON mode is not reccomended it is incomplete and unstable.") + .font(.caption2) } Section(header: Text("Custom Server")) { HStack { @@ -147,6 +157,29 @@ struct MQTTConfig: View { } .keyboardType(.default) .scrollDismissesKeyboard(.interactively) + + 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 > 14 { + let firstNBytes = Data(root.utf8.prefix(14)) + 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) + 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") + .font(.caption2) } Text("WiFi or Ethernet must also be enabled for MQTT to work. You can set uplink and downlink for each channel.") .font(.callout) @@ -179,8 +212,10 @@ struct MQTTConfig: View { mqtt.address = self.address mqtt.username = self.username mqtt.password = self.password + mqtt.root = self.root mqtt.encryptionEnabled = self.encryptionEnabled mqtt.jsonEnabled = self.jsonEnabled + mqtt.tlsEnabled = self.tlsEnabled 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 @@ -212,6 +247,26 @@ struct MQTTConfig: View { } } } + .onChange(of: address) { newAddress in + if node != nil && node?.mqttConfig != nil { + if newAddress != node!.mqttConfig!.address { hasChanges = true } + } + } + .onChange(of: username) { newUsername in + if node != nil && node?.mqttConfig != nil { + if newUsername != node!.mqttConfig!.username { hasChanges = true } + } + } + .onChange(of: password) { newPassword in + if node != nil && node?.mqttConfig != nil { + if newPassword != node!.mqttConfig!.password { hasChanges = true } + } + } + .onChange(of: root) { newRoot in + if node != nil && node?.mqttConfig != nil { + if newRoot != node!.mqttConfig!.root { hasChanges = true } + } + } .onChange(of: enabled) { newEnabled in if node != nil && node?.mqttConfig != nil { if newEnabled != node!.mqttConfig!.enabled { hasChanges = true } @@ -227,6 +282,11 @@ struct MQTTConfig: View { if newJsonEnabled != node!.mqttConfig!.jsonEnabled { hasChanges = true } } } + .onChange(of: tlsEnabled) { newTlsEnabled in + if node != nil && node?.mqttConfig != nil { + if newTlsEnabled != node!.mqttConfig!.tlsEnabled { hasChanges = true } + } + } } func setMqttValues() { @@ -234,8 +294,10 @@ struct MQTTConfig: View { 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.hasChanges = false } }