Bump GPIO Pickers to 45

This commit is contained in:
Garth Vander Houwen 2023-04-03 17:48:58 -07:00
parent f992d6e47a
commit b455fb25c6
11 changed files with 319 additions and 271 deletions

View file

@ -127,6 +127,7 @@
DDDE5A1129AFE69700490C6C /* MeshActivityAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDE5A0F29AFE69700490C6C /* MeshActivityAttributes.swift */; };
DDDE5A1329AFEAB900490C6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDDE5A1229AFEAB900490C6C /* Assets.xcassets */; };
DDDE5A1429AFEAB900490C6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDDE5A1229AFEAB900490C6C /* Assets.xcassets */; };
DDDEE5E129DA3E1100A8E078 /* NodeInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDEE5E029DA3E1100A8E078 /* NodeInfoView.swift */; };
DDE0F7C5295F77B700B8AAB3 /* AppSettingsEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE0F7C4295F77B700B8AAB3 /* AppSettingsEnums.swift */; };
DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF924C926FBB953009FE055 /* ConnectedDevice.swift */; };
DDFEB3BB29900C1200EE7472 /* CurrentConditionsCompact.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFEB3BA29900C1200EE7472 /* CurrentConditionsCompact.swift */; };
@ -305,6 +306,7 @@
DDDE5A0429AF163E00490C6C /* WidgetsExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WidgetsExtension.entitlements; sourceTree = "<group>"; };
DDDE5A0F29AFE69700490C6C /* MeshActivityAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshActivityAttributes.swift; sourceTree = "<group>"; };
DDDE5A1229AFEAB900490C6C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
DDDEE5E029DA3E1100A8E078 /* NodeInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfoView.swift; sourceTree = "<group>"; };
DDE0F7C4295F77B700B8AAB3 /* AppSettingsEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsEnums.swift; sourceTree = "<group>"; };
DDEE03EC29544A1000FCAD57 /* MeshtasticDataModelV4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV4.xcdatamodel; sourceTree = "<group>"; };
DDF924C926FBB953009FE055 /* ConnectedDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectedDevice.swift; sourceTree = "<group>"; };
@ -632,6 +634,7 @@
DDC2E18D26CE25CB0042C5E4 /* Helpers */ = {
isa = PBXGroup;
children = (
DDDEE5DF29DA3DA000A8E078 /* Node */,
DD5E523D298F5A7D00D21B61 /* Weather */,
DD47E3D526F17ED900029299 /* CircleText.swift */,
DDF924C926FBB953009FE055 /* ConnectedDevice.swift */,
@ -689,6 +692,14 @@
path = Widgets;
sourceTree = "<group>";
};
DDDEE5DF29DA3DA000A8E078 /* Node */ = {
isa = PBXGroup;
children = (
DDDEE5E029DA3E1100A8E078 /* NodeInfoView.swift */,
);
path = Node;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -938,6 +949,7 @@
DD964FC2297272AE007C176F /* WaypointEntityExtension.swift in Sources */,
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */,
DD5E520A298EE33B00D21B61 /* channel.pb.swift in Sources */,
DDDEE5E129DA3E1100A8E078 /* NodeInfoView.swift in Sources */,
DD8EBF43285058FA00426DCA /* DisplayConfig.swift in Sources */,
DD964FC42974767D007C176F /* MapViewFitExtension.swift in Sources */,
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */,

View file

@ -45,6 +45,7 @@ extension UIColor {
let red = CGFloat((hex & 0xFF0000) >> 16)
let green = CGFloat((hex & 0x00FF00) >> 8)
let blue = CGFloat((hex & 0x0000FF))
//print("\(red) - \(green) - \(blue)")
self.init(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: 1.0)
}
}

View file

@ -138,7 +138,6 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext)
fetchedNode[0].num = Int64(packet.from)
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
fetchedNode[0].snr = packet.rxSnr
//fetchedNode[0].channel = Int32(packet.channel)
if let nodeInfoMessage = try? NodeInfo(serializedData: packet.decoded.payload) {

View file

@ -0,0 +1,285 @@
//
// NodeInfoView.swift
// Meshtastic
//
// Created by Garth Vander Houwen on 4/2/23.
//
//
// DistanceText.swift
// Meshtastic
//
// Copyright(c) Garth Vander Houwen 8/19/22.
//
import SwiftUI
import CoreLocation
import MapKit
struct NodeInfoView: View {
var node: NodeInfoEntity
var body: some View {
let hwModelString = node.user?.hwModel ?? "UNSET"
Divider()
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
HStack {
VStack(alignment: .center) {
CircleText(text: node.user?.shortName ?? "???", color: Color(UIColor(hex: UInt32(node.num))), circleSize: 75, fontSize: 24, textColor: UIColor(hex: UInt32(node.num)).isLight() ? .black : .white )
}
Divider()
VStack {
if node.user != nil {
Image(hwModelString)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 100)
.cornerRadius(5)
Text(String(hwModelString))
.foregroundColor(.gray)
.font(.largeTitle).fixedSize()
}
}
if node.snr > 0 {
Divider()
VStack(alignment: .center) {
Image(systemName: "waveform.path")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
.padding(.bottom, 10)
Text("SNR").font(.largeTitle).fixedSize()
Text("\(String(format: "%.2f", node.snr)) dB")
.font(.largeTitle)
.foregroundColor(.gray)
.fixedSize()
}
}
let deviceMetrics = node.telemetries?.filtered(using: NSPredicate(format: "metricsType == 0"))
if deviceMetrics?.count ?? 0 >= 1 {
let mostRecent = deviceMetrics?.lastObject as? TelemetryEntity
Divider()
VStack(alignment: .center) {
BatteryGauge(batteryLevel: Double(mostRecent?.batteryLevel ?? 0))
if mostRecent?.voltage ?? 0 > 0.0 {
Text(String(format: "%.2f", mostRecent?.voltage ?? 0.0) + " V")
.font(.title)
.foregroundColor(.gray)
.fixedSize()
}
}
.padding()
}
}
.padding()
Divider()
HStack(alignment: .center) {
VStack {
HStack {
Image(systemName: "person")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("user").font(.title)+Text(":").font(.title)
}
Text("!\(String(format: "%02x", node.num))")
.font(.title).foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "number")
.font(.title2)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("Node Number:").font(.title)
}
Text(String(node.num)).font(.title).foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "globe")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("MAC Address: ").font(.title)
}
Text(String(node.user?.macaddr?.macAddressString ?? "not a valid mac address"))
.font(.title)
.foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "clock.badge.checkmark.fill")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("heard.last").font(.title)+Text(":").font(.title)
}
DateTimeText(dateTime: node.lastHeard)
.font(.title3)
.foregroundColor(.gray)
}
}
Divider()
} else {
HStack {
VStack(alignment: .center) {
CircleText(text: node.user?.shortName ?? "???", color: Color(UIColor(hex: UInt32(node.num))), circleSize: 65, fontSize: 20, textColor: UIColor(hex: UInt32(node.num)).isLight() ? .black : .white )
}
Divider()
VStack {
if node.user != nil {
Image(node.user!.hwModel ?? NSLocalizedString("unset", comment: "Unset"))
.resizable()
.frame(width: 75, height: 75)
.cornerRadius(5)
Text(String(node.user!.hwModel ?? NSLocalizedString("unset", comment: "Unset")))
.font(.callout).fixedSize()
}
}
if node.snr > 0 {
Divider()
VStack(alignment: .center) {
Image(systemName: "waveform.path")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("SNR").font(.title2).fixedSize()
Text("\(String(format: "%.2f", node.snr)) dB")
.font(.title2)
.foregroundColor(.gray)
.fixedSize()
}
}
let deviceMetrics = node.telemetries?.filtered(using: NSPredicate(format: "metricsType == 0"))
if deviceMetrics?.count ?? 0 >= 1 {
let mostRecent = deviceMetrics?.lastObject as? TelemetryEntity
Divider()
VStack(alignment: .center) {
BatteryGauge(batteryLevel: Double(mostRecent?.batteryLevel ?? 0))
if mostRecent?.voltage ?? 0 > 0 {
Text(String(format: "%.2f", mostRecent?.voltage ?? 0) + " V")
.font(.callout)
.foregroundColor(.gray)
.fixedSize()
}
}
}
}
Divider()
HStack(alignment: .center) {
VStack {
HStack {
Image(systemName: "person")
.font(.title2)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("User Id:").font(.title2)
}
Text(node.user?.userId ?? "??????").font(.title3).foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "number")
.font(.title2)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("Node Number:").font(.title2)
}
Text(String(node.num)).font(.title3).foregroundColor(.gray)
}
}
Divider()
HStack {
Image(systemName: "globe")
.font(.headline)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("MAC Address: ")
Text(String(node.user?.macaddr?.macAddressString ?? "not a valid mac address")).foregroundColor(.gray)
}
.padding([.bottom], 10)
Divider()
}
VStack {
if (node.positions?.count ?? 0) > 0 {
NavigationLink {
PositionLog(node: node)
} label: {
Image(systemName: "building.columns")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Position Log")
.font(.title3)
}
.fixedSize(horizontal: false, vertical: true)
Divider()
}
if (node.telemetries?.count ?? 0) > 0 {
NavigationLink {
DeviceMetricsLog(node: node)
} label: {
Image(systemName: "flipphone")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Device Metrics Log")
.font(.title3)
}
Divider()
NavigationLink {
EnvironmentMetricsLog(node: node)
} label: {
Image(systemName: "chart.xyaxis.line")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Environment Metrics Log")
.font(.title3)
}
Divider()
}
}
}
}
struct NodeInfoView_Previews: PreviewProvider {
static var previews: some View {
VStack {
}
}
}

