Update hardware section on node details.
|
|
@ -9017,7 +9017,7 @@
|
|||
}
|
||||
},
|
||||
"incomplete" : {
|
||||
"extractionState" : "migrated",
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"de" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -15216,6 +15216,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Model" : {
|
||||
|
||||
},
|
||||
"module.configuration" : {
|
||||
"localizations" : {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Paper-Meshtastic-2 copy.jpg",
|
||||
"filename" : "heltec-wireless-paper.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 66 KiB |
1
Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/heltec-wireless-paper.svg
vendored
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "images.png",
|
||||
"filename" : "heltec-wireless-tracker.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
1
Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/heltec-wireless-tracker.svg
vendored
Normal file
|
After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "heltecwsl.png",
|
||||
"filename" : "heltec-wsl-v3.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
1
Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltec-wsl-v3.svg
vendored
Normal file
|
After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 209 KiB |
12
Meshtastic/Assets.xcassets/TBEAM.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tbeam.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TBEAM.imageset/tbeam.svg
vendored
Normal file
|
After Width: | Height: | Size: 112 KiB |
12
Meshtastic/Assets.xcassets/TLORAC6.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tlora-c6.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TLORAC6.imageset/tlora-c6.svg
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
12
Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tlora-t3s3-v1.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/tlora-t3s3-v1.svg
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||