Merge pull request #336 from meshtastic/2.1.2_Working_Changes

2.1.2 working changes
This commit is contained in:
Garth Vander Houwen 2023-03-19 18:46:00 -07:00 committed by GitHub
commit 57f39ad5de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 386 additions and 346 deletions

View file

@ -1188,7 +1188,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.1.2;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
@ -1222,7 +1222,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.1.2;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;

View file

@ -10,27 +10,27 @@ import Foundation
enum HardwareModels: String, CaseIterable, Identifiable {
case UNSET
case TLORA_V2
case TLORA_V1
case TLORA_V2_1_1P6
case TLORAV2
case TLORAV1
case TLORAV211P6
case TBEAM
case HELTEC_V2_0
case TBEAM_V0P7
case T_ECHO
case TLORA_V1_1P3
case HELTECV20
case TBEAMV0P7
case TECHO
case TLORAV11P3
case RAK4631
case HELTEC_V2_1
case HELTEC_V1
case LILYGO_TBEAM_S3_CORE
case HELTECV21
case HELTECV1
case LILYGOTBEAMS3CORE
case RAK11200
case NANO_G1
case TLORA_V2_1_1P8
case TLORA_T3_S3
case NANO_G1_EXPLORER
case STATION_G1
case NANOG1
case TLORAV211P8
case TLORAT3S3
case NANOG1EXPLORER
case STATIONG1
case M5STACK
case HELTEC_V3
case HELTEC_WSL_V3
case HELTECV3
case HELTECWSLV3
var id: String { self.rawValue }
var description: String {
@ -38,47 +38,47 @@ enum HardwareModels: String, CaseIterable, Identifiable {
case .UNSET:
return NSLocalizedString("unset", comment: "UNSET")
case .TLORA_V2:
case .TLORAV2:
return "TLoRa V2"
case .TLORA_V1:
case .TLORAV1:
return "TLoRa V1"
case .TLORA_V2_1_1P6:
case .TLORAV211P6:
return "TLoRa V2.1.1.6"
case .TBEAM:
return "TBeam"
case .HELTEC_V2_0:
case .HELTECV20:
return "HELTEC V2.0"
case .TBEAM_V0P7:
case .TBEAMV0P7:
return "TBeam 0.7"
case .T_ECHO:
case .TECHO:
return "TEcho"
case .TLORA_V1_1P3:
case .TLORAV11P3:
return "TLORA V1.1.3"
case .RAK4631:
return "RAK 4631 NRF"
case .HELTEC_V2_1:
case .HELTECV21:
return "HELTEC V2.1"
case .HELTEC_V1:
case .HELTECV1:
return "HELTEC V1"
case .LILYGO_TBEAM_S3_CORE:
case .LILYGOTBEAMS3CORE:
return "TBEAM S3"
case .RAK11200:
return "RAK 11200 ESP32"
case .NANO_G1:
case .NANOG1:
return "Nano G1"
case .TLORA_V2_1_1P8:
case .TLORAV211P8:
return "TLoRa V2.1.1.8"
case .TLORA_T3_S3:
case .TLORAT3S3:
return "TLoRa T3 S3"
case .NANO_G1_EXPLORER:
case .NANOG1EXPLORER:
return "Nano G1 Explorer"
case .STATION_G1:
case .STATIONG1:
return "Station G1"
case .M5STACK:
return "M5 Stack"
case .HELTEC_V3:
case .HELTECV3:
return "Heltec V3"
case .HELTEC_WSL_V3:
case .HELTECWSLV3:
return "Heltec wireless stick lite V3"
}
@ -88,47 +88,47 @@ enum HardwareModels: String, CaseIterable, Identifiable {
case .UNSET:
return []
case .TLORA_V2:
case .TLORAV2:
return ["firmware-tlora-v2-"]
case .TLORA_V1:
case .TLORAV1:
return ["firmware-tlora-v1-"]
case .TLORA_V2_1_1P6:
case .TLORAV211P6:
return ["firmware-tlora-v2-1-1.6-"]
case .TBEAM:
return ["firmware-tbeam-"]
case .HELTEC_V2_0:
case .HELTECV20:
return ["firmware-heltec-v2.0-"]
case .TBEAM_V0P7:
case .TBEAMV0P7:
return ["firmware-tbeam0.7-"]
case .T_ECHO:
case .TECHO:
return ["firmware-t-echo-"]
case .TLORA_V1_1P3:
case .TLORAV11P3:
return ["firmware-tlora_v1_3-"]
case .RAK4631:
return ["firmware-rak4631-", "firmware-rak4631_eink-"]
case .HELTEC_V2_1:
case .HELTECV21:
return ["firmware-heltec-v2.1-"]
case .HELTEC_V1:
case .HELTECV1:
return ["firmware-heltec-v1-"]
case .LILYGO_TBEAM_S3_CORE:
case .LILYGOTBEAMS3CORE:
return ["firmware-tbeam-s3-core-"]
case .RAK11200:
return ["firmware-rak11200-"]
case .NANO_G1:
case .NANOG1:
return ["firmware-nano-g1-"]
case .TLORA_V2_1_1P8:
case .TLORAV211P8:
return ["firmware-tlora-v2-1-1.8-"]
case .TLORA_T3_S3:
case .TLORAT3S3:
return ["firmware-tlora-t3s3-v1-"]
case .NANO_G1_EXPLORER:
case .NANOG1EXPLORER:
return ["firmware-nano-g1-explorer-"]
case .STATION_G1:
case .STATIONG1:
return ["firmware-station-g1-"]
case .M5STACK:
return ["firmware-m5stack-core-", "firmware-m5stack-coreink-"]
case .HELTEC_V3:
case .HELTECV3:
return ["firmware-heltec-v3-"]
case .HELTEC_WSL_V3:
case .HELTECWSLV3:
return ["firmware-heltec-wsl-v3-"]
}
@ -138,49 +138,49 @@ enum HardwareModels: String, CaseIterable, Identifiable {
switch self {
case .UNSET:
return HardwarePlatforms.NONE
case .TLORA_V2:
return HardwarePlatforms.ESP32
case .TLORA_V1:
return HardwarePlatforms.ESP32
case .TLORA_V2_1_1P6:
return HardwarePlatforms.ESP32
return HardwarePlatforms.none
case .TLORAV2:
return HardwarePlatforms.esp32
case .TLORAV1:
return HardwarePlatforms.esp32
case .TLORAV211P6:
return HardwarePlatforms.esp32
case .TBEAM:
return HardwarePlatforms.ESP32
case .HELTEC_V2_0:
return HardwarePlatforms.ESP32
case .TBEAM_V0P7:
return HardwarePlatforms.ESP32
case .T_ECHO:
return HardwarePlatforms.NRF52
case .TLORA_V1_1P3:
return HardwarePlatforms.ESP32
return HardwarePlatforms.esp32
case .HELTECV20:
return HardwarePlatforms.esp32
case .TBEAMV0P7:
return HardwarePlatforms.esp32
case .TECHO:
return HardwarePlatforms.nrf52
case .TLORAV11P3:
return HardwarePlatforms.esp32
case .RAK4631:
return HardwarePlatforms.NRF52
case .HELTEC_V2_1:
return HardwarePlatforms.ESP32
case .HELTEC_V1:
return HardwarePlatforms.ESP32
case .LILYGO_TBEAM_S3_CORE:
return HardwarePlatforms.ESP32
return HardwarePlatforms.nrf52
case .HELTECV21:
return HardwarePlatforms.esp32
case .HELTECV1:
return HardwarePlatforms.esp32
case .LILYGOTBEAMS3CORE:
return HardwarePlatforms.esp32
case .RAK11200:
return HardwarePlatforms.ESP32
case .NANO_G1:
return HardwarePlatforms.ESP32
case .TLORA_V2_1_1P8:
return HardwarePlatforms.ESP32
case .TLORA_T3_S3:
return HardwarePlatforms.ESP32
case .NANO_G1_EXPLORER:
return HardwarePlatforms.ESP32
case .STATION_G1:
return HardwarePlatforms.ESP32
return HardwarePlatforms.esp32
case .NANOG1:
return HardwarePlatforms.esp32
case .TLORAV211P8:
return HardwarePlatforms.esp32
case .TLORAT3S3:
return HardwarePlatforms.esp32
case .NANOG1EXPLORER:
return HardwarePlatforms.esp32
case .STATIONG1:
return HardwarePlatforms.esp32
case .M5STACK:
return HardwarePlatforms.ESP32
case .HELTEC_V3:
return HardwarePlatforms.ESP32
case .HELTEC_WSL_V3:
return HardwarePlatforms.ESP32
return HardwarePlatforms.esp32
case .HELTECV3:
return HardwarePlatforms.esp32
case .HELTECWSLV3:
return HardwarePlatforms.esp32
}
}
func protoEnumValue() -> HardwareModel {
@ -189,47 +189,47 @@ enum HardwareModels: String, CaseIterable, Identifiable {
case .UNSET:
return HardwareModel.unset
case .TLORA_V2:
case .TLORAV2:
return HardwareModel.tloraV2
case .TLORA_V1:
case .TLORAV1:
return HardwareModel.tloraV1
case .TLORA_V2_1_1P6:
case .TLORAV211P6:
return HardwareModel.tloraV211P6
case .TBEAM:
return HardwareModel.tbeam
case .HELTEC_V2_0:
case .HELTECV20:
return HardwareModel.heltecV20
case .TBEAM_V0P7:
case .TBEAMV0P7:
return HardwareModel.tbeamV0P7
case .T_ECHO:
case .TECHO:
return HardwareModel.tEcho
case .TLORA_V1_1P3:
case .TLORAV11P3:
return HardwareModel.tloraV11P3
case .RAK4631:
return HardwareModel.rak4631
case .HELTEC_V2_1:
case .HELTECV21:
return HardwareModel.heltecV21
case .HELTEC_V1:
case .HELTECV1:
return HardwareModel.heltecV1
case .LILYGO_TBEAM_S3_CORE:
case .LILYGOTBEAMS3CORE:
return HardwareModel.lilygoTbeamS3Core
case .RAK11200:
return HardwareModel.rak11200
case .NANO_G1:
case .NANOG1:
return HardwareModel.nanoG1
case .TLORA_V2_1_1P8:
case .TLORAV211P8:
return HardwareModel.tloraV211P8
case .TLORA_T3_S3:
case .TLORAT3S3:
return HardwareModel.tloraT3S3
case .NANO_G1_EXPLORER:
case .NANOG1EXPLORER:
return HardwareModel.nanoG1Explorer
case .STATION_G1:
case .STATIONG1:
return HardwareModel.stationG1
case .M5STACK:
return HardwareModel.m5Stack
case .HELTEC_V3:
case .HELTECV3:
return HardwareModel.heltecV3
case .HELTEC_WSL_V3:
case .HELTECWSLV3:
return HardwareModel.heltecWslV3
}
}
@ -238,24 +238,24 @@ enum HardwareModels: String, CaseIterable, Identifiable {
enum HardwarePlatforms: String, CaseIterable, Identifiable {
case NONE
case ESP32
case NRF52
case STM32
case PIPICO
case none
case esp32
case nrf52
case stm32
case piPico
var id: String { self.rawValue }
var description: String {
switch self {
case .NONE:
case .none:
return "None"
case .ESP32:
case .esp32:
return "Expressif ESP 32"
case .NRF52:
case .nrf52:
return "Nordic NRF52"
case .STM32:
case .stm32:
return "ARM STM 32"
case .PIPICO:
case .piPico:
return "Raspberrry Pi Pico"
}
}

View file

@ -449,6 +449,9 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
} else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) {
upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) {
upsertDisplayConfigPacket(config: config.display, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) {
upsertLoRaConfigPacket(config: config.lora, nodeNum: Int64(packet.from), context: context)

View file

@ -160,7 +160,7 @@ struct Connect: View {
if !self.bleManager.isConnected {
Section(header: Text("available.radios").font(.title)) {
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.name > $1.name })) { peripheral in
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.name < $1.name })) { peripheral in
HStack {
if userSettings.preferredPeripheralId == peripheral.peripheral.identifier.uuidString {
Image(systemName: "star.fill")

View file

@ -21,7 +21,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
let mapViewType: MKMapType
let userTrackingMode: MKUserTrackingMode
let centeringMode: CenteringMode
let showBreadcrumbLines: Bool
let centerOnPositionsOnly: Bool
@AppStorage("meshMapRecentering") private var recenter: Bool = false
@ -120,6 +120,16 @@ struct MapViewSwiftUI: UIViewRepresentable {
DispatchQueue.main.async {
self.presentCustomMapOverlayHash = self.customMapOverlay
self.loadedLastUpdatedLocalMapFile = self.lastUpdatedLocalMapFile
if showBreadcrumbLines {
let nodePositions = positions.filter { $0.time! >= Calendar.current.startOfDay(for: Date()) }
let lineCoords = nodePositions.map ({
(position) -> CLLocationCoordinate2D in
return position.nodeCoordinate!
})
let polyline = MKPolyline(coordinates: lineCoords, count: nodePositions.count)
mapView.addOverlay(polyline)
}
}
}
@ -334,45 +344,16 @@ struct MapViewSwiftUI: UIViewRepresentable {
public func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let index = self.overlays.firstIndex(where: { overlay_ in overlay_.shape.hash == overlay.hash }) {
let unwrappedOverlay = self.overlays[index]
if let circleOverlay = unwrappedOverlay.shape as? MKCircle {
let renderer = MKCircleRenderer(circle: circleOverlay)
renderer.fillColor = unwrappedOverlay.fillColor
renderer.strokeColor = unwrappedOverlay.strokeColor
renderer.lineWidth = unwrappedOverlay.lineWidth
return renderer
} else if let polygonOverlay = unwrappedOverlay.shape as? MKPolygon {
let renderer = MKPolygonRenderer(polygon: polygonOverlay)
renderer.fillColor = unwrappedOverlay.fillColor
renderer.strokeColor = unwrappedOverlay.strokeColor
renderer.lineWidth = unwrappedOverlay.lineWidth
return renderer
} else if let multiPolygonOverlay = unwrappedOverlay.shape as? MKMultiPolygon {
let renderer = MKMultiPolygonRenderer(multiPolygon: multiPolygonOverlay)
renderer.fillColor = unwrappedOverlay.fillColor
renderer.strokeColor = unwrappedOverlay.strokeColor
renderer.lineWidth = unwrappedOverlay.lineWidth
return renderer
} else if let polyLineOverlay = unwrappedOverlay.shape as? MKPolyline {
let renderer = MKPolylineRenderer(polyline: polyLineOverlay)
renderer.fillColor = unwrappedOverlay.fillColor
renderer.strokeColor = unwrappedOverlay.strokeColor
renderer.lineWidth = unwrappedOverlay.lineWidth
return renderer
} else if let multiPolylineOverlay = unwrappedOverlay.shape as? MKMultiPolyline {
let renderer = MKMultiPolylineRenderer(multiPolyline: multiPolylineOverlay)
renderer.fillColor = unwrappedOverlay.fillColor
renderer.strokeColor = unwrappedOverlay.strokeColor
renderer.lineWidth = unwrappedOverlay.lineWidth
return renderer
} else {
return MKOverlayRenderer()
}
} else if let tileOverlay = overlay as? MKTileOverlay {
if let tileOverlay = overlay as? MKTileOverlay {
return MKTileOverlayRenderer(tileOverlay: tileOverlay)
} else {
if let routePolyline = overlay as? MKPolyline {
let renderer = MKPolylineRenderer(polyline: routePolyline)
renderer.strokeColor = UIColor.systemIndigo
renderer.lineWidth = 5
return renderer
}
return MKOverlayRenderer()
}
}

View file

@ -71,10 +71,10 @@ struct NodeDetail: View {
mapViewType: mapType,
userTrackingMode: MKUserTrackingMode.none,
centeringMode: .allPositions,
showBreadcrumbLines: false,
centerOnPositionsOnly: true,
customMapOverlay: self.customMapOverlay,
overlays: self.overlays
)
VStack(alignment: .leading) {
Spacer()
@ -486,29 +486,6 @@ struct NodeDetail: View {
mapType = .hybridFlyover
}
}
.task(id: node.num) {
do {
if node.positions?.count ?? 0 > 0 {
let mostRecent = node.positions?.lastObject as? PositionEntity
let weather = try await WeatherService.shared.weather(for: mostRecent?.nodeLocation ?? CLLocation(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude))
condition = weather.currentWeather.condition
temperature = weather.currentWeather.temperature
humidity = Int(weather.currentWeather.humidity * 100)
symbolName = weather.currentWeather.symbolName
let attribution = try await WeatherService.shared.attribution
attributionLink = attribution.legalPageURL
attributionLogo = colorScheme == .light ? attribution.combinedMarkLightURL : attribution.combinedMarkDarkURL
}
} catch {
print("Could not gather weather information...", error.localizedDescription)
condition = .clear
symbolName = "cloud.fill"
}
}
}
}
}

View file

@ -84,6 +84,7 @@ struct NodeMap: View {
mapViewType: mapType,
userTrackingMode: userTrackingMode,
centeringMode: mapCenteringMode,
showBreadcrumbLines: false,
centerOnPositionsOnly: false,
customMapOverlay: self.customMapOverlay,
overlays: self.overlays

View file

@ -40,6 +40,9 @@ struct BluetoothConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setBluetoothValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -135,10 +138,7 @@ struct BluetoothConfig: View {
})
.onAppear {
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
setBluetoothValues()
// Need to request a BluetoothConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.bluetoothConfig == nil {
print("empty bluetooth config")
@ -164,4 +164,10 @@ struct BluetoothConfig: View {
}
}
}
func setBluetoothValues() {
self.enabled = node?.bluetoothConfig?.enabled ?? true
self.mode = Int(node?.bluetoothConfig?.mode ?? 0)
self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456)
self.hasChanges = false
}
}

