mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #84 from meshtastic/feature/new_config
Mock Up new Config Views
This commit is contained in:
commit
75f19d2dbe
9 changed files with 135 additions and 59 deletions
|
|
@ -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 */,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
61
MeshtasticApple/Views/Settings/PowerConfig.swift
Normal file
61
MeshtasticApple/Views/Settings/PowerConfig.swift
Normal 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())
|
||||
}
|
||||
}
|
||||
|
|
@ -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") {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue