diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index b007418b..7c131f75 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -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; diff --git a/Meshtastic/Enums/HardwareModels.swift b/Meshtastic/Enums/HardwareModels.swift index de6e9331..59cbc30c 100644 --- a/Meshtastic/Enums/HardwareModels.swift +++ b/Meshtastic/Enums/HardwareModels.swift @@ -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" } } diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 81f0caa4..d329dceb 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -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) diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index 6fd4844c..32b25c29 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -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") diff --git a/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift b/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift index 46a6d070..32bed165 100644 --- a/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift +++ b/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift @@ -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() } } diff --git a/Meshtastic/Views/Nodes/NodeDetail.swift b/Meshtastic/Views/Nodes/NodeDetail.swift index d914ec74..bb24243d 100644 --- a/Meshtastic/Views/Nodes/NodeDetail.swift +++ b/Meshtastic/Views/Nodes/NodeDetail.swift @@ -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" - } - } } } } diff --git a/Meshtastic/Views/Nodes/NodeMap.swift b/Meshtastic/Views/Nodes/NodeMap.swift index 3a9d3de5..7dbad566 100644 --- a/Meshtastic/Views/Nodes/NodeMap.swift +++ b/Meshtastic/Views/Nodes/NodeMap.swift @@ -84,6 +84,7 @@ struct NodeMap: View { mapViewType: mapType, userTrackingMode: userTrackingMode, centeringMode: mapCenteringMode, + showBreadcrumbLines: false, centerOnPositionsOnly: false, customMapOverlay: self.customMapOverlay, overlays: self.overlays diff --git a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index 3ec63ef3..3dc03f42 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index 1210cc99..468e770d 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/DisplayConfig.swift b/Meshtastic/Views/Settings/Config/DisplayConfig.swift index e45fe011..8a595a11 100644 --- a/Meshtastic/Views/Settings/Config/DisplayConfig.swift +++ b/Meshtastic/Views/Settings/Config/DisplayConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index 751fb1ee..3eb061da 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift index 386683c8..38debac0 100644 --- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift index 2074bf0f..2765b46d 100644 --- a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index f264907e..33a57063 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift index 9d6ed6de..44d03ee9 100644 --- a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift index c5d1e900..6f5cc238 100644 --- a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift index 3d5910b7..93c67b89 100644 --- a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/NetworkConfig.swift b/Meshtastic/Views/Settings/Config/NetworkConfig.swift index 4c74afea..21c48653 100644 --- a/Meshtastic/Views/Settings/Config/NetworkConfig.swift +++ b/Meshtastic/Views/Settings/Config/NetworkConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Config/PositionConfig.swift b/Meshtastic/Views/Settings/Config/PositionConfig.swift index b275f77d..25a91a69 100644 --- a/Meshtastic/Views/Settings/Config/PositionConfig.swift +++ b/Meshtastic/Views/Settings/Config/PositionConfig.swift @@ -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 + } } diff --git a/Meshtastic/Views/Settings/Firmware.swift b/Meshtastic/Views/Settings/Firmware.swift index fa9965c4..e2876280 100644 --- a/Meshtastic/Views/Settings/Firmware.swift +++ b/Meshtastic/Views/Settings/Firmware.swift @@ -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()