Merge pull request #84 from meshtastic/feature/new_config

Mock Up new Config Views
This commit is contained in:
Garth Vander Houwen 2022-06-12 22:10:19 -07:00 committed by GitHub
commit 75f19d2dbe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 135 additions and 59 deletions

View file

@ -18,6 +18,7 @@
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */; };
DD2553572855B02500E55709 /* LoRaConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2553562855B02500E55709 /* LoRaConfig.swift */; };
DD2553592855B52700E55709 /* PositionConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2553582855B52700E55709 /* PositionConfig.swift */; };
DD25535D285666C700E55709 /* PowerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD25535C285666C700E55709 /* PowerConfig.swift */; };
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2E65252767A01F00E45FC5 /* NodeDetail.swift */; };
DD3501892852FC3B000FC853 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3501882852FC3B000FC853 /* Settings.swift */; };
DD35018B2852FC79000FC853 /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD35018A2852FC79000FC853 /* UserSettings.swift */; };
@ -98,6 +99,7 @@
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralModel.swift; sourceTree = "<group>"; };
DD2553562855B02500E55709 /* LoRaConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoRaConfig.swift; sourceTree = "<group>"; };
DD2553582855B52700E55709 /* PositionConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionConfig.swift; sourceTree = "<group>"; };
DD25535C285666C700E55709 /* PowerConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerConfig.swift; sourceTree = "<group>"; };
DD2E65252767A01F00E45FC5 /* NodeDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeDetail.swift; sourceTree = "<group>"; };
DD3501882852FC3B000FC853 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
DD35018A2852FC79000FC853 /* UserSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettings.swift; sourceTree = "<group>"; };
@ -231,6 +233,7 @@
DD8EBF42285058FA00426DCA /* DisplayConfig.swift */,
DD2553562855B02500E55709 /* LoRaConfig.swift */,
DD2553582855B52700E55709 /* PositionConfig.swift */,
DD25535C285666C700E55709 /* PowerConfig.swift */,
DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */,
DD8169FE272476C700F4AB02 /* LogDocument.swift */,
);
@ -592,6 +595,7 @@
DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */,
DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */,
DD9D8F2F2764403B00080993 /* Meshtastic.xcdatamodeld in Sources */,
DD25535D285666C700E55709 /* PowerConfig.swift in Sources */,
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */,
DDB2CC6E27F3EB47009C5FCC /* telemetry.pb.swift in Sources */,
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */,

View file

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21E258" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="20086" systemVersion="21F79" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="LoRaConfigEntity" representedClassName="LoRaConfigEntity" syncable="YES" codeGenerationType="class">
<attribute name="modemPreset" optional="YES" attributeType="String"/>
<attribute name="num" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="regionCode" optional="YES" attributeType="String"/>
</entity>
<entity name="MessageEntity" representedClassName="MessageEntity" syncable="YES" codeGenerationType="class">
<attribute name="ackSNR" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="ackTimestamp" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
@ -99,5 +104,6 @@
<element name="PositionEntity" positionX="-54" positionY="54" width="128" height="119"/>
<element name="TelemetryEntity" positionX="160" positionY="192" width="128" height="194"/>
<element name="UserEntity" positionX="0" positionY="144" width="128" height="200"/>
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="74"/>
</elements>
</model>

View file