View file

@ -7,35 +7,35 @@
import SwiftUI
struct DeviceConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingNodeDBResetConfirm = false
@State private var isPresentingFactoryResetConfirm = false
@State private var isPresentingSaveConfirm = false
@State var hasChanges = false
@State var deviceRole = 0
@State var buzzerGPIO = 0
@State var buttonGPIO = 0
@State var serialEnabled = true
@State var debugLogEnabled = false
@State var rebroadcastMode = 0
var body: some View {
VStack {
Form {
if node != nil && node?.metadata == nil && node?.num ?? 0 != bleManager.connectedPeripheral?.num ?? 0 {
Text("There has been no response to a request for device metadata over the admin channel for this node.")
.font(.callout)
.foregroundColor(.orange)
} else if node != nil && node?.num ?? 0 != bleManager.connectedPeripheral?.num ?? 0 {
// Let users know what is going on if they are using remote admin and don't have the config yet
if node?.deviceConfig == nil {
@ -45,6 +45,9 @@ struct DeviceConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setDeviceValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -55,7 +58,7 @@ struct DeviceConfig: View {
.foregroundColor(.orange)
}
Section(header: Text("options")) {
Picker("Device Role", selection: $deviceRole ) {
ForEach(DeviceRoles.allCases) { dr in
Text(dr.name)
@ -66,7 +69,7 @@ struct DeviceConfig: View {
Text(DeviceRoles(rawValue: deviceRole)?.description ?? "")
.foregroundColor(.gray)
.font(.caption)
Picker("Rebroadcast Mode", selection: $rebroadcastMode ) {
ForEach(RebroadcastModes.allCases) { rm in
Text(rm.name)
@ -78,24 +81,24 @@ struct DeviceConfig: View {
.foregroundColor(.gray)
.font(.caption)
}
Section(header: Text("Debug")) {
Toggle(isOn: $serialEnabled) {
Label("Serial Console", systemImage: "terminal")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $debugLogEnabled) {
Label("Debug Log", systemImage: "ant.fill")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
Section(header: Text("GPIO")) {
Picker("Button GPIO", selection: $buttonGPIO) {
ForEach(0..<40) {
if $0 == 0 {
@ -117,14 +120,14 @@ struct DeviceConfig: View {
}
.pickerStyle(DefaultPickerStyle())
}
}
.disabled(self.bleManager.connectedPeripheral == nil || node?.deviceConfig == nil)
// Only show these buttons for the BLE connected node
if bleManager.connectedPeripheral != nil && node?.num ?? -1 == bleManager.connectedPeripheral.num {
HStack {
Button("Reset NodeDB", role: .destructive) {
isPresentingNodeDBResetConfirm = true
}
@ -139,7 +142,7 @@ struct DeviceConfig: View {
titleVisibility: .visible
) {
Button("Erase all device and app data?", role: .destructive) {
if bleManager.sendNodeDBReset(fromUser: node!.user!, toUser: node!.user!) {
bleManager.disconnectPeripheral()
clearCoreDataDatabase(context: context)
@ -162,23 +165,23 @@ struct DeviceConfig: View {
titleVisibility: .visible
) {
Button("Factory reset your device and app? ", role: .destructive) {
if bleManager.sendFactoryReset(fromUser: node!.user!, toUser: node!.user!) {
bleManager.disconnectPeripheral()
clearCoreDataDatabase(context: context)
} else {
print("Factory Reset Failed")
}
}
}
}
}
HStack {
Button {
isPresentingSaveConfirm = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
@ -188,7 +191,7 @@ struct DeviceConfig: View {
.controlSize(.large)
.padding()
.confirmationDialog(
"are.you.sure",
isPresented: $isPresentingSaveConfirm,
titleVisibility: .visible
@ -204,7 +207,7 @@ struct DeviceConfig: View {
dc.debugLogEnabled = debugLogEnabled
dc.buttonGpio = UInt32(buttonGPIO)
dc.buzzerGpio = UInt32(buzzerGPIO)
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
@ -215,26 +218,21 @@ struct DeviceConfig: View {
}
}
}
message: {
Text("config.save.confirm")
}
message: {
Text("config.save.confirm")
}
}
Spacer()
}
.navigationTitle("device.config")
.navigationBarItems(trailing:
ZStack {
ZStack {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
.onAppear {
self.bleManager.context = context
self.deviceRole = Int(node?.deviceConfig?.role ?? 0)
self.serialEnabled = (node?.deviceConfig?.serialEnabled ?? true)
self.debugLogEnabled = node?.deviceConfig?.debugLogEnabled ?? false
self.buttonGPIO = Int(node?.deviceConfig?.buttonGpio ?? 0)
self.buzzerGPIO = Int(node?.deviceConfig?.buzzerGpio ?? 0)
self.hasChanges = false
setDeviceValues()
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.deviceConfig == nil {
print("empty device config")
@ -245,39 +243,47 @@ struct DeviceConfig: View {
}
}
.onChange(of: deviceRole) { newRole in
if node != nil && node!.deviceConfig != nil {
if newRole != node!.deviceConfig!.role { hasChanges = true }
}
}
.onChange(of: serialEnabled) { newSerial in
if node != nil && node!.deviceConfig != nil {
if newSerial != node!.deviceConfig!.serialEnabled { hasChanges = true }
}
}
.onChange(of: debugLogEnabled) { newDebugLog in
if node != nil && node!.deviceConfig != nil {
if newDebugLog != node!.deviceConfig!.debugLogEnabled { hasChanges = true }
}
}
.onChange(of: buttonGPIO) { newButtonGPIO in
if node != nil && node!.deviceConfig != nil {
if newButtonGPIO != node!.deviceConfig!.buttonGpio { hasChanges = true }
}
}
.onChange(of: buzzerGPIO) { newBuzzerGPIO in
if node != nil && node!.deviceConfig != nil {
if newBuzzerGPIO != node!.deviceConfig!.buttonGpio { hasChanges = true }
}
}
}
func setDeviceValues() {
self.deviceRole = Int(node?.deviceConfig?.role ?? 0)
self.serialEnabled = (node?.deviceConfig?.serialEnabled ?? true)
self.debugLogEnabled = node?.deviceConfig?.debugLogEnabled ?? false
self.buttonGPIO = Int(node?.deviceConfig?.buttonGpio ?? 0)
self.buzzerGPIO = Int(node?.deviceConfig?.buzzerGpio ?? 0)
self.hasChanges = false
}
}

View file

@ -43,6 +43,9 @@ struct DisplayConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setDisplayValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -173,14 +176,7 @@ struct DisplayConfig: View {
})
.onAppear {
self.bleManager.context = context
self.gpsFormat = Int(node?.displayConfig?.gpsFormat ?? 0)
self.screenOnSeconds = Int(node?.displayConfig?.screenOnSeconds ?? 0)
self.screenCarouselInterval = Int(node?.displayConfig?.screenCarouselInterval ?? 0)
self.compassNorthTop = node?.displayConfig?.compassNorthTop ?? false
self.flipScreen = node?.displayConfig?.flipScreen ?? false
self.oledType = Int(node?.displayConfig?.oledType ?? 0)
self.displayMode = Int(node?.displayConfig?.displayMode ?? 0)
self.hasChanges = false
setDisplayValues()
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.displayConfig == nil {
@ -227,4 +223,15 @@ struct DisplayConfig: View {
}
}
}
func setDisplayValues() {
self.gpsFormat = Int(node?.displayConfig?.gpsFormat ?? 0)
self.screenOnSeconds = Int(node?.displayConfig?.screenOnSeconds ?? 0)
self.screenCarouselInterval = Int(node?.displayConfig?.screenCarouselInterval ?? 0)
self.compassNorthTop = node?.displayConfig?.compassNorthTop ?? false
self.flipScreen = node?.displayConfig?.flipScreen ?? false
self.oledType = Int(node?.displayConfig?.oledType ?? 0)
self.displayMode = Int(node?.displayConfig?.displayMode ?? 0)
self.hasChanges = false
}
}

View file

@ -30,7 +30,7 @@ struct LoRaConfig: View {
@State var isPresentingSaveConfirm = false
@State var hasChanges = false
@State var region = 0
@State var region: Int = 0
@State var modemPreset = 0
@State var hopLimit = 0
@State var txPower = 0
@ -57,9 +57,13 @@ struct LoRaConfig: View {
Text("LoRa config data was requested over the admin channel but no response has been returned from the remote node. You can check the status of admin message requests in the admin message log.")
.font(.callout)
.foregroundColor(.orange)
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setLoRaValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -228,19 +232,7 @@ struct LoRaConfig: View {
.onAppear {
self.bleManager.context = context
self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 3)
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.channelNum = Int(node?.loRaConfig?.channelNum ?? 0)
self.bandwidth = Int(node?.loRaConfig?.bandwidth ?? 0)
self.codingRate = Int(node?.loRaConfig?.codingRate ?? 0)
self.spreadFactor = Int(node?.loRaConfig?.spreadFactor ?? 0)
self.rxBoostedGain = node?.loRaConfig?.sx126xRxBoostedGain ?? false
print(rxBoostedGain)
self.hasChanges = false
setLoRaValues()
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.loRaConfig == nil {
@ -297,4 +289,18 @@ struct LoRaConfig: View {
}
}
}
func setLoRaValues() {
self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 3)
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.channelNum = Int(node?.loRaConfig?.channelNum ?? 0)
self.bandwidth = Int(node?.loRaConfig?.bandwidth ?? 0)
self.codingRate = Int(node?.loRaConfig?.codingRate ?? 0)
self.spreadFactor = Int(node?.loRaConfig?.spreadFactor ?? 0)
self.rxBoostedGain = node?.loRaConfig?.sx126xRxBoostedGain ?? false
self.hasChanges = false
}
}

View file

@ -53,6 +53,9 @@ struct CannedMessagesConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setCannedMessagesValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -263,19 +266,7 @@ struct CannedMessagesConfig: View {
})
.onAppear {
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.messages = node?.cannedMessageConfig?.messages ?? ""
self.hasChanges = false
self.hasMessagesChanges = false
setCannedMessagesValues()
// Need to request a CannedMessagesModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.cannedMessageConfig == nil {
@ -367,4 +358,19 @@ struct CannedMessagesConfig: View {
}
}
}
func setCannedMessagesValues() {
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.messages = node?.cannedMessageConfig?.messages ?? ""
self.hasChanges = false
self.hasMessagesChanges = false
}
}

View file

@ -48,6 +48,9 @@ struct ExternalNotificationConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setExternalNotificationValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -190,6 +193,7 @@ struct ExternalNotificationConfig: View {
enc.alertMessageVibra = alertMessageVibra
enc.active = active
enc.output = UInt32(output)
enc.nagTimeout = UInt32(nagTimeout)
enc.outputBuzzer = UInt32(outputBuzzer)
enc.outputVibra = UInt32(outputVibra)
enc.outputMs = UInt32(outputMilliseconds)
@ -214,21 +218,7 @@ struct ExternalNotificationConfig: View {
})
.onAppear {
self.bleManager.context = context
self.enabled = node?.externalNotificationConfig?.enabled ?? false
self.alertBell = node?.externalNotificationConfig?.alertBell ?? false
self.alertBellBuzzer = node?.externalNotificationConfig?.alertBellBuzzer ?? false
self.alertBellVibra = node?.externalNotificationConfig?.alertBellVibra ?? false
self.alertMessage = node?.externalNotificationConfig?.alertMessage ?? false
self.alertMessageBuzzer = node?.externalNotificationConfig?.alertMessageBuzzer ?? false
self.alertMessageVibra = node?.externalNotificationConfig?.alertMessageVibra ?? false
self.active = node?.externalNotificationConfig?.active ?? false
self.output = Int(node?.externalNotificationConfig?.output ?? 0)
self.outputBuzzer = Int(node?.externalNotificationConfig?.outputBuzzer ?? 0)
self.outputVibra = Int(node?.externalNotificationConfig?.outputVibra ?? 0)
self.outputMilliseconds = Int(node?.externalNotificationConfig?.outputMilliseconds ?? 0)
self.nagTimeout = Int(node?.externalNotificationConfig?.nagTimeout ?? 0)
self.usePWM = node?.externalNotificationConfig?.usePWM ?? false
self.hasChanges = false
setExternalNotificationValues()
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.externalNotificationConfig == nil {
@ -310,4 +300,21 @@ struct ExternalNotificationConfig: View {
}
}
}
func setExternalNotificationValues() {
self.enabled = node?.externalNotificationConfig?.enabled ?? false
self.alertBell = node?.externalNotificationConfig?.alertBell ?? false
self.alertBellBuzzer = node?.externalNotificationConfig?.alertBellBuzzer ?? false
self.alertBellVibra = node?.externalNotificationConfig?.alertBellVibra ?? false
self.alertMessage = node?.externalNotificationConfig?.alertMessage ?? false
self.alertMessageBuzzer = node?.externalNotificationConfig?.alertMessageBuzzer ?? false
self.alertMessageVibra = node?.externalNotificationConfig?.alertMessageVibra ?? false
self.active = node?.externalNotificationConfig?.active ?? false
self.output = Int(node?.externalNotificationConfig?.output ?? 0)
self.outputBuzzer = Int(node?.externalNotificationConfig?.outputBuzzer ?? 0)
self.outputVibra = Int(node?.externalNotificationConfig?.outputVibra ?? 0)
self.outputMilliseconds = Int(node?.externalNotificationConfig?.outputMilliseconds ?? 0)
self.nagTimeout = Int(node?.externalNotificationConfig?.nagTimeout ?? 0)
self.usePWM = node?.externalNotificationConfig?.usePWM ?? false
self.hasChanges = false
}
}

View file

@ -38,6 +38,9 @@ struct MQTTConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setMqttValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -198,16 +201,10 @@ struct MQTTConfig: View {
})
.onAppear {
self.bleManager.context = context
self.enabled = (node?.mqttConfig?.enabled ?? false)
self.address = node?.mqttConfig?.address ?? ""
self.username = node?.mqttConfig?.username ?? ""
self.password = node?.mqttConfig?.password ?? ""
self.encryptionEnabled = (node?.mqttConfig?.encryptionEnabled ?? false)
self.jsonEnabled = (node?.mqttConfig?.jsonEnabled ?? false)
self.hasChanges = false
setMqttValues()
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.telemetryConfig == nil {
if bleManager.connectedPeripheral != nil && node?.mqttConfig == nil {
print("empty mqtt module config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if node != nil && connectedNode != nil {
@ -231,4 +228,14 @@ struct MQTTConfig: View {
}
}
}
func setMqttValues() {
self.enabled = (node?.mqttConfig?.enabled ?? false)
self.address = node?.mqttConfig?.address ?? ""
self.username = node?.mqttConfig?.username ?? ""
self.password = node?.mqttConfig?.password ?? ""
self.encryptionEnabled = (node?.mqttConfig?.encryptionEnabled ?? false)
self.jsonEnabled = (node?.mqttConfig?.jsonEnabled ?? false)
self.hasChanges = false
}
}

View file

@ -37,6 +37,9 @@ struct RangeTestConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setRangeTestValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -115,10 +118,7 @@ struct RangeTestConfig: View {
})
.onAppear {
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
setRangeTestValues()
// Need to request a RangeTestModule Config from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.rangeTestConfig == nil {
@ -146,4 +146,10 @@ struct RangeTestConfig: View {
}
}
}
func setRangeTestValues() {
self.enabled = node?.rangeTestConfig?.enabled ?? false
self.save = node?.rangeTestConfig?.save ?? false
self.sender = Int(node?.rangeTestConfig?.sender ?? 0)
self.hasChanges = false
}
}

View file

@ -44,6 +44,9 @@ struct SerialConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setSerialValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -177,15 +180,7 @@ struct SerialConfig: View {
.onAppear {
self.bleManager.context = context
self.enabled = node?.serialConfig?.enabled ?? false
self.echo = node?.serialConfig?.echo ?? false
self.rxd = Int(node?.serialConfig?.rxd ?? 0)
self.txd = Int(node?.serialConfig?.txd ?? 0)
self.baudRate = Int(node?.serialConfig?.baudRate ?? 0)
self.timeout = Int(node?.serialConfig?.timeout ?? 0)
self.mode = Int(node?.serialConfig?.mode ?? 0)
self.hasChanges = false
setSerialValues()
// Need to request a SerialModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.serialConfig == nil {
print("empty serial module config")
@ -247,4 +242,14 @@ struct SerialConfig: View {
}
}
}
func setSerialValues() {
self.enabled = node?.serialConfig?.enabled ?? false
self.echo = node?.serialConfig?.echo ?? false
self.rxd = Int(node?.serialConfig?.rxd ?? 0)
self.txd = Int(node?.serialConfig?.txd ?? 0)
self.baudRate = Int(node?.serialConfig?.baudRate ?? 0)
self.timeout = Int(node?.serialConfig?.timeout ?? 0)
self.mode = Int(node?.serialConfig?.mode ?? 0)
self.hasChanges = false
}
}

View file

@ -40,6 +40,9 @@ struct TelemetryConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setTelemetryValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -131,12 +134,7 @@ struct TelemetryConfig: View {
})
.onAppear {
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
setTelemetryValues()
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.telemetryConfig == nil {
@ -174,4 +172,12 @@ struct TelemetryConfig: View {
}
}
}
func setTelemetryValues() {
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
}
}

View file

@ -43,6 +43,9 @@ struct NetworkConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setNetworkValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -161,15 +164,10 @@ struct NetworkConfig: View {
})
.onAppear {
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.ethEnabled = node?.networkConfig?.ethEnabled ?? false
self.hasChanges = false
setNetworkValues()
// Need to request a NetworkConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.positionConfig == nil {
if bleManager.connectedPeripheral != nil && node?.networkConfig == nil {
print("empty network config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if node != nil && connectedNode != nil {
@ -203,4 +201,13 @@ struct NetworkConfig: View {
}
}
}
func setNetworkValues() {
self.wifiEnabled = node?.networkConfig?.wifiEnabled ?? false
self.wifiSsid = node?.networkConfig?.wifiSsid ?? ""
self.wifiPsk = node?.networkConfig?.wifiPsk ?? ""
self.wifiMode = Int(node?.networkConfig?.wifiMode ?? 0)
self.ethEnabled = node?.networkConfig?.ethEnabled ?? false
self.hasChanges = false
}
}

View file

@ -86,6 +86,9 @@ struct PositionConfig: View {
} else {
Text("Remote administration for: \(node?.user?.longName ?? "Unknown")")
.font(.title3)
.onAppear {
setPositionValues()
}
}
} else if node != nil && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Text("Configuration for: \(node?.user?.longName ?? "Unknown")")
@ -277,28 +280,7 @@ struct PositionConfig: View {
.onAppear {
self.bleManager.context = context
self.smartPositionEnabled = node?.positionConfig?.smartPositionEnabled ?? true
self.deviceGpsEnabled = node?.positionConfig?.deviceGpsEnabled ?? true
self.fixedPosition = node?.positionConfig?.fixedPosition ?? false
self.gpsUpdateInterval = Int(node?.positionConfig?.gpsUpdateInterval ?? 30)
self.gpsAttemptTime = Int(node?.positionConfig?.gpsAttemptTime ?? 30)
self.positionBroadcastSeconds = Int(node?.positionConfig?.positionBroadcastSeconds ?? 900)
self.positionFlags = Int(node?.positionConfig?.positionFlags ?? 3)
let pf = PositionFlags(rawValue: self.positionFlags)
if pf.contains(.Altitude) { self.includeAltitude = true } else { self.includeAltitude = false }
if pf.contains(.AltitudeMsl) { self.includeAltitudeMsl = true } else { self.includeAltitudeMsl = false }
if pf.contains(.GeoidalSeparation) { self.includeGeoidalSeparation = true } else { self.includeGeoidalSeparation = false }
if pf.contains(.Dop) { self.includeDop = true } else { self.includeDop = false }
if pf.contains(.Hvdop) { self.includeHvdop = true } else { self.includeHvdop = false }
if pf.contains(.Satsinview) { self.includeSatsinview = true } else { self.includeSatsinview = false }
if pf.contains(.SeqNo) { self.includeSeqNo = true } else { self.includeSeqNo = false }
if pf.contains(.Timestamp) { self.includeTimestamp = true } else { self.includeTimestamp = false }
if pf.contains(.Speed) { self.includeSpeed = true } else { self.includeSpeed = false }
if pf.contains(.Heading) { self.includeHeading = true } else { self.includeHeading = false }
self.hasChanges = false
setPositionValues()
// Need to request a PositionConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.positionConfig == nil {
@ -395,4 +377,29 @@ struct PositionConfig: View {
if existingValue != hvdopFlag { hasChanges = true }
}
}
func setPositionValues() {
self.smartPositionEnabled = node?.positionConfig?.smartPositionEnabled ?? true
self.deviceGpsEnabled = node?.positionConfig?.deviceGpsEnabled ?? true
self.fixedPosition = node?.positionConfig?.fixedPosition ?? false
self.gpsUpdateInterval = Int(node?.positionConfig?.gpsUpdateInterval ?? 30)
self.gpsAttemptTime = Int(node?.positionConfig?.gpsAttemptTime ?? 30)
self.positionBroadcastSeconds = Int(node?.positionConfig?.positionBroadcastSeconds ?? 900)
self.positionFlags = Int(node?.positionConfig?.positionFlags ?? 3)
let pf = PositionFlags(rawValue: self.positionFlags)
if pf.contains(.Altitude) { self.includeAltitude = true } else { self.includeAltitude = false }
if pf.contains(.AltitudeMsl) { self.includeAltitudeMsl = true } else { self.includeAltitudeMsl = false }
if pf.contains(.GeoidalSeparation) { self.includeGeoidalSeparation = true } else { self.includeGeoidalSeparation = false }
if pf.contains(.Dop) { self.includeDop = true } else { self.includeDop = false }
if pf.contains(.Hvdop) { self.includeHvdop = true } else { self.includeHvdop = false }
if pf.contains(.Satsinview) { self.includeSatsinview = true } else { self.includeSatsinview = false }
if pf.contains(.SeqNo) { self.includeSeqNo = true } else { self.includeSeqNo = false }
if pf.contains(.Timestamp) { self.includeTimestamp = true } else { self.includeTimestamp = false }
if pf.contains(.Speed) { self.includeSpeed = true } else { self.includeSpeed = false }
if pf.contains(.Heading) { self.includeHeading = true } else { self.includeHeading = false }
self.hasChanges = false
}
}

View file

@ -44,7 +44,7 @@ struct Firmware: View {
}
.padding(.bottom)
if hwModel.platform() == HardwarePlatforms.NRF52 {
if hwModel.platform() == HardwarePlatforms.nrf52 {
VStack(alignment: .leading) {
if hwModel == HardwareModels.RAK4631 {
Text("nRF OTA Device Firmware Update App")
@ -60,7 +60,7 @@ struct Firmware: View {
.font(.callout)
}
}
} else if hwModel.platform() == HardwarePlatforms.ESP32 {
} else if hwModel.platform() == HardwarePlatforms.esp32 {
VStack(alignment: .leading) {
Text("ESP32 Device Firmware Update")
.font(.title3)
@ -74,13 +74,11 @@ struct Firmware: View {
HStack(alignment: .center) {
Spacer()
Button {
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context)
if connectedNode != nil {
if !bleManager.sendRebootOta(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode!.myInfo!.adminIndex) {
print("Reboot Failed")
} else {
bleManager.disconnectPeripheral(reconnect: false)
}
}
}
} label: {
Label("Send Reboot OTA", systemImage: "square.and.arrow.down")
@ -95,6 +93,10 @@ struct Firmware: View {
} else {
Text("OTA Updates are not supported on your platform.")
.font(.title3)
Text(node?.user?.hwModel ?? "UNSET")
.font(.title3)
Text(hwModel.platform().description)
.font(.title3)
}
}.padding()