View file

@ -140,257 +140,8 @@ struct NodeDetail: View {
.padding([.top], 20)
}
ScrollView {
Divider()
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
HStack {
VStack(alignment: .center) {
CircleText(text: node.user?.shortName ?? "???", color: Color(UIColor(hex: UInt32(node.num))), circleSize: 75, fontSize: 24, textColor: UIColor(hex: UInt32(node.num)).isLight() ? .black : .white )
}
Divider()
VStack {
if node.user != nil {
Image(hwModelString)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 100)
.cornerRadius(5)
Text(String(hwModelString))
.foregroundColor(.gray)
.font(.largeTitle).fixedSize()
}
}
if node.snr > 0 {
Divider()
VStack(alignment: .center) {
Image(systemName: "waveform.path")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
.padding(.bottom, 10)
Text("SNR").font(.largeTitle).fixedSize()
Text("\(String(format: "%.2f", node.snr)) dB")
.font(.largeTitle)
.foregroundColor(.gray)
.fixedSize()
}
}
let deviceMetrics = node.telemetries?.filtered(using: NSPredicate(format: "metricsType == 0"))
if deviceMetrics?.count ?? 0 >= 1 {
let mostRecent = deviceMetrics?.lastObject as? TelemetryEntity
Divider()
VStack(alignment: .center) {
BatteryGauge(batteryLevel: Double(mostRecent?.batteryLevel ?? 0))
if mostRecent?.voltage ?? 0 > 0.0 {
Text(String(format: "%.2f", mostRecent?.voltage ?? 0.0) + " V")
.font(.title)
.foregroundColor(.gray)
.fixedSize()
}
}
.padding()
}
}
.padding()
Divider()
HStack(alignment: .center) {
VStack {
HStack {
Image(systemName: "person")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("user").font(.title)+Text(":").font(.title)
}
Text("!\(String(format: "%02x", node.num))")
.font(.title).foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "number")
.font(.title2)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("Node Number:").font(.title)
}
Text(String(node.num)).font(.title).foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "globe")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("MAC Address: ").font(.title)
}
Text(String(node.user?.macaddr?.macAddressString ?? "not a valid mac address"))
.font(.title)
.foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "clock.badge.checkmark.fill")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("heard.last").font(.title)+Text(":").font(.title)
}
DateTimeText(dateTime: node.lastHeard)
.font(.title3)
.foregroundColor(.gray)
}
}
Divider()
} else {
HStack {
VStack(alignment: .center) {
CircleText(text: node.user?.shortName ?? "???", color: Color(UIColor(hex: UInt32(node.num))), circleSize: 65, fontSize: 20, textColor: UIColor(hex: UInt32(node.num)).isLight() ? .black : .white )
}
Divider()
VStack {
if node.user != nil {
Image(node.user!.hwModel ?? NSLocalizedString("unset", comment: "Unset"))
.resizable()
.frame(width: 75, height: 75)
.cornerRadius(5)
Text(String(node.user!.hwModel ?? NSLocalizedString("unset", comment: "Unset")))
.font(.callout).fixedSize()
}
}
if node.snr > 0 {
Divider()
VStack(alignment: .center) {
Image(systemName: "waveform.path")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("SNR").font(.title2).fixedSize()
Text("\(String(format: "%.2f", node.snr)) dB")
.font(.title2)
.foregroundColor(.gray)
.fixedSize()
}
}
let deviceMetrics = node.telemetries?.filtered(using: NSPredicate(format: "metricsType == 0"))
if deviceMetrics?.count ?? 0 >= 1 {
let mostRecent = deviceMetrics?.lastObject as? TelemetryEntity
Divider()
VStack(alignment: .center) {
BatteryGauge(batteryLevel: Double(mostRecent?.batteryLevel ?? 0))
if mostRecent?.voltage ?? 0 > 0 {
Text(String(format: "%.2f", mostRecent?.voltage ?? 0) + " V")
.font(.callout)
.foregroundColor(.gray)
.fixedSize()
}
}
}
}
Divider()
HStack(alignment: .center) {
VStack {
HStack {
Image(systemName: "person")
.font(.title2)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("User Id:").font(.title2)
}
Text(node.user?.userId ?? "??????").font(.title3).foregroundColor(.gray)
}
Divider()
VStack {
HStack {
Image(systemName: "number")
.font(.title2)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("Node Number:").font(.title2)
}
Text(String(node.num)).font(.title3).foregroundColor(.gray)
}
}
Divider()
HStack {
Image(systemName: "globe")
.font(.headline)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("MAC Address: ")
Text(String(node.user?.macaddr?.macAddressString ?? "not a valid mac address")).foregroundColor(.gray)
}
.padding([.bottom], 10)
Divider()
}
VStack {
if (node.positions?.count ?? 0) > 0 {
NavigationLink {
PositionLog(node: node)
} label: {
Image(systemName: "building.columns")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Position Log")
.font(.title3)
}
.fixedSize(horizontal: false, vertical: true)
Divider()
}
if (node.telemetries?.count ?? 0) > 0 {
NavigationLink {
DeviceMetricsLog(node: node)
} label: {
Image(systemName: "flipphone")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Device Metrics Log")
.font(.title3)
}
Divider()
NavigationLink {
EnvironmentMetricsLog(node: node)
} label: {
Image(systemName: "chart.xyaxis.line")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Environment Metrics Log")
.font(.title3)
}
Divider()
}
}
ScrollView() {
NodeInfoView(node: node)
if self.bleManager.connectedPeripheral != nil && node.metadata != nil {
HStack {

View file

@ -64,13 +64,6 @@ struct NodeList: View {
}
}
}
HStack(alignment: .bottom) {
Image(systemName: "clock.badge.checkmark.fill")
.font(.title3)
.symbolRenderingMode(.hierarchical)
LastHeardText(lastHeard: node.lastHeard)
.font(.subheadline)
}
if node.channel > 0 {
HStack(alignment: .bottom) {
Image(systemName: "fibrechannel")
@ -80,6 +73,13 @@ struct NodeList: View {
.font(.subheadline)
}
}
HStack(alignment: .bottom) {
Image(systemName: "clock.badge.checkmark.fill")
.font(.title3)
.symbolRenderingMode(.hierarchical)
LastHeardText(lastHeard: node.lastHeard)
.font(.subheadline)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
}

View file

@ -100,7 +100,7 @@ struct DeviceConfig: View {
Section(header: Text("GPIO")) {
Picker("Button GPIO", selection: $buttonGPIO) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {
@ -110,7 +110,7 @@ struct DeviceConfig: View {
}
.pickerStyle(DefaultPickerStyle())
Picker("Buzzer GPIO", selection: $buzzerGPIO) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {

View file

@ -125,7 +125,7 @@ struct CannedMessagesConfig: View {
.disabled(configPreset > 0)
Section(header: Text("Inputs")) {
Picker("Pin A", selection: $inputbrokerPinA) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {
@ -137,7 +137,7 @@ struct CannedMessagesConfig: View {
Text("GPIO pin for rotary encoder A port.")
.font(.caption)
Picker("Pin B", selection: $inputbrokerPinB) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {
@ -149,7 +149,7 @@ struct CannedMessagesConfig: View {
Text("GPIO pin for rotary encoder B port.")
.font(.caption)
Picker("Press Pin", selection: $inputbrokerPinPress) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {

View file

@ -92,7 +92,7 @@ struct ExternalNotificationConfig: View {
Text("If enabled, the 'output' Pin will be pulled active high, disabled means active low.")
.font(.caption)
Picker("Output pin GPIO", selection: $output) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {
@ -140,7 +140,7 @@ struct ExternalNotificationConfig: View {
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Picker("Output pin buzzer GPIO ", selection: $outputBuzzer) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {
@ -150,7 +150,7 @@ struct ExternalNotificationConfig: View {
}
.pickerStyle(DefaultPickerStyle())
Picker("Output pin vibra GPIO", selection: $outputVibra) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {

View file

@ -98,7 +98,7 @@ struct SerialConfig: View {
Section(header: Text("GPIO")) {
Picker("Receive data (rxd) GPIO pin", selection: $rxd) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {
@ -109,7 +109,7 @@ struct SerialConfig: View {
.pickerStyle(DefaultPickerStyle())
Picker("Transmit data (txd) GPIO pin", selection: $txd) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {

View file

@ -236,7 +236,7 @@ struct PositionConfig: View {
.font(.caption)
Picker("GPS Receive GPIO", selection: $rxGpio) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {
@ -247,7 +247,7 @@ struct PositionConfig: View {
.pickerStyle(DefaultPickerStyle())
Picker("GPS Transmit GPIO", selection: $txGpio) {
ForEach(0..<40) {
ForEach(0..<46) {
if $0 == 0 {
Text("unset")
} else {