mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #234 from meshtastic/2.0_Alpha_Launch
Bump Version, Code Cleanup
This commit is contained in:
commit
3bcfd70aed
12 changed files with 64 additions and 374 deletions
|
|
@ -964,7 +964,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -996,7 +996,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
|
|||
|
|
@ -7,22 +7,15 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
|
||||
func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> String {
|
||||
|
||||
var csvString: String = ""
|
||||
|
||||
if metricsType == 0 {
|
||||
|
||||
// Create Device Metrics Header
|
||||
csvString = "Battery Level, Voltage, Channel Utilization, Airtime, Timestamp"
|
||||
|
||||
for dm in telemetry{
|
||||
|
||||
if dm.metricsType == 0 {
|
||||
|
||||
csvString += "\n"
|
||||
csvString += String("\(dm.batteryLevel) %")
|
||||
csvString += String(dm.batteryLevel)
|
||||
csvString += ", "
|
||||
csvString += String(dm.voltage)
|
||||
csvString += ", "
|
||||
|
|
@ -33,18 +26,13 @@ func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin
|
|||
csvString += dm.time?.formattedDate(format: "yyyy-MM-dd HH:mm:ss") ?? "Unknown Age"
|
||||
}
|
||||
}
|
||||
|
||||
} else if metricsType == 1 {
|
||||
|
||||
// Create Environment Telemetry Header
|
||||
csvString = "Temperature, Relative Humidity, Barometric Pressure, Gas Resistance, Voltage, Current"
|
||||
|
||||
for dm in telemetry{
|
||||
|
||||
if dm.metricsType == 1 {
|
||||
|
||||
csvString += "\n"
|
||||
csvString += String("\(dm.temperature)°")
|
||||
csvString += String(dm.temperature)
|
||||
csvString += ", "
|
||||
csvString += String(dm.relativeHumidity)
|
||||
csvString += ", "
|
||||
|
|
@ -60,19 +48,14 @@ func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return csvString
|
||||
}
|
||||
|
||||
func PositionToCsvFile(positions: [PositionEntity]) -> String {
|
||||
|
||||
var csvString: String = ""
|
||||
|
||||
// Create Position Header
|
||||
csvString = "SeqNo, Latitude, Longitude, Alt, Sats, Speed, Heading, SNR, Timestamp"
|
||||
|
||||
for pos in positions {
|
||||
|
||||
csvString += "\n"
|
||||
csvString += String(pos.seqNo)
|
||||
csvString += ", "
|
||||
|
|
@ -90,9 +73,7 @@ func PositionToCsvFile(positions: [PositionEntity]) -> String {
|
|||
csvString += ", "
|
||||
csvString += String(pos.snr)
|
||||
csvString += ", "
|
||||
|
||||
csvString += pos.time?.formattedDate(format: "yyyy-MM-dd HH:mm:ss") ?? "Unknown Age"
|
||||
}
|
||||
|
||||
return csvString
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ extension PositionEntity {
|
|||
var coordinate: CLLocationCoordinate2D? {
|
||||
if latitudeI != 0 && longitudeI != 0 {
|
||||
let coord = CLLocationCoordinate2D(latitude: latitude!, longitude: longitude!)
|
||||
|
||||
return coord
|
||||
} else {
|
||||
return nil
|
||||
|
|
@ -36,10 +35,8 @@ extension PositionEntity {
|
|||
var annotaton: MKPointAnnotation {
|
||||
let pointAnn = MKPointAnnotation()
|
||||
if coordinate != nil {
|
||||
|
||||
pointAnn.coordinate = coordinate!
|
||||
}
|
||||
return pointAnn
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ struct NodeDetail: View {
|
|||
|
||||
@State private var showingDetailsPopover = false
|
||||
|
||||
@State var initialLoad: Bool = true
|
||||
@State var satsInView = 0
|
||||
@State private var showingShutdownConfirm: Bool = false
|
||||
@State private var showingRebootConfirm: Bool = false
|
||||
|
|
@ -416,12 +415,7 @@ struct NodeDetail: View {
|
|||
}
|
||||
)
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,7 @@ struct BluetoothConfig: View {
|
|||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var enabled = true
|
||||
@State var mode = 0
|
||||
@State var fixedPin = "123456"
|
||||
|
|
@ -132,40 +130,27 @@ struct BluetoothConfig: View {
|
|||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.enabled = node?.bluetoothConfig?.enabled ?? true
|
||||
self.mode = Int(node?.bluetoothConfig?.mode ?? 0)
|
||||
self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456)
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
self.enabled = node?.bluetoothConfig?.enabled ?? true
|
||||
self.mode = Int(node?.bluetoothConfig?.mode ?? 0)
|
||||
self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456)
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: enabled) { newEnabled in
|
||||
|
||||
if node != nil && node!.bluetoothConfig != nil {
|
||||
|
||||
if newEnabled != node!.bluetoothConfig!.enabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: mode) { newMode in
|
||||
|
||||
if node != nil && node!.bluetoothConfig != nil {
|
||||
|
||||
if newMode != node!.bluetoothConfig!.mode { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: fixedPin) { newFixedPin in
|
||||
|
||||
if node != nil && node!.bluetoothConfig != nil {
|
||||
|
||||
if newFixedPin != String(node!.bluetoothConfig!.fixedPin) { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,7 @@ struct LoRaConfig: View {
|
|||
var node: NodeInfoEntity?
|
||||
|
||||
@State var isPresentingSaveConfirm = false
|
||||
@State var initialLoad = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var region = 0
|
||||
@State var modemPreset = 0
|
||||
@State var hopLimit = 0
|
||||
|
|
@ -28,10 +26,8 @@ struct LoRaConfig: View {
|
|||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
Section(header: Text("Region")) {
|
||||
|
||||
Picker("Region", selection: $region ) {
|
||||
ForEach(RegionCodes.allCases) { r in
|
||||
Text(r.description)
|
||||
|
|
@ -52,7 +48,6 @@ struct LoRaConfig: View {
|
|||
.font(.caption)
|
||||
}
|
||||
Section(header: Text("Mesh Options")) {
|
||||
|
||||
Picker("Number of hops", selection: $hopLimit) {
|
||||
ForEach(HopValues.allCases) { hop in
|
||||
Text(hop.description)
|
||||
|
|
@ -64,13 +59,9 @@ struct LoRaConfig: View {
|
|||
}
|
||||
}
|
||||
.disabled(self.bleManager.connectedPeripheral == nil)
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
||||
|
|
@ -79,22 +70,18 @@ struct LoRaConfig: View {
|
|||
.controlSize(.large)
|
||||
.padding()
|
||||
.confirmationDialog(
|
||||
|
||||
"Are you sure you want to save?",
|
||||
isPresented: $isPresentingSaveConfirm,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Save Config for \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")") {
|
||||
|
||||
var lc = Config.LoRaConfig()
|
||||
lc.hopLimit = UInt32(hopLimit)
|
||||
lc.region = RegionCodes(rawValue: region)!.protoEnumValue()
|
||||
lc.modemPreset = ModemPresets(rawValue: modemPreset)!.protoEnumValue()
|
||||
lc.usePreset = true
|
||||
lc.txEnabled = true
|
||||
|
||||
let adminMessageId = bleManager.saveLoRaConfig(config: lc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
|
|
@ -107,53 +94,36 @@ struct LoRaConfig: View {
|
|||
}
|
||||
|
||||
} message: {
|
||||
|
||||
Text("After LoRa config saves the node will reboot.")
|
||||
}
|
||||
}
|
||||
.navigationTitle("LoRa Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
|
||||
self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 0)
|
||||
self.region = Int(node?.loRaConfig?.regionCode ?? 0)
|
||||
self.usePreset = node?.loRaConfig?.usePreset ?? true
|
||||
self.modemPreset = Int(node?.loRaConfig?.modemPreset ?? 0)
|
||||
self.txEnabled = node?.loRaConfig?.txEnabled ?? true
|
||||
self.txPower = Int(node?.loRaConfig?.txPower ?? 0)
|
||||
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 0)
|
||||
self.region = Int(node?.loRaConfig?.regionCode ?? 0)
|
||||
self.usePreset = node?.loRaConfig?.usePreset ?? true
|
||||
self.modemPreset = Int(node?.loRaConfig?.modemPreset ?? 0)
|
||||
self.txEnabled = node?.loRaConfig?.txEnabled ?? true
|
||||
self.txPower = Int(node?.loRaConfig?.txPower ?? 0)
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: region) { newRegion in
|
||||
|
||||
if node != nil && node!.loRaConfig != nil {
|
||||
|
||||
if newRegion != node!.loRaConfig!.regionCode { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: modemPreset) { newModemPreset in
|
||||
|
||||
if node != nil && node!.loRaConfig != nil {
|
||||
|
||||
if newModemPreset != node!.loRaConfig!.modemPreset { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: hopLimit) { newHopLimit in
|
||||
|
||||
if node != nil && node!.loRaConfig != nil {
|
||||
|
||||
if newHopLimit != node!.loRaConfig!.hopLimit { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ struct CannedMessagesConfig: View {
|
|||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges = false
|
||||
@State var hasMessagesChanges = false
|
||||
@State var configPreset = 0
|
||||
|
|
@ -213,7 +212,6 @@ struct CannedMessagesConfig: View {
|
|||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || (!hasChanges && !hasMessagesChanges))
|
||||
|
|
@ -222,7 +220,6 @@ struct CannedMessagesConfig: View {
|
|||
.controlSize(.large)
|
||||
.padding()
|
||||
.confirmationDialog(
|
||||
|
||||
"Are you sure?",
|
||||
isPresented: $isPresentingSaveConfirm,
|
||||
titleVisibility: .visible
|
||||
|
|
@ -230,24 +227,18 @@ struct CannedMessagesConfig: View {
|
|||
Button("Save Canned Messages Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
||||
|
||||
if hasChanges {
|
||||
|
||||
var cmc = ModuleConfig.CannedMessageConfig()
|
||||
cmc.enabled = enabled
|
||||
cmc.sendBell = sendBell
|
||||
cmc.rotary1Enabled = rotary1Enabled
|
||||
cmc.updown1Enabled = updown1Enabled
|
||||
if rotary1Enabled {
|
||||
|
||||
/// Input event origin accepted by the canned messages
|
||||
/// Can be e.g. "rotEnc1", "upDownEnc1", "cardkb", or keyword "_any"
|
||||
cmc.allowInputSource = "rotEnc1"
|
||||
|
||||
} else if updown1Enabled {
|
||||
|
||||
cmc.allowInputSource = "_any"
|
||||
|
||||
} else {
|
||||
|
||||
cmc.allowInputSource = "_any"
|
||||
}
|
||||
cmc.inputbrokerPinA = UInt32(inputbrokerPinA)
|
||||
|
|
@ -256,55 +247,41 @@ struct CannedMessagesConfig: View {
|
|||
cmc.inputbrokerEventCw = InputEventChars(rawValue: inputbrokerEventCw)!.protoEnumValue()
|
||||
cmc.inputbrokerEventCcw = InputEventChars(rawValue: inputbrokerEventCcw)!.protoEnumValue()
|
||||
cmc.inputbrokerEventPress = InputEventChars(rawValue: inputbrokerEventPress)!.protoEnumValue()
|
||||
|
||||
let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
// for now just disable the button after a successful save
|
||||
hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
if hasMessagesChanges {
|
||||
|
||||
let adminMessageId = bleManager.saveCannedMessageModuleMessages(messages: messages, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
// for now just disable the button after a successful save
|
||||
hasMessagesChanges = false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navigationTitle("Canned Messages Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
self.enabled = node?.cannedMessageConfig?.enabled ?? false
|
||||
self.sendBell = node?.cannedMessageConfig?.sendBell ?? false
|
||||
self.rotary1Enabled = node?.cannedMessageConfig?.rotary1Enabled ?? false
|
||||
self.updown1Enabled = node?.cannedMessageConfig?.updown1Enabled ?? false
|
||||
self.inputbrokerPinA = Int(node?.cannedMessageConfig?.inputbrokerPinA ?? 0)
|
||||
self.inputbrokerPinB = Int(node?.cannedMessageConfig?.inputbrokerPinB ?? 0)
|
||||
self.inputbrokerPinPress = Int(node?.cannedMessageConfig?.inputbrokerPinPress ?? 0)
|
||||
self.inputbrokerEventCw = Int(node?.cannedMessageConfig?.inputbrokerEventCw ?? 0)
|
||||
self.inputbrokerEventCcw = Int(node?.cannedMessageConfig?.inputbrokerEventCcw ?? 0)
|
||||
self.inputbrokerEventPress = Int(node?.cannedMessageConfig?.inputbrokerEventPress ?? 0)
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
self.enabled = node?.cannedMessageConfig?.enabled ?? false
|
||||
self.sendBell = node?.cannedMessageConfig?.sendBell ?? false
|
||||
self.rotary1Enabled = node?.cannedMessageConfig?.rotary1Enabled ?? false
|
||||
self.updown1Enabled = node?.cannedMessageConfig?.updown1Enabled ?? false
|
||||
self.inputbrokerPinA = Int(node?.cannedMessageConfig?.inputbrokerPinA ?? 0)
|
||||
self.inputbrokerPinB = Int(node?.cannedMessageConfig?.inputbrokerPinB ?? 0)
|
||||
self.inputbrokerPinPress = Int(node?.cannedMessageConfig?.inputbrokerPinPress ?? 0)
|
||||
self.inputbrokerEventCw = Int(node?.cannedMessageConfig?.inputbrokerEventCw ?? 0)
|
||||
self.inputbrokerEventCcw = Int(node?.cannedMessageConfig?.inputbrokerEventCcw ?? 0)
|
||||
self.inputbrokerEventPress = Int(node?.cannedMessageConfig?.inputbrokerEventPress ?? 0)
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: configPreset) { newPreset in
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,7 @@ struct ExternalNotificationConfig: View {
|
|||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var enabled = false
|
||||
@State var alertBell = false
|
||||
@State var alertMessage = false
|
||||
|
|
@ -67,50 +65,34 @@ struct ExternalNotificationConfig: View {
|
|||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
|
||||
Section(header: Text("Options")) {
|
||||
|
||||
Toggle(isOn: $enabled) {
|
||||
|
||||
Label("Enabled", systemImage: "megaphone")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
Toggle(isOn: $alertBell) {
|
||||
|
||||
Label("Alert when receiving a bell", systemImage: "bell")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
Toggle(isOn: $alertMessage) {
|
||||
|
||||
Label("Alert when receiving a message", systemImage: "message")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
|
||||
Section(header: Text("GPIO")) {
|
||||
|
||||
Toggle(isOn: $active) {
|
||||
|
||||
Label("Active", systemImage: "togglepower")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
Text("Specifies whether the external circuit is triggered when the device's GPIO is low or high.")
|
||||
.font(.caption)
|
||||
.listRowSeparator(.visible)
|
||||
|
||||
Picker("GPIO to monitor", selection: $output) {
|
||||
ForEach(0..<40) {
|
||||
|
||||
if $0 == 0 {
|
||||
|
||||
Text("Unset")
|
||||
|
||||
} else {
|
||||
|
||||
Text("Pin \($0)")
|
||||
}
|
||||
}
|
||||
|
|
@ -118,7 +100,6 @@ struct ExternalNotificationConfig: View {
|
|||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("Specifies the GPIO that your external circuit is attached to on the device.")
|
||||
.font(.caption)
|
||||
|
||||
Picker("GPIO Output Duration", selection: $outputMilliseconds ) {
|
||||
ForEach(OutputIntervals.allCases) { oi in
|
||||
Text(oi.description)
|
||||
|
|
@ -130,13 +111,9 @@ struct ExternalNotificationConfig: View {
|
|||
}
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
||||
|
|
@ -150,7 +127,6 @@ struct ExternalNotificationConfig: View {
|
|||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Save External Notification Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
||||
|
||||
var enc = ModuleConfig.ExternalNotificationConfig()
|
||||
enc.enabled = enabled
|
||||
enc.alertBell = alertBell
|
||||
|
|
@ -158,84 +134,58 @@ struct ExternalNotificationConfig: View {
|
|||
enc.active = active
|
||||
enc.output = UInt32(output)
|
||||
enc.outputMs = UInt32(outputMilliseconds)
|
||||
|
||||
let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0{
|
||||
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
// for now just disable the button after a successful save
|
||||
hasChanges = false
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navigationTitle("External Notification Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.enabled = node?.externalNotificationConfig?.enabled ?? false
|
||||
self.alertBell = node?.externalNotificationConfig?.alertBell ?? false
|
||||
self.alertMessage = node?.externalNotificationConfig?.alertMessage ?? false
|
||||
self.active = node?.externalNotificationConfig?.active ?? false
|
||||
self.output = Int(node?.externalNotificationConfig?.output ?? 0)
|
||||
self.outputMilliseconds = Int(node?.externalNotificationConfig?.outputMilliseconds ?? 0)
|
||||
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
self.enabled = node?.externalNotificationConfig?.enabled ?? false
|
||||
self.alertBell = node?.externalNotificationConfig?.alertBell ?? false
|
||||
self.alertMessage = node?.externalNotificationConfig?.alertMessage ?? false
|
||||
self.active = node?.externalNotificationConfig?.active ?? false
|
||||
self.output = Int(node?.externalNotificationConfig?.output ?? 0)
|
||||
self.outputMilliseconds = Int(node?.externalNotificationConfig?.outputMilliseconds ?? 0)
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: enabled) { newEnabled in
|
||||
|
||||
if node != nil && node!.externalNotificationConfig != nil {
|
||||
|
||||
if newEnabled != node!.externalNotificationConfig!.enabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: alertBell) { newAlertBell in
|
||||
|
||||
if node != nil && node!.externalNotificationConfig != nil {
|
||||
|
||||
if newAlertBell != node!.externalNotificationConfig!.alertBell { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: alertMessage) { newAlertMessage in
|
||||
|
||||
if node != nil && node!.externalNotificationConfig != nil {
|
||||
|
||||
if newAlertMessage != node!.externalNotificationConfig!.alertMessage { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: active) { newActuve in
|
||||
|
||||
if node != nil && node!.externalNotificationConfig != nil {
|
||||
|
||||
if newActuve != node!.externalNotificationConfig!.active { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: output) { newOutput in
|
||||
|
||||
if node != nil && node!.externalNotificationConfig != nil {
|
||||
|
||||
if newOutput != node!.externalNotificationConfig!.output { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: outputMilliseconds) { newOutputMs in
|
||||
|
||||
if node != nil && node!.externalNotificationConfig != nil {
|
||||
|
||||
if newOutputMs != node!.externalNotificationConfig!.outputMilliseconds { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,27 +52,20 @@ struct RangeTestConfig: View {
|
|||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var enabled = false
|
||||
@State var sender = 0
|
||||
@State var save = false
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
|
||||
Section(header: Text("Options")) {
|
||||
|
||||
Toggle(isOn: $enabled) {
|
||||
|
||||
Label("Enabled", systemImage: "figure.walk")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
Picker("Sender Interval", selection: $sender ) {
|
||||
ForEach(SenderIntervals.allCases) { sci in
|
||||
Text(sci.description)
|
||||
|
|
@ -81,26 +74,19 @@ struct RangeTestConfig: View {
|
|||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("This device will send out range test messages on the selected interval.")
|
||||
.font(.caption)
|
||||
|
||||
Toggle(isOn: $save) {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down.fill")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.disabled(!(node != nil && node!.myInfo?.hasWifi ?? false))
|
||||
|
||||
Text("Saves a CSV with the range test message details, currently only available on ESP32 devices with a web server.")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
.disabled(!(node != nil && node!.myInfo?.hasWifi ?? false))
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node!.myInfo?.hasWifi ?? false))
|
||||
|
|
@ -114,63 +100,44 @@ struct RangeTestConfig: View {
|
|||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Save Range Test Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
||||
|
||||
var rtc = ModuleConfig.RangeTestConfig()
|
||||
rtc.enabled = enabled
|
||||
rtc.save = save
|
||||
rtc.sender = UInt32(sender)
|
||||
|
||||
let adminMessageId = bleManager.saveRangeTestModuleConfig(config: rtc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
// for now just disable the button after a successful save
|
||||
hasChanges = false
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navigationTitle("Range Test Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
self.enabled = node?.rangeTestConfig?.enabled ?? false
|
||||
self.save = node?.rangeTestConfig?.save ?? false
|
||||
self.sender = Int(node?.rangeTestConfig?.sender ?? 0)
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
self.enabled = node?.rangeTestConfig?.enabled ?? false
|
||||
self.save = node?.rangeTestConfig?.save ?? false
|
||||
self.sender = Int(node?.rangeTestConfig?.sender ?? 0)
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: enabled) { newEnabled in
|
||||
|
||||
if node != nil && node!.rangeTestConfig != nil {
|
||||
|
||||
if newEnabled != node!.rangeTestConfig!.enabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: save) { newSave in
|
||||
|
||||
if node != nil && node!.rangeTestConfig != nil {
|
||||
|
||||
if newSave != node!.rangeTestConfig!.save { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: sender) { newSender in
|
||||
|
||||
if node != nil && node!.rangeTestConfig != nil {
|
||||
|
||||
if newSender != node!.rangeTestConfig!.sender { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,9 +74,7 @@ struct TelemetryConfig: View {
|
|||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var deviceUpdateInterval = 0
|
||||
@State var environmentUpdateInterval = 0
|
||||
@State var environmentMeasurementEnabled = false
|
||||
|
|
@ -86,11 +84,8 @@ struct TelemetryConfig: View {
|
|||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
|
||||
Section(header: Text("Update Intervals")) {
|
||||
|
||||
Picker("Device Metrics", selection: $deviceUpdateInterval ) {
|
||||
ForEach(UpdateIntervals.allCases) { ui in
|
||||
Text(ui.description)
|
||||
|
|
@ -99,7 +94,6 @@ struct TelemetryConfig: View {
|
|||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("How often device metrics are sent out over the mesh. Default is 15 minutes.")
|
||||
.font(.caption)
|
||||
|
||||
Picker("Sensor Metrics", selection: $environmentUpdateInterval ) {
|
||||
ForEach(UpdateIntervals.allCases) { ui in
|
||||
Text(ui.description)
|
||||
|
|
@ -109,39 +103,27 @@ struct TelemetryConfig: View {
|
|||
Text("How often sensor metrics are sent out over the mesh. Default is 15 minutes.")
|
||||
.font(.caption)
|
||||
}
|
||||
|
||||
Section(header: Text("Sensor Options")) {
|
||||
|
||||
Text("Supported I2C Connected sensors will be detected automatically, sensors are BMP280, BME280, BME680, MCP9808, INA219, INA260, LPS22 and SHTC3.")
|
||||
.font(.caption)
|
||||
|
||||
Toggle(isOn: $environmentMeasurementEnabled) {
|
||||
|
||||
Label("Enabled", systemImage: "chart.xyaxis.line")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
Toggle(isOn: $environmentScreenEnabled) {
|
||||
|
||||
Label("Show on device screen", systemImage: "display")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
Toggle(isOn: $environmentDisplayFahrenheit) {
|
||||
|
||||
Label("Display Fahrenheit", systemImage: "thermometer")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || node!.telemetryConfig == nil)
|
||||
|
|
@ -150,28 +132,22 @@ struct TelemetryConfig: View {
|
|||
.controlSize(.large)
|
||||
.padding()
|
||||
.confirmationDialog(
|
||||
|
||||
"Are you sure?",
|
||||
isPresented: $isPresentingSaveConfirm,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Save Telemetry Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
||||
|
||||
var tc = ModuleConfig.TelemetryConfig()
|
||||
tc.deviceUpdateInterval = UInt32(deviceUpdateInterval)
|
||||
tc.environmentUpdateInterval = UInt32(environmentUpdateInterval)
|
||||
tc.environmentMeasurementEnabled = environmentMeasurementEnabled
|
||||
tc.environmentScreenEnabled = environmentScreenEnabled
|
||||
tc.environmentDisplayFahrenheit = environmentDisplayFahrenheit
|
||||
|
||||
let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
// for now just disable the button after a successful save
|
||||
hasChanges = false
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
|
@ -180,57 +156,40 @@ struct TelemetryConfig: View {
|
|||
|
||||
.navigationTitle("Telemetry Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
self.deviceUpdateInterval = Int(node?.telemetryConfig?.deviceUpdateInterval ?? 0)
|
||||
self.environmentUpdateInterval = Int(node?.telemetryConfig?.environmentUpdateInterval ?? 0)
|
||||
self.environmentMeasurementEnabled = node?.telemetryConfig?.environmentMeasurementEnabled ?? false
|
||||
self.environmentScreenEnabled = node?.telemetryConfig?.environmentScreenEnabled ?? false
|
||||
self.environmentDisplayFahrenheit = node?.telemetryConfig?.environmentDisplayFahrenheit ?? false
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
self.deviceUpdateInterval = Int(node?.telemetryConfig?.deviceUpdateInterval ?? 0)
|
||||
self.environmentUpdateInterval = Int(node?.telemetryConfig?.environmentUpdateInterval ?? 0)
|
||||
self.environmentMeasurementEnabled = node?.telemetryConfig?.environmentMeasurementEnabled ?? false
|
||||
self.environmentScreenEnabled = node?.telemetryConfig?.environmentScreenEnabled ?? false
|
||||
self.environmentDisplayFahrenheit = node?.telemetryConfig?.environmentDisplayFahrenheit ?? false
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: deviceUpdateInterval) { newDeviceInterval in
|
||||
|
||||
if node != nil && node!.telemetryConfig != nil {
|
||||
|
||||
if newDeviceInterval != node!.telemetryConfig!.deviceUpdateInterval { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentUpdateInterval) { newEnvInterval in
|
||||
|
||||
if node != nil && node!.telemetryConfig != nil {
|
||||
|
||||
if newEnvInterval != node!.telemetryConfig!.environmentUpdateInterval { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentMeasurementEnabled) { newEnvEnabled in
|
||||
|
||||
if node != nil && node!.telemetryConfig != nil {
|
||||
|
||||
if newEnvEnabled != node!.telemetryConfig!.environmentMeasurementEnabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentScreenEnabled) { newEnvScreenEnabled in
|
||||
|
||||
if node!.telemetryConfig != nil {
|
||||
|
||||
if newEnvScreenEnabled != node!.telemetryConfig!.environmentScreenEnabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentDisplayFahrenheit) { newEnvDisplayF in
|
||||
|
||||
if node != nil && node!.telemetryConfig != nil {
|
||||
|
||||
if newEnvDisplayF != node!.telemetryConfig!.environmentDisplayFahrenheit { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,7 @@ struct NetworkConfig: View {
|
|||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges: Bool = false
|
||||
|
||||
@State var wifiEnabled = false
|
||||
@State var wifiSsid = ""
|
||||
@State var wifiPsk = ""
|
||||
|
|
@ -27,20 +25,14 @@ struct NetworkConfig: View {
|
|||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
|
||||
Section(header: Text("WiFi Options")) {
|
||||
|
||||
Text("Enabling WiFi will disable the bluetooth connection to the app.")
|
||||
.font(.title3)
|
||||
|
||||
Toggle(isOn: $wifiEnabled) {
|
||||
|
||||
Label("Enabled", systemImage: "wifi")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
HStack {
|
||||
Label("SSID", systemImage: "network")
|
||||
TextField("SSID", text: $wifiSsid)
|
||||
|
|
@ -48,16 +40,11 @@ struct NetworkConfig: View {
|
|||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.onChange(of: wifiSsid, perform: { value in
|
||||
|
||||
let totalBytes = wifiSsid.utf8.count
|
||||
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 32 {
|
||||
|
||||
let firstNBytes = Data(wifiSsid.utf8.prefix(32))
|
||||
|
||||
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
|
||||
|
||||
// Set the shortName back to the last place where it was the right size
|
||||
wifiSsid = maxBytesString
|
||||
}
|
||||
|
|
@ -67,7 +54,6 @@ struct NetworkConfig: View {
|
|||
.foregroundColor(.gray)
|
||||
}
|
||||
.keyboardType(.default)
|
||||
|
||||
HStack {
|
||||
Label("Password", systemImage: "wallet.pass")
|
||||
TextField("Password", text: $wifiPsk)
|
||||
|
|
@ -75,16 +61,11 @@ struct NetworkConfig: View {
|
|||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.onChange(of: wifiPsk, perform: { value in
|
||||
|
||||
let totalBytes = wifiPsk.utf8.count
|
||||
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 63 {
|
||||
|
||||
let firstNBytes = Data(wifiPsk.utf8.prefix(63))
|
||||
|
||||
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
|
||||
|
||||
// Set the shortName back to the last place where it was the right size
|
||||
wifiPsk = maxBytesString
|
||||
}
|
||||
|
|
@ -98,13 +79,9 @@ struct NetworkConfig: View {
|
|||
}
|
||||
.scrollDismissesKeyboard(.interactively)
|
||||
.disabled(!(node != nil && node!.myInfo?.hasWifi ?? false))
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
||||
|
|
@ -113,22 +90,17 @@ struct NetworkConfig: View {
|
|||
.controlSize(.large)
|
||||
.padding()
|
||||
.confirmationDialog(
|
||||
|
||||
"Are you sure you want to save?",
|
||||
isPresented: $isPresentingSaveConfirm,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Save Config for \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")") {
|
||||
|
||||
var network = Config.NetworkConfig()
|
||||
network.wifiEnabled = self.wifiEnabled
|
||||
network.wifiSsid = self.wifiSsid
|
||||
network.wifiPsk = self.wifiPsk
|
||||
|
||||
let adminMessageId = bleManager.saveWiFiConfig(config: network, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
// for now just disable the button after a successful save
|
||||
self.hasChanges = false
|
||||
|
|
@ -138,57 +110,39 @@ struct NetworkConfig: View {
|
|||
}
|
||||
}
|
||||
} message: {
|
||||
|
||||
Text("After network config saves the node will reboot.")
|
||||
}
|
||||
}
|
||||
.navigationTitle("Network Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.wifiEnabled = (node?.networkConfig?.wifiEnabled ?? false)
|
||||
self.wifiSsid = node?.networkConfig?.wifiSsid ?? ""
|
||||
self.wifiPsk = node?.networkConfig?.wifiPsk ?? ""
|
||||
self.wifiMode = Int(node?.networkConfig?.wifiMode ?? 0)
|
||||
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
self.wifiEnabled = (node?.networkConfig?.wifiEnabled ?? false)
|
||||
self.wifiSsid = node?.networkConfig?.wifiSsid ?? ""
|
||||
self.wifiPsk = node?.networkConfig?.wifiPsk ?? ""
|
||||
self.wifiMode = Int(node?.networkConfig?.wifiMode ?? 0)
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: wifiEnabled) { newEnabled in
|
||||
|
||||
if node != nil && node!.networkConfig != nil {
|
||||
|
||||
if newEnabled != node!.networkConfig!.wifiEnabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: wifiSsid) { newSSID in
|
||||
|
||||
if node != nil && node!.networkConfig != nil {
|
||||
|
||||
if newSSID != node!.networkConfig!.wifiSsid { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: wifiPsk) { newPsk in
|
||||
|
||||
if node != nil && node!.networkConfig != nil {
|
||||
|
||||
if newPsk != node!.networkConfig!.wifiPsk { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: wifiMode) { newMode in
|
||||
|
||||
if node != nil && node!.networkConfig != nil {
|
||||
|
||||
if newMode != node!.networkConfig!.wifiMode { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,61 +15,44 @@ struct UserConfig: View {
|
|||
|
||||
@State private var isPresentingFactoryResetConfirm: Bool = false
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var shortName = ""
|
||||
@State var longName = ""
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
|
||||
Section(header: Text("USER DETAILS")) {
|
||||
|
||||
HStack {
|
||||
Label("Long Name", systemImage: "person.crop.rectangle.fill")
|
||||
TextField("Long Name", text: $longName)
|
||||
.onChange(of: longName, perform: { value in
|
||||
|
||||
let totalBytes = longName.utf8.count
|
||||
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 36 {
|
||||
|
||||
let firstNBytes = Data(longName.utf8.prefix(36))
|
||||
|
||||
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
|
||||
|
||||
// Set the longName back to the last place where it was the right size
|
||||
longName = maxBytesString
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
.keyboardType(.default)
|
||||
.disableAutocorrection(true)
|
||||
Text("Long name can be up to 36 bytes long.")
|
||||
.font(.caption)
|
||||
|
||||
HStack {
|
||||
Label("Short Name", systemImage: "circlebadge.fill")
|
||||
TextField("Long Name", text: $shortName)
|
||||
.foregroundColor(.gray)
|
||||
.onChange(of: shortName, perform: { value in
|
||||
|
||||
let totalBytes = shortName.utf8.count
|
||||
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 4 {
|
||||
|
||||
let firstNBytes = Data(shortName.utf8.prefix(4))
|
||||
|
||||
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
|
||||
|
||||
// Set the shortName back to the last place where it was the right size
|
||||
shortName = maxBytesString
|
||||
}
|
||||
|
|
@ -81,20 +64,13 @@ struct UserConfig: View {
|
|||
.disableAutocorrection(true)
|
||||
Text("The short name is used in maps and messaging and will be appended to the last 4 of the device MAC address to set the device's BLE Name. It can be up to 4 bytes long.")
|
||||
.font(.caption)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
HStack {
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
||||
|
|
@ -103,63 +79,43 @@ struct UserConfig: View {
|
|||
.controlSize(.large)
|
||||
.padding()
|
||||
.confirmationDialog(
|
||||
|
||||
"Are you sure you want to save?",
|
||||
isPresented: $isPresentingSaveConfirm,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Save User Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
||||
|
||||
var u = User()
|
||||
u.shortName = shortName
|
||||
u.longName = longName
|
||||
|
||||
let adminMessageId = bleManager.saveUser(config: u, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
hasChanges = false
|
||||
}
|
||||
}
|
||||
} message: {
|
||||
|
||||
Text("After user config saves the node will reboot.")
|
||||
}
|
||||
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
|
||||
.navigationTitle("User Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.shortName = node?.user!.shortName ?? ""
|
||||
self.longName = node?.user!.longName ?? ""
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
self.bleManager.context = context
|
||||
self.shortName = node?.user!.shortName ?? ""
|
||||
self.longName = node?.user!.longName ?? ""
|
||||
self.hasChanges = false
|
||||
}
|
||||
.onChange(of: shortName) { newShort in
|
||||
|
||||
if node != nil && node!.user != nil {
|
||||
|
||||
if newShort != node?.user!.shortName { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: longName) { newLong in
|
||||
|
||||
if node != nil && node!.user != nil {
|
||||
|
||||
if newLong != node?.user!.longName { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue