diff --git a/Localizable.xcstrings b/Localizable.xcstrings
index 99a00727..ad45481e 100644
--- a/Localizable.xcstrings
+++ b/Localizable.xcstrings
@@ -9017,7 +9017,7 @@
}
},
"incomplete" : {
- "extractionState" : "migrated",
+ "extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
@@ -15216,6 +15216,9 @@
}
}
}
+ },
+ "Model" : {
+
},
"module.configuration" : {
"localizations" : {
diff --git a/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/Contents.json b/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/Contents.json
index 1a8d07dc..a1a7444e 100644
--- a/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/Contents.json
+++ b/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "Paper-Meshtastic-2 copy.jpg",
+ "filename" : "heltec-wireless-paper.svg",
"idiom" : "universal"
}
],
diff --git a/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/Paper-Meshtastic-2 copy.jpg b/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/Paper-Meshtastic-2 copy.jpg
deleted file mode 100644
index 36692599..00000000
Binary files a/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/Paper-Meshtastic-2 copy.jpg and /dev/null differ
diff --git a/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/heltec-wireless-paper.svg b/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/heltec-wireless-paper.svg
new file mode 100644
index 00000000..cb3f188d
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/heltec-wireless-paper.svg
@@ -0,0 +1 @@
+
diff --git a/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/Contents.json b/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/Contents.json
index 3b6b227c..d13152fe 100644
--- a/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/Contents.json
+++ b/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "images.png",
+ "filename" : "heltec-wireless-tracker.svg",
"idiom" : "universal"
}
],
diff --git a/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/heltec-wireless-tracker.svg b/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/heltec-wireless-tracker.svg
new file mode 100644
index 00000000..a5392595
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/heltec-wireless-tracker.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/images.png b/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/images.png
deleted file mode 100644
index 4e9336c5..00000000
Binary files a/Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/images.png and /dev/null differ
diff --git a/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/Contents.json b/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/Contents.json
index aed717e4..dea94fc1 100644
--- a/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/Contents.json
+++ b/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "heltecwsl.png",
+ "filename" : "heltec-wsl-v3.svg",
"idiom" : "universal"
}
],
diff --git a/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltec-wsl-v3.svg b/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltec-wsl-v3.svg
new file mode 100644
index 00000000..1741223e
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltec-wsl-v3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltecwsl.png b/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltecwsl.png
deleted file mode 100644
index 8881d0e1..00000000
Binary files a/Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltecwsl.png and /dev/null differ
diff --git a/Meshtastic/Assets.xcassets/TBEAM.imageset/Contents.json b/Meshtastic/Assets.xcassets/TBEAM.imageset/Contents.json
new file mode 100644
index 00000000..0ecd041c
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/TBEAM.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "tbeam.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Meshtastic/Assets.xcassets/TBEAM.imageset/tbeam.svg b/Meshtastic/Assets.xcassets/TBEAM.imageset/tbeam.svg
new file mode 100644
index 00000000..cd0475c6
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/TBEAM.imageset/tbeam.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Meshtastic/Assets.xcassets/TLORAC6.imageset/Contents.json b/Meshtastic/Assets.xcassets/TLORAC6.imageset/Contents.json
new file mode 100644
index 00000000..593dc16e
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/TLORAC6.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "tlora-c6.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Meshtastic/Assets.xcassets/TLORAC6.imageset/tlora-c6.svg b/Meshtastic/Assets.xcassets/TLORAC6.imageset/tlora-c6.svg
new file mode 100644
index 00000000..8b626638
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/TLORAC6.imageset/tlora-c6.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/Contents.json b/Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/Contents.json
new file mode 100644
index 00000000..a5716fc8
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "tlora-t3s3-v1.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/tlora-t3s3-v1.svg b/Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/tlora-t3s3-v1.svg
new file mode 100644
index 00000000..1f8847d4
--- /dev/null
+++ b/Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/tlora-t3s3-v1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Meshtastic/Extensions/CoreData/UserEntityExtension.swift b/Meshtastic/Extensions/CoreData/UserEntityExtension.swift
index 099d910d..662ca5b0 100644
--- a/Meshtastic/Extensions/CoreData/UserEntityExtension.swift
+++ b/Meshtastic/Extensions/CoreData/UserEntityExtension.swift
@@ -37,6 +37,8 @@ extension UserEntity {
var hardwareImage: String? {
guard let hwModel else { return nil }
switch hwModel {
+ /// SVG Images for Vendors who are project backers
+ /// Heltec
case "HELTECV3":
return "HELTECV3"
case "HELTECWIRELESSPAPER", "HELTECWIRELESSPAPERV10":
@@ -45,18 +47,23 @@ extension UserEntity {
return "HELTECWIRELESSTRACKER"
case "HELTECWSLV3":
return "HELTECWSLV3"
+ /// LilyGO
+ case "TBEAM", "TBEAM_V0P7":
+ return "TBEAM"
+ case "TLORAT3S3V1":
+ return "TLORAT3S3V1"
+ case "TLORAC6":
+ return "TLORAC6"
+ /// B&O Consulting
case "NANOG1", "NANOG1EXPLORER":
return "NANOG1"
case "NANOG2ULTRA":
return "NANOG2ULTRA"
- case "RAK4631":
- return "RAK4631"
- case "RAK11200":
- return "RAK11200"
+ case "STATIONG2":
+ return "STATIONG2"
case "SOLAR_NODE":
return "SOLAR_NODE"
- case "STATIONG1":
- return "STATIONG1"
+
case "UNPHONE":
return "UNPHONE"
default:
diff --git a/Meshtastic/Resources/DeviceHardware.json b/Meshtastic/Resources/DeviceHardware.json
index 94c74660..fd874357 100644
--- a/Meshtastic/Resources/DeviceHardware.json
+++ b/Meshtastic/Resources/DeviceHardware.json
@@ -294,7 +294,7 @@
"RAK"
],
"images": [
- "rak4631.svg"
+ "rak11310.svg"
],
"requiresDfu": true
},
@@ -350,6 +350,9 @@
"displayName": "DIY V1",
"tags": [
"DIY"
+ ],
+ "images": [
+ "diy.svg"
]
},
{
@@ -427,10 +430,13 @@
"supportLevel": 3,
"displayName": "Raspberry Pi Pico",
"tags": [
- "Raspberry Pi",
+ "RPi",
"DIY"
],
- "requiresDfu": true
+ "requiresDfu": true,
+ "images": [
+ "pico.svg"
+ ]
},
{
"hwModel": 47,
@@ -441,10 +447,13 @@
"supportLevel": 3,
"displayName": "Raspberry Pi Pico W",
"tags": [
- "Raspberry Pi",
+ "RPi",
"DIY"
],
- "requiresDfu": true
+ "requiresDfu": true,
+ "images": [
+ "rpipicow.svg"
+ ]
},
{
"hwModel": 48,
diff --git a/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift b/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift
index a9f7bcfe..0a648571 100644
--- a/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift
+++ b/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift
@@ -16,12 +16,16 @@ struct NodeDetail: View {
formatter.unitsStyle = .full
return formatter
}()
+ var modemPreset: ModemPresets = ModemPresets(
+ rawValue: UserDefaults.modemPreset
+ ) ?? ModemPresets.longFast
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State private var showingShutdownConfirm: Bool = false
@State private var showingRebootConfirm: Bool = false
@State private var dateFormatRelative: Bool = true
+ @State private var currentDevice: DeviceHardware?
// The node the device is currently connected to
var connectedNode: NodeInfoEntity?
@@ -41,9 +45,37 @@ struct NodeDetail: View {
)
Section("Hardware") {
- NodeInfoItem(node: node)
+ NodeInfoItem(node: node, supported: currentDevice?.activelySupported ?? false)
}
Section("Node") {
+ HStack(alignment: .center) {
+ Spacer()
+ CircleText(
+ text: node.user?.shortName ?? "?",
+ color: Color(UIColor(hex: UInt32(node.num))),
+ circleSize: 75
+ )
+ if node.snr != 0 && !node.viaMqtt && node.hopsAway == 0 {
+ Spacer()
+ VStack {
+ let signalStrength = getLoRaSignalStrength(snr: node.snr, rssi: node.rssi, preset: modemPreset)
+ LoRaSignalStrengthIndicator(signalStrength: signalStrength)
+ Text("Signal \(signalStrength.description)").font(.footnote)
+ Text("SNR \(String(format: "%.2f", node.snr))dB")
+ .foregroundColor(getSnrColor(snr: node.snr, preset: modemPreset))
+ .font(.caption)
+ Text("RSSI \(node.rssi)dB")
+ .foregroundColor(getRssiColor(rssi: node.rssi))
+ .font(.caption)
+ }
+ }
+ if node.telemetries?.count ?? 0 > 0 {
+ Spacer()
+ BatteryGauge(node: node)
+ }
+ Spacer()
+ }
+ .listRowSeparator(.hidden)
if let user = node.user {
if !user.keyMatch {
Label {
@@ -406,6 +438,17 @@ struct NodeDetail: View {
}
}
.listStyle(.insetGrouped)
+ .onFirstAppear {
+ Api().loadDeviceHardwareData { (hw) in
+ for device in hw {
+ let currentHardware = node.user?.hwModel ?? "UNSET"
+ let deviceString = device.hwModelSlug.replacingOccurrences(of: "_", with: "")
+ if deviceString == currentHardware {
+ currentDevice = device
+ }
+ }
+ }
+ }
}
}
}
diff --git a/Meshtastic/Views/Nodes/Helpers/NodeInfoItem.swift b/Meshtastic/Views/Nodes/Helpers/NodeInfoItem.swift
index e0da484e..649fe6d1 100644
--- a/Meshtastic/Views/Nodes/Helpers/NodeInfoItem.swift
+++ b/Meshtastic/Views/Nodes/Helpers/NodeInfoItem.swift
@@ -12,61 +12,58 @@ import MapKit
struct NodeInfoItem: View {
@ObservedObject var node: NodeInfoEntity
-
- var modemPreset: ModemPresets = ModemPresets(
- rawValue: UserDefaults.modemPreset
- ) ?? ModemPresets.longFast
+ var supported: Bool
var body: some View {
+ if let user = node.user {
ViewThatFits(in: .horizontal) {
- VStack {
- if let user = node.user {
- HStack(alignment: .center) {
- if user.hwModel != "UNSET" {
- Image(user.hardwareImage ?? "UNSET")
- .resizable()
- .aspectRatio(contentMode: .fit)
- .frame(width: 65, height: 65)
- .cornerRadius(5)
- Text(String(node.user?.hwDisplayName ?? (node.user?.hwModel ?? "unset".localized)))
- .font(.callout)
- } else {
- Image(systemName: "person.crop.circle.badge.questionmark")
- .resizable()
- .aspectRatio(contentMode: .fit)
- .frame(width: 65, height: 65)
- .cornerRadius(5)
- Text(String("incomplete".localized))
+ HStack {
+ Spacer()
+ VStack(alignment: .center) {
+ Spacer()
+ Image(systemName: supported ? "checkmark.seal.fill" : "x.circle")
+ .resizable()
+ .aspectRatio(contentMode: .fill) // << here !!
+ .frame(width: 75, height: 75)
+ .foregroundStyle(supported ? .green : .red)
+ Text( supported ? "Supported" : "Unsupported")
+ .foregroundStyle(.gray)
.font(.callout)
+ }
+ Spacer()
+ VStack(alignment: .center) {
+ HStack {
+ if user.hwModel != "UNSET" {
+ Image(user.hardwareImage ?? "UNSET")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(maxHeight: 150)
+ .cornerRadius(5)
+ } else {
+ Image(systemName: "person.crop.circle.badge.questionmark")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 65, height: 65)
+ .cornerRadius(5)
+ }
}
}
+ Spacer()
}
- HStack(alignment: .center) {
- Spacer()
- CircleText(
- text: node.user?.shortName ?? "?",
- color: Color(UIColor(hex: UInt32(node.num))),
- circleSize: 75
- )
- if node.snr != 0 && !node.viaMqtt && node.hopsAway == 0 {
- Spacer()
- VStack {
- let signalStrength = getLoRaSignalStrength(snr: node.snr, rssi: node.rssi, preset: modemPreset)
- LoRaSignalStrengthIndicator(signalStrength: signalStrength)
- Text("Signal \(signalStrength.description)").font(.footnote)
- Text("SNR \(String(format: "%.2f", node.snr))dB")
- .foregroundColor(getSnrColor(snr: node.snr, preset: modemPreset))
- .font(.caption)
- Text("RSSI \(node.rssi)dB")
- .foregroundColor(getRssiColor(rssi: node.rssi))
- .font(.caption)
- }
- }
- if node.telemetries?.count ?? 0 > 0 {
- Spacer()
- BatteryGauge(node: node)
- }
- Spacer()
+ }
+ .listRowSeparator(.hidden)
+ HStack {
+ Label {
+ Text("Model")
+ } icon: {
+ Image(systemName: "flipphone")
+ .symbolRenderingMode(.hierarchical)
+ }
+ Spacer()
+ if user.hwModel != "UNSET" {
+ Text(String(node.user?.hwDisplayName ?? (node.user?.hwModel ?? "unset".localized)))
+ } else {
+ Text(String("incomplete".localized))
}
}
}
diff --git a/Meshtastic/Views/Settings/Firmware.swift b/Meshtastic/Views/Settings/Firmware.swift
index 9962e69d..6e1427bf 100644
--- a/Meshtastic/Views/Settings/Firmware.swift
+++ b/Meshtastic/Views/Settings/Firmware.swift
@@ -185,7 +185,7 @@ struct Firmware: View {
}
.padding()
.padding(.bottom, 5)
- .onAppear {
+ .onFirstAppear {
Api().loadDeviceHardwareData { (hw) in
for device in hw {
let currentHardware = node?.user?.hwModel ?? "UNSET"