@ -390,7 +390,7 @@ struct Config {
/// If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in
/// we should try to minimize power consumption as much as possible.
/// YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case).
var isLowPower: Bool = false
var isPowerSaving: Bool = false
///
/// Circumvents the logic block for determining whether the device is powered or not.
@ -401,10 +401,6 @@ struct Config {
/// If non-zero, the device will fully power off this many seconds after external power is removed.
var onBatteryShutdownAfterSecs: UInt32 = 0
///
/// If set to true, enable power saving features of the esp32
var isPowerSaving: Bool = false
///
/// Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k)
/// Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation.
@ -1350,10 +1346,9 @@ extension Config.PowerConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
static let protoMessageName: String = Config.protoMessageName + ".PowerConfig"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "charge_current"),
2: .standard(proto: "is_low_power"),
2: .standard(proto: "is_power_saving"),
3: .standard(proto: "is_always_powered"),
4: .standard(proto: "on_battery_shutdown_after_secs"),
5: .standard(proto: "is_power_saving"),
6: .standard(proto: "adc_multiplier_override"),
7: .standard(proto: "wait_bluetooth_secs"),
9: .standard(proto: "mesh_sds_timeout_secs"),
@ -1369,10 +1364,9 @@ extension Config.PowerConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularEnumField(value: &self.chargeCurrent) }()
case 2: try { try decoder.decodeSingularBoolField(value: &self.isLowPower) }()
case 2: try { try decoder.decodeSingularBoolField(value: &self.isPowerSaving) }()
case 3: try { try decoder.decodeSingularBoolField(value: &self.isAlwaysPowered) }()
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.onBatteryShutdownAfterSecs) }()
case 5: try { try decoder.decodeSingularBoolField(value: &self.isPowerSaving) }()
case 6: try { try decoder.decodeSingularFloatField(value: &self.adcMultiplierOverride) }()
case 7: try { try decoder.decodeSingularUInt32Field(value: &self.waitBluetoothSecs) }()
case 9: try { try decoder.decodeSingularUInt32Field(value: &self.meshSdsTimeoutSecs) }()
@ -1388,8 +1382,8 @@ extension Config.PowerConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
if self.chargeCurrent != .maunset {
try visitor.visitSingularEnumField(value: self.chargeCurrent, fieldNumber: 1)
}
if self.isLowPower != false {
try visitor.visitSingularBoolField(value: self.isLowPower, fieldNumber: 2)
if self.isPowerSaving != false {
try visitor.visitSingularBoolField(value: self.isPowerSaving, fieldNumber: 2)
}
if self.isAlwaysPowered != false {
try visitor.visitSingularBoolField(value: self.isAlwaysPowered, fieldNumber: 3)
@ -1397,9 +1391,6 @@ extension Config.PowerConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
if self.onBatteryShutdownAfterSecs != 0 {
try visitor.visitSingularUInt32Field(value: self.onBatteryShutdownAfterSecs, fieldNumber: 4)
}
if self.isPowerSaving != false {
try visitor.visitSingularBoolField(value: self.isPowerSaving, fieldNumber: 5)
}
if self.adcMultiplierOverride != 0 {
try visitor.visitSingularFloatField(value: self.adcMultiplierOverride, fieldNumber: 6)
}
@ -1423,10 +1414,9 @@ extension Config.PowerConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
static func ==(lhs: Config.PowerConfig, rhs: Config.PowerConfig) -> Bool {
if lhs.chargeCurrent != rhs.chargeCurrent {return false}
if lhs.isLowPower != rhs.isLowPower {return false}
if lhs.isPowerSaving != rhs.isPowerSaving {return false}
if lhs.isAlwaysPowered != rhs.isAlwaysPowered {return false}
if lhs.onBatteryShutdownAfterSecs != rhs.onBatteryShutdownAfterSecs {return false}
if lhs.isPowerSaving != rhs.isPowerSaving {return false}
if lhs.adcMultiplierOverride != rhs.adcMultiplierOverride {return false}
if lhs.waitBluetoothSecs != rhs.waitBluetoothSecs {return false}
if lhs.meshSdsTimeoutSecs != rhs.meshSdsTimeoutSecs {return false}

View file

@ -19,6 +19,8 @@ struct NodeDetail: View {
var node: NodeInfoEntity
var body: some View {
let hwModelString = node.user?.hwModel ?? "UNSET"
HStack {
@ -87,6 +89,8 @@ struct NodeDetail: View {
HStack {
if self.bleManager.connectedPeripheral != nil && self.bleManager.connectedPeripheral.num == node.num && self.bleManager.connectedPeripheral.num == node.num {
if hwModelString == "TBEAM" || hwModelString == "TECHO" || hwModelString.contains("4631") {
Button(action: {
isPresentingShutdownConfirm = true
@ -111,35 +115,34 @@ struct NodeDetail: View {
let success = bleManager.sendShutdown(destNum: node.num, wantResponse: false)
}
}
}
Button(action: {
isPresentingRebootConfirm = true
Button(action: {
isPresentingRebootConfirm = true
}) {
Image(systemName: "arrow.triangle.2.circlepath")
.symbolRenderingMode(.hierarchical)
.imageScale(.small)
.foregroundColor(Color.accentColor)
Text("Reboot")
.font(.caption)
}) {
Image(systemName: "arrow.triangle.2.circlepath")
.symbolRenderingMode(.hierarchical)
.imageScale(.small)
.foregroundColor(Color.accentColor)
Text("Reboot")
.font(.caption)
}
.padding()
.background(Color(.systemGray6))
.clipShape(Capsule())
.confirmationDialog(
"Are you sure?",
isPresented: $isPresentingRebootConfirm
}
.padding()
.background(Color(.systemGray6))
.clipShape(Capsule())
.confirmationDialog(
"Are you sure?",
isPresented: $isPresentingRebootConfirm
) {
Button("Reboot Node?", role: .destructive) {
let success = bleManager.sendReboot(destNum: node.num, wantResponse: false)
Button("Reboot Node?", role: .destructive) {
let success = bleManager.sendReboot(destNum: node.num, wantResponse: false)
}
}
}
}
.padding(5)
Divider()

View file

@ -46,6 +46,7 @@ enum ScreenOnSeconds: Int, CaseIterable, Identifiable {
case fiveMinutes = 300
case tenMinutes = 600
case fifteenMinutes = 900
case max = 2147483647
var id: Int { self.rawValue }
var description: String {
@ -63,6 +64,8 @@ enum ScreenOnSeconds: Int, CaseIterable, Identifiable {
return "Ten Minutes"
case .fifteenMinutes:
return "Fifteen Minutes"
case .max:
return "Always On"
}
}
}
@ -107,9 +110,9 @@ struct DisplayConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State var isConnected: Bool = false
@State var gpsFormat: Config.DisplayConfig.GpsCoordinateFormat = .gpsFormatDec
@State var screenOnSeconds = 0
@State var screenCarouselInterval = 0
@State var gpsFormat = 0
var body: some View {
@ -118,9 +121,9 @@ struct DisplayConfig: View {
Form {
Section(header: Text("Timing")) {
Picker("Screen on for", selection: $gpsFormat ) {
ForEach(ScreenOnSeconds.allCases) { lu in
Text(lu.description)
Picker("Screen on for", selection: $screenOnSeconds ) {
ForEach(ScreenOnSeconds.allCases) { sos in
Text(sos.description)
}
}
.pickerStyle(DefaultPickerStyle())
@ -129,9 +132,9 @@ struct DisplayConfig: View {
.font(.caption)
.listRowSeparator(.visible)
Picker("Carousel Interval", selection: $gpsFormat ) {
ForEach(ScreenCarouselSeconds.allCases) { lu in
Text(lu.description)
Picker("Carousel Interval", selection: $screenCarouselInterval ) {
ForEach(ScreenCarouselSeconds.allCases) { scs in
Text(scs.description)
}
}
.pickerStyle(DefaultPickerStyle())

View file

@ -7,7 +7,6 @@
import SwiftUI
enum RegionCodes : Int, CaseIterable, Identifiable {
case unset = 0
@ -96,9 +95,9 @@ struct LoRaConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State var region: Config.LoRaConfig.RegionCode = .us
@State var modemPreset: Config.LoRaConfig.ModemPreset = .longFast
@State var region = 1
@State var modemPreset = 0
@State var numberOfHops = 0
var body: some View {
@ -130,9 +129,20 @@ struct LoRaConfig: View {
.listRowSeparator(.visible)
.listRowSeparator(.visible)
}
Section(header: Text("Mesh Options")) {
Picker("Number of hops", selection: $numberOfHops) {
ForEach(0..<8) {
if $0 == 0 {
Text("Default")
} else {
Text("\($0) Hops")
}
}
}
.pickerStyle(DefaultPickerStyle())
}
}
}
.navigationTitle("LoRa Config")
.navigationBarItems(trailing:

View file

@ -114,9 +114,9 @@ struct PositionConfig: View {
@State var smartPositionEnabled = true
@State var deviceGpsEnabled = true
@State var fixedPosition = false
@State var gpsUpdateInterval: Int32 = 0
@State var gpsAttemptTime: Int32 = 0
@State var positionBroadcastSeconds: Int32 = 0
@State var gpsUpdateInterval = 0
@State var gpsAttemptTime = 0
@State var positionBroadcastSeconds = 0
var body: some View {

View file

@ -0,0 +1,61 @@
//
// PowerConfig.swift
// Meshtastic Apple
//
// Copyright (c) Garth Vander Houwen 6/12/22.
//
import Foundation
import SwiftUI
struct PowerConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State var isPowerSaving = false
@State var isAlwaysPowered = false
var body: some View {
VStack {
Form {
Section(header: Text("States")) {
Toggle(isOn: $isPowerSaving) {
Label("Power Saving", systemImage: "powersleep")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Text("If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in we should try to minimize power consumption as much as possible.")
.font(.caption)
.listRowSeparator(.visible)
Toggle(isOn: $isAlwaysPowered) {
Label("Always Powered", systemImage: "powerplug.fill")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Text("Circumvents the logic block for determining whether the device is powered or not. Useful for devices with finicky ADC issues on the battery sense pins, or no battery pin at all.")
.font(.caption)
.listRowSeparator(.visible)
}
}
}
.navigationTitle("Power Config")
.navigationBarItems(trailing:
ZStack {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.lastFourCode : "????")
})
.onAppear {
self.bleManager.context = context
}
.navigationViewStyle(StackNavigationViewStyle())
}
}

View file

@ -64,7 +64,7 @@ struct Settings: View {
Text("Position")
}
NavigationLink {
PositionConfig()
PowerConfig()
} label: {
Image(systemName: "bolt")
@ -72,7 +72,6 @@ struct Settings: View {
Text("Power")
}
.disabled(true)
}
Section("Module Configuration") {