From ac37e6a28fe0cc6d25f1d67c4ef75e9eb73bbea1 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 2 Apr 2025 07:26:29 -0700 Subject: [PATCH 1/8] Add SVG files for think node m1 and M2 fix power metrick strings --- Localizable.xcstrings | 10 - Meshtastic.xcodeproj/project.pbxproj | 8 +- .../THINKNODEM1.imageset/Contents.json | 12 + .../THINKNODEM1.imageset/thinknode_m1.svg | 109 +++++ .../THINKNODEM2.imageset/Contents.json | 12 + .../THINKNODEM2.imageset/thinknode_m2.svg | 391 ++++++++++++++++++ Meshtastic/Resources/DeviceHardware.json | 17 +- 7 files changed, 540 insertions(+), 19 deletions(-) create mode 100644 Meshtastic/Assets.xcassets/THINKNODEM1.imageset/Contents.json create mode 100644 Meshtastic/Assets.xcassets/THINKNODEM1.imageset/thinknode_m1.svg create mode 100644 Meshtastic/Assets.xcassets/THINKNODEM2.imageset/Contents.json create mode 100644 Meshtastic/Assets.xcassets/THINKNODEM2.imageset/thinknode_m2.svg diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 08f7b2ae..43a11bb0 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -23158,16 +23158,6 @@ } }, "Power Metrics Log" : { - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Логови метрике снаге" - } - } - } - }, - "Power Metrics Log}" : { "localizations" : { "sr" : { "stringUnit" : { diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 58e2baa5..a1f44726 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -1805,7 +1805,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.5.22; + MARKETING_VERSION = 2.5.23; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1839,7 +1839,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.5.22; + MARKETING_VERSION = 2.5.23; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1871,7 +1871,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.5.22; + MARKETING_VERSION = 2.5.23; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1904,7 +1904,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.5.22; + MARKETING_VERSION = 2.5.23; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Meshtastic/Assets.xcassets/THINKNODEM1.imageset/Contents.json b/Meshtastic/Assets.xcassets/THINKNODEM1.imageset/Contents.json new file mode 100644 index 00000000..7001ca9b --- /dev/null +++ b/Meshtastic/Assets.xcassets/THINKNODEM1.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "thinknode_m1.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Meshtastic/Assets.xcassets/THINKNODEM1.imageset/thinknode_m1.svg b/Meshtastic/Assets.xcassets/THINKNODEM1.imageset/thinknode_m1.svg new file mode 100644 index 00000000..27e21a0b --- /dev/null +++ b/Meshtastic/Assets.xcassets/THINKNODEM1.imageset/thinknode_m1.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Meshtastic/Assets.xcassets/THINKNODEM2.imageset/Contents.json b/Meshtastic/Assets.xcassets/THINKNODEM2.imageset/Contents.json new file mode 100644 index 00000000..81ee0ac1 --- /dev/null +++ b/Meshtastic/Assets.xcassets/THINKNODEM2.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "thinknode_m2.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Meshtastic/Assets.xcassets/THINKNODEM2.imageset/thinknode_m2.svg b/Meshtastic/Assets.xcassets/THINKNODEM2.imageset/thinknode_m2.svg new file mode 100644 index 00000000..5e5a0e3c --- /dev/null +++ b/Meshtastic/Assets.xcassets/THINKNODEM2.imageset/thinknode_m2.svg @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Meshtastic/Resources/DeviceHardware.json b/Meshtastic/Resources/DeviceHardware.json index 00b80aea..bbe99f2a 100644 --- a/Meshtastic/Resources/DeviceHardware.json +++ b/Meshtastic/Resources/DeviceHardware.json @@ -543,7 +543,7 @@ "images": [ "t-watch-s3.svg" ], - "partitionScheme": "16MB" + "partitionScheme": "8MB" }, { "hwModel": 52, @@ -845,25 +845,32 @@ "hwModelSlug": "THINKNODE_M1", "platformioTarget": "thinknode_m1", "architecture": "nrf52840", - "activelySupported": false, + "activelySupported": true, "supportLevel": 1, "displayName": "ThinkNode M1", "tags": [ "Elecrow" ], - "requiresDfu": true + "requiresDfu": true, + "images": [ + "thinknode_m1.svg" + ], + "hasInkHud": true }, { "hwModel": 90, "hwModelSlug": "THINKNODE_M2", "platformioTarget": "thinknode_m2", "architecture": "esp32-s3", - "activelySupported": false, + "activelySupported": true, "supportLevel": 1, "displayName": "ThinkNode M2", "tags": [ "Elecrow" ], - "requiresDfu": false + "requiresDfu": false, + "images": [ + "thinknode_m2.svg" + ] } ] From 2db3883ce1b387f9cc04bf6cae71849743099daf Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 2 Apr 2025 15:30:53 -0700 Subject: [PATCH 2/8] Add SVG for XIAO NRF kit --- .../XIAONRF52KIT.imageset/Contents.json | 12 ++++++++++++ .../XIAONRF52KIT.imageset/seeed_xiao_nrf52_kit.svg | 1 + 2 files changed, 13 insertions(+) create mode 100644 Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/Contents.json create mode 100644 Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/seeed_xiao_nrf52_kit.svg diff --git a/Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/Contents.json b/Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/Contents.json new file mode 100644 index 00000000..08990d2d --- /dev/null +++ b/Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "seeed_xiao_nrf52_kit.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/seeed_xiao_nrf52_kit.svg b/Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/seeed_xiao_nrf52_kit.svg new file mode 100644 index 00000000..95f7211b --- /dev/null +++ b/Meshtastic/Assets.xcassets/XIAONRF52KIT.imageset/seeed_xiao_nrf52_kit.svg @@ -0,0 +1 @@ + \ No newline at end of file From 114f3c35cc5cf5e9b43ee7e586d32907b1c813a4 Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Fri, 18 Apr 2025 13:09:18 -0700 Subject: [PATCH 3/8] Fixed transparent tab view --- Meshtastic/Views/ContentView.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Meshtastic/Views/ContentView.swift b/Meshtastic/Views/ContentView.swift index d6b2fd6b..50734893 100644 --- a/Meshtastic/Views/ContentView.swift +++ b/Meshtastic/Views/ContentView.swift @@ -11,6 +11,12 @@ struct ContentView: View { @ObservedObject var router: Router + init(appState: AppState, router: Router) { + self.appState = appState + self.router = router + UITabBar.appearance().scrollEdgeAppearance = UITabBarAppearance(idiom: .unspecified) + } + var body: some View { TabView(selection: $appState.router.navigationState.selectedTab) { Messages( From dc00d8d118c18f88967d769934541710123cdd9d Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 19 Apr 2025 06:49:15 -0500 Subject: [PATCH 4/8] Add delegate to fix tls issues with cocoamqtt --- Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift index cac34de8..1fa45f2e 100644 --- a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift +++ b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift @@ -40,8 +40,8 @@ class MqttClientProxyManager { if let host = host { let port = defaultServerPort - var username = node.mqttConfig?.username - var password = node.mqttConfig?.password + let username = node.mqttConfig?.username + let password = node.mqttConfig?.password // if host == defaultServerAddress { //username = ProcessInfo.processInfo.environment["PUBLIC_MQTT_USERNAME"] //password = ProcessInfo.processInfo.environment["PUBLIC_MQTT_PASSWORD"] @@ -130,6 +130,9 @@ extension MqttClientProxyManager: CocoaMQTTDelegate { self.disconnect() } } + func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) { + completionHandler(true) + } func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) { Logger.mqtt.debug("📲 [MQTT Client Proxy] disconnected: \(err?.localizedDescription ?? "", privacy: .public)") if let error = err { From 5e6486b8d4f8c4634b42f078605cf52e3762047e Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 19 Apr 2025 07:06:56 -0500 Subject: [PATCH 5/8] Update Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Helpers/Mqtt/MqttClientProxyManager.swift | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift index 1fa45f2e..450dbc52 100644 --- a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift +++ b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift @@ -131,8 +131,24 @@ extension MqttClientProxyManager: CocoaMQTTDelegate { } } func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) { - completionHandler(true) + var isValid = false + #if canImport(Security) + if #available(macOS 10.15, iOS 13.0, *) { + isValid = SecTrustEvaluateWithError(trust, nil) + } else { + var result: SecTrustResultType = .invalid + let status = SecTrustEvaluate(trust, &result) + isValid = (status == errSecSuccess) && (result == .unspecified || result == .proceed) } + #endif + if isValid { + Logger.mqtt.info("📲 [MQTT Client Proxy] TLS validation succeeded.") + completionHandler(true) + } else { + Logger.mqtt.error("📲 [MQTT Client Proxy] TLS validation failed.") + completionHandler(false) + } + } func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) { Logger.mqtt.debug("📲 [MQTT Client Proxy] disconnected: \(err?.localizedDescription ?? "", privacy: .public)") if let error = err { From d4ece62cce1bfd0b6654a89d0ac9c5c3d3e39b3f Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 19 Apr 2025 07:09:08 -0500 Subject: [PATCH 6/8] Complete anyway --- Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift index 450dbc52..569379b5 100644 --- a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift +++ b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift @@ -145,8 +145,8 @@ extension MqttClientProxyManager: CocoaMQTTDelegate { Logger.mqtt.info("📲 [MQTT Client Proxy] TLS validation succeeded.") completionHandler(true) } else { - Logger.mqtt.error("📲 [MQTT Client Proxy] TLS validation failed.") - completionHandler(false) + Logger.mqtt.warning("📲 [MQTT Client Proxy] TLS validation failed.") + completionHandler(true) } } func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) { From be5540eda57d5a520f7d4f3ba913de5dc130b92f Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sun, 20 Apr 2025 10:38:51 -0700 Subject: [PATCH 7/8] Remove impossible cases --- Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift index 569379b5..6dc1854b 100644 --- a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift +++ b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift @@ -8,6 +8,7 @@ import Foundation import CocoaMQTT import OSLog +import Security protocol MqttClientProxyManagerDelegate: AnyObject { func onMqttConnected() @@ -131,16 +132,7 @@ extension MqttClientProxyManager: CocoaMQTTDelegate { } } func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) { - var isValid = false - #if canImport(Security) - if #available(macOS 10.15, iOS 13.0, *) { - isValid = SecTrustEvaluateWithError(trust, nil) - } else { - var result: SecTrustResultType = .invalid - let status = SecTrustEvaluate(trust, &result) - isValid = (status == errSecSuccess) && (result == .unspecified || result == .proceed) - } - #endif + let isValid = SecTrustEvaluateWithError(trust, nil) if isValid { Logger.mqtt.info("📲 [MQTT Client Proxy] TLS validation succeeded.") completionHandler(true) From 8729dfa656f61c875ebe9e5c25c8bb208c5c3924 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Mon, 21 Apr 2025 17:44:21 -0700 Subject: [PATCH 8/8] MQTT Map report opt in prototype, add legacy admin channel back to restricted channels. --- Localizable.xcstrings | 15 +++++++++++++++ Meshtastic/Views/Messages/ChannelList.swift | 2 +- .../Views/Settings/Config/Module/MQTTConfig.swift | 9 +++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 43a11bb0..6ca06337 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -2748,6 +2748,12 @@ } } } + }, + "By enabling the map report your node will periodically send a totally unencrypted packet to the configured MQTT server irrigardness of any channel specific uplink and downling MQTT Settings. This report includes short and long name, position, hardware model, role, firmware version, LoRa region, modem preset and primary channel name" : { + + }, + "By enabling this feature, you acknowledge and expressly consent to the transmission of your device’s real-time geographic location over the MQTT protocol without encryption. This location data may be used for purposes such as live map reporting, device tracking, and related telemetry functions." : { + }, "Bytes" : { "extractionState" : "migrated", @@ -5938,6 +5944,9 @@ } } } + }, + "Consent to Share Unencrypted Location Data via MQTT" : { + }, "contacts" : { "extractionState" : "manual", @@ -12265,6 +12274,9 @@ } } } + }, + "I have read and understand the above. I voluntarily consent to the unencrypted transmission of my location data via MQTT for map reporting purposes." : { + }, "IAQ" : { "localizations" : { @@ -22822,6 +22834,9 @@ } } } + }, + "Please be advised that because MQTT transmission is not encrypted by default, your location data may be stored permanently and displayed by third parties. Meshtastic does not assume responsibility for any such unauthorized access or disclosure resulting from unencrypted transmission." : { + }, "Please connect to a radio to configure settings." : { "localizations" : { diff --git a/Meshtastic/Views/Messages/ChannelList.swift b/Meshtastic/Views/Messages/ChannelList.swift index a4fd86bf..426cb0c7 100644 --- a/Meshtastic/Views/Messages/ChannelList.swift +++ b/Meshtastic/Views/Messages/ChannelList.swift @@ -24,7 +24,7 @@ struct ChannelList: View { @State private var isPresentingTraceRouteSentAlert = false - var restrictedChannels = ["gpio", "mqtt", "serial"] + var restrictedChannels = ["gpio", "mqtt", "serial", "admin"] @ViewBuilder private func makeChannelRow( diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index 29b06464..046d86aa 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -30,6 +30,7 @@ struct MQTTConfig: View { @State var mqttConnected: Bool = false @State var defaultTopic = "msh/US" @State var nearbyTopics = [String]() + @State var mapReportingOptIn = false @State var mapReportingEnabled = false @State var mapPublishIntervalSecs = 3600 @State var mapPositionPrecision: Double = 14.0 @@ -92,9 +93,17 @@ struct MQTTConfig: View { } Section(header: Text("Map Report")) { + Text("Consent to Share Unencrypted Location Data via MQTT") + .font(.title2) + Text("By enabling this feature, you acknowledge and expressly consent to the transmission of your device’s real-time geographic location over the MQTT protocol without encryption. This location data may be used for purposes such as live map reporting, device tracking, and related telemetry functions.") + Text("Please be advised that because MQTT transmission is not encrypted by default, your location data may be stored permanently and displayed by third parties. Meshtastic does not assume responsibility for any such unauthorized access or disclosure resulting from unencrypted transmission.") + Toggle(isOn: $mapReportingOptIn) { + Label("I have read and understand the above. I voluntarily consent to the unencrypted transmission of my location data via MQTT for map reporting purposes.", systemImage: "hand.raised") + } Toggle(isOn: $mapReportingEnabled) { Label("enabled", systemImage: "map") + Text("By enabling the map report your node will periodically send a totally unencrypted packet to the configured MQTT server irrigardness of any channel specific uplink and downling MQTT Settings. This report includes short and long name, position, hardware model, role, firmware version, LoRa region, modem preset and primary channel name") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) if mapReportingEnabled {