diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 5e7d84e1..f2dc5667 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -295,10 +295,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { guard (connectedPeripheral!.peripheral.state == CBPeripheralState.connected) else { return 0 } - let nodeName = connectedPeripheral!.peripheral.name ?? NSLocalizedString("unknown", comment: NSLocalizedString("unknown", comment: "Unknown")) - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.devicemetadata %@", - comment: "Requesting Device Metadata for %@"), nodeName) - MeshLogger.log("πŸ›ŽοΈ \(logString)") var adminPacket = AdminMessage() adminPacket.getDeviceMetadataRequest = true var meshPacket: MeshPacket = MeshPacket() @@ -307,6 +303,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { meshPacket.from = UInt32(fromUser.num) meshPacket.priority = MeshPacket.Priority.reliable meshPacket.channel = UInt32(adminIndex) + meshPacket.wantAck = true var dataMessage = DataMessage() dataMessage.payload = try! adminPacket.serializedData() dataMessage.portnum = PortNum.adminApp @@ -322,13 +319,14 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { func sendTraceRouteRequest(destNum: Int64, wantResponse: Bool) -> Bool { var success = false + guard (connectedPeripheral!.peripheral.state == CBPeripheralState.connected) else { return success } + let fromNodeNum = connectedPeripheral.num - let routePacket = RouteDiscovery() - var meshPacket = MeshPacket() meshPacket.to = UInt32(destNum) - meshPacket.from = UInt32(fromNodeNum)//0 // Send 0 as from from phone to device to avoid warning about client trying to set node num + meshPacket.from = UInt32(fromNodeNum) + meshPacket.wantAck = true var dataMessage = DataMessage() dataMessage.payload = try! routePacket.serializedData() dataMessage.portnum = PortNum.tracerouteApp @@ -831,7 +829,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { } } - public func sendShutdown(fromUser: UserEntity, toUser: UserEntity) -> Bool { + public func sendShutdown(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool { var adminPacket = AdminMessage() adminPacket.shutdownSeconds = 5 @@ -841,12 +839,13 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { + public func sendReboot(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool { var adminPacket = AdminMessage() adminPacket.rebootSeconds = 5 @@ -865,13 +864,13 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { var adminPacket = AdminMessage() - adminPacket.factoryReset = 1 + adminPacket.factoryReset = 5 var meshPacket: MeshPacket = MeshPacket() meshPacket.to = UInt32(toUser.num) @@ -895,7 +894,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { dataMessage.portnum = PortNum.adminApp meshPacket.decoded = dataMessage - let messageDescription = "Sent Factory Reset Admin Message to: \(toUser.longName ?? NSLocalizedString("unknown", comment: ""))" + let messageDescription = "πŸš€ Sent Factory Reset Admin Message to: \(toUser.longName ?? NSLocalizedString("unknown", comment: "")) from: \(fromUser.longName ?? NSLocalizedString("unknown", comment: ""))" if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) { return true } @@ -905,7 +904,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { public func sendNodeDBReset(fromUser: UserEntity, toUser: UserEntity) -> Bool { var adminPacket = AdminMessage() - adminPacket.nodedbReset = 1 + adminPacket.nodedbReset = 10 var meshPacket: MeshPacket = MeshPacket() meshPacket.to = UInt32(toUser.num) @@ -913,13 +912,12 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + public func saveBluetoothConfig(config: Config.BluetoothConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 { var adminPacket = AdminMessage() adminPacket.setConfig.bluetooth = config var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(connectedPeripheral.num) - meshPacket.from = 0 //UInt32(connectedPeripheral.num) + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.channel = UInt32(adminIndex) meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + public func saveDeviceConfig(config: Config.DeviceConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 { var adminPacket = AdminMessage() adminPacket.setConfig.device = config var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(connectedPeripheral.num) - meshPacket.from = 0 //UInt32(connectedPeripheral.num) + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.channel = UInt32(adminIndex) meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + public func saveDisplayConfig(config: Config.DisplayConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 { var adminPacket = AdminMessage() adminPacket.setConfig.display = config var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(connectedPeripheral.num) - meshPacket.from = 0 //UInt32(connectedPeripheral.num) + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + if adminIndex > 0 { + meshPacket.channel = UInt32(adminIndex) + } meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + public func savePositionConfig(config: Config.PositionConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 { var adminPacket = AdminMessage() adminPacket.setConfig.position = config var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(connectedPeripheral.num) - meshPacket.from = 0 //UInt32(connectedPeripheral.num) + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.channel = UInt32(adminIndex) meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + public func saveNetworkConfig(config: Config.NetworkConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 { var adminPacket = AdminMessage() adminPacket.setConfig.network = config var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(connectedPeripheral.num) - meshPacket.from = 0 //UInt32(connectedPeripheral.num) + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.channel = UInt32(adminIndex) meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + + var adminPacket = AdminMessage() + adminPacket.setModuleConfig.cannedMessage = config + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.channel = UInt32(adminIndex) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + + var adminPacket = AdminMessage() + adminPacket.setCannedMessageModuleMessages = messages + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.channel = UInt32(adminIndex) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + + var adminPacket = AdminMessage() + adminPacket.setModuleConfig.externalNotification = config + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.channel = UInt32(adminIndex) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + + var adminPacket = AdminMessage() + adminPacket.setModuleConfig.mqtt = config + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + public func saveRangeTestModuleConfig(config: ModuleConfig.RangeTestConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 { + + var adminPacket = AdminMessage() + adminPacket.setModuleConfig.rangeTest = config + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + public func saveSerialModuleConfig(config: ModuleConfig.SerialConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 { var adminPacket = AdminMessage() - adminPacket.setCannedMessageModuleMessages = messages + adminPacket.setModuleConfig.serial = config var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(toUser.num) - meshPacket.from = 0 //UInt32(fromUser.num) meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { + + var adminPacket = AdminMessage() + adminPacket.setModuleConfig.telemetry = config + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { - - var adminPacket = AdminMessage() - adminPacket.setModuleConfig.externalNotification = config - - var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(toUser.num) - meshPacket.from = 0 //UInt32(fromUser.num) - meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { - - var adminPacket = AdminMessage() - adminPacket.setModuleConfig.mqtt = config - - var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(connectedPeripheral.num) - meshPacket.from = 0 //UInt32(connectedPeripheral.num) - meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { - - var adminPacket = AdminMessage() - adminPacket.setModuleConfig.rangeTest = config - - var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(toUser.num) - meshPacket.from = 0 //UInt32(fromUser.num) - meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { - - var adminPacket = AdminMessage() - adminPacket.setModuleConfig.serial = config - - var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(connectedPeripheral.num) - meshPacket.from = 0 //UInt32(connectedPeripheral.num) - meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Int64 { - - var adminPacket = AdminMessage() - adminPacket.setModuleConfig.telemetry = config - - var meshPacket: MeshPacket = MeshPacket() - meshPacket.to = UInt32(toUser.num) - meshPacket.from = 0 //UInt32(fromUser.num) - meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 9498af21..be1653a1 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -209,7 +209,7 @@ func deviceMetadataPacket (metadata: DeviceMetadata, fromNum: Int64, context: NS newMetadata.role = Int32(metadata.role.rawValue) newMetadata.positionFlags = Int32(metadata.positionFlags) fetchedNode[0].metadata = newMetadata - + do { try context.save() } catch { @@ -525,6 +525,35 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) { } else { MeshLogger.log("πŸ•ΈοΈ MESH PACKET received for Admin App \(try! packet.decoded.jsonString())") } + + // Save an ack for the admin message log for each admin message response received as we stopped sending acks if there is also a response to reduce airtime. + adminResponseAck(packet: packet, context: context) + } +} + +func adminResponseAck (packet: MeshPacket, context: NSManagedObjectContext) { + + let fetchedAdminMessageRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MessageEntity") + fetchedAdminMessageRequest.predicate = NSPredicate(format: "messageId == %lld", packet.decoded.requestID) + do { + let fetchedMessage = try context.fetch(fetchedAdminMessageRequest) as! [MessageEntity] + if fetchedMessage.count > 0 { + fetchedMessage[0].ackTimestamp = Int32(Date().timeIntervalSince1970) + fetchedMessage[0].ackError = Int32(RoutingError.none.rawValue) + fetchedMessage[0].receivedACK = true + fetchedMessage[0].realACK = true + fetchedMessage[0].ackSNR = packet.rxSnr + if fetchedMessage[0].fromUser != nil { + fetchedMessage[0].fromUser?.objectWillChange.send() + } + do { + try context.save() + } catch { + print("Failed to save admin message response as an ack") + } + } + } catch { + print("Failed to fetch admin message by requestID") } } diff --git a/Meshtastic/Views/Nodes/NodeDetail.swift b/Meshtastic/Views/Nodes/NodeDetail.swift index c00d475b..32507e5e 100644 --- a/Meshtastic/Views/Nodes/NodeDetail.swift +++ b/Meshtastic/Views/Nodes/NodeDetail.swift @@ -357,11 +357,12 @@ struct NodeDetail: View { } } - if self.bleManager.connectedPeripheral != nil && self.bleManager.connectedPeripheral.num == node.num && self.bleManager.connectedPeripheral.num == node.num { + if (self.bleManager.connectedPeripheral != nil && self.bleManager.connectedPeripheral.num == node.num) + || (self.bleManager.connectedPeripheral != nil && node.metadata != nil) { HStack { - - if node.metadata != nil && node.metadata?.canShutdown ?? false { + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + if node.metadata?.canShutdown ?? false { Button(action: { showingShutdownConfirm = true @@ -378,7 +379,7 @@ struct NodeDetail: View { isPresented: $showingShutdownConfirm ) { Button("Shutdown Node?", role: .destructive) { - if !bleManager.sendShutdown(fromUser: node.user!, toUser: node.user!) { + if !bleManager.sendShutdown(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo!.adminIndex) { print("Shutdown Failed") } } @@ -398,7 +399,7 @@ struct NodeDetail: View { isPresented: $showingRebootConfirm ) { Button("reboot.node", role: .destructive) { - if !bleManager.sendReboot(fromUser: node.user!, toUser: node.user!) { + if !bleManager.sendReboot(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo!.adminIndex) { print("Reboot Failed") } } @@ -407,21 +408,22 @@ struct NodeDetail: View { .padding(5) Divider() } - - VStack { - AsyncImage(url: attributionLogo) { image in - image - .resizable() - .scaledToFit() - } placeholder: { - ProgressView() - .controlSize(.mini) + if node.positions?.count ?? 0 > 0 { + VStack { + AsyncImage(url: attributionLogo) { image in + image + .resizable() + .scaledToFit() + } placeholder: { + ProgressView() + .controlSize(.mini) + } + .frame(height: 15) + + Link("Other data sources", destination: attributionLink ?? URL(string: "https://weather-data.apple.com/legal-attribution.html")!) } - .frame(height: 15) - - Link("Other data sources", destination: attributionLink ?? URL(string: "https://weather-data.apple.com/legal-attribution.html")!) + .font(.footnote) } - .font(.footnote) } } .edgesIgnoringSafeArea([.leading, .trailing]) @@ -440,6 +442,16 @@ struct NodeDetail: View { }) .onAppear { self.bleManager.context = context + + if bleManager.connectedPeripheral != nil { + + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + if connectedNode.myInfo != nil { + + let adminMessageId = bleManager.requestDeviceMetadata(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo!.adminIndex, context: context) + } + } + } .task(id: node.num) { do { @@ -456,9 +468,7 @@ struct NodeDetail: View { 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 diff --git a/Meshtastic/Views/Settings/AdminMessageList.swift b/Meshtastic/Views/Settings/AdminMessageList.swift index b2c40f8a..9e597164 100644 --- a/Meshtastic/Views/Settings/AdminMessageList.swift +++ b/Meshtastic/Views/Settings/AdminMessageList.swift @@ -5,9 +5,9 @@ // Created by Garth Vander Houwen on 7/2/22. // /* -Abstract: -A view showing the details for a node. -*/ + Abstract: + A view showing the details for a node. + */ import SwiftUI import MapKit @@ -17,39 +17,41 @@ struct AdminMessageList: View { @Environment(\.managedObjectContext) var context @EnvironmentObject var bleManager: BLEManager - + var user: UserEntity? - + var body: some View { let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmmssa", options: 0, locale: Locale.current) let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mm:ss a") List { if user != nil { - - ForEach ( user!.adminMessageList ) { am in - HStack { + ForEach ( user!.adminMessageList.reversed() ) { am in + + VStack (alignment: .leading) { Text("\(am.adminDescription ?? NSLocalizedString("unknown", comment: "Unknown")) - \(Date(timeIntervalSince1970: TimeInterval(am.messageTimestamp)).formattedDate(format: dateFormatString))") - .font(.caption) + .font(.caption2) - if am.receivedACK { - - Image(systemName: "checkmark.square") - .foregroundColor(.gray) - .font(.caption) - Text("routing.acknowledged").foregroundColor(.gray).font(.caption) + Text(": \(Date(timeIntervalSince1970: TimeInterval(am.ackTimestamp)).formattedDate(format: "h:mm:ss a"))") - .foregroundColor(.gray) - .font(.caption) - - } else { - let ackErrorVal = RoutingError(rawValue: Int(am.ackError)) - Image(systemName: "square") - .foregroundColor(.gray) - .font(.caption) - Text(ackErrorVal?.display ?? "Empty Ack Error") - .foregroundColor(.gray) - .font(.caption) + HStack{ + if am.receivedACK { + + Image(systemName: "checkmark.square") + .foregroundColor(.gray) + .font(.caption) + Text("routing.acknowledged").foregroundColor(.gray).font(.caption) + Text(": \(Date(timeIntervalSince1970: TimeInterval(am.ackTimestamp)).formattedDate(format: "h:mm:ss a"))") + .foregroundColor(.gray) + .font(.caption) + + } else { + let ackErrorVal = RoutingError(rawValue: Int(am.ackError)) + Image(systemName: "square") + .foregroundColor(.gray) + .font(.caption) + Text(ackErrorVal?.display ?? "Empty Ack Error") + .foregroundColor(.gray) + .font(.caption) + } } } } @@ -57,7 +59,7 @@ struct AdminMessageList: View { } .navigationTitle("admin.log") .navigationBarItems(trailing: - ZStack { + ZStack { ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") }) .onAppear { diff --git a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index b05d2190..b11e4614 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -104,7 +104,7 @@ struct BluetoothConfig: View { bc.enabled = enabled bc.mode = BluetoothModes(rawValue: mode)?.protoEnumValue() ?? Config.BluetoothConfig.PairingMode.randomPin bc.fixedPin = UInt32(fixedPin) ?? 123456 - let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index 8023fb4f..5786dce7 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -87,56 +87,59 @@ struct DeviceConfig: View { } .disabled(self.bleManager.connectedPeripheral == nil || node?.deviceConfig == nil) - HStack { - - Button("Reset NodeDB", role: .destructive) { - isPresentingNodeDBResetConfirm = true - } - .disabled(node?.user == nil) - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding() - .confirmationDialog( - "are.you.sure", - isPresented: $isPresentingNodeDBResetConfirm, - 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) - } else { - print("NodeDB Reset Failed") + // 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 + } + .disabled(node?.user == nil) + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding() + .confirmationDialog( + "are.you.sure", + isPresented: $isPresentingNodeDBResetConfirm, + 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) + } else { + print("NodeDB Reset Failed") + } } } - } - Button("Factory Reset", role: .destructive) { - isPresentingFactoryResetConfirm = true - } - .disabled(node?.user == nil) - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding() - .confirmationDialog( - "All device and app data will be deleted. You will also need to forget your devices under Settings > Bluetooth.", - isPresented: $isPresentingFactoryResetConfirm, - 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") + Button("Factory Reset", role: .destructive) { + isPresentingFactoryResetConfirm = true + } + .disabled(node?.user == nil) + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding() + .confirmationDialog( + "All device and app data will be deleted. You will also need to forget your devices under Settings > Bluetooth.", + isPresented: $isPresentingFactoryResetConfirm, + 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 { @@ -167,7 +170,7 @@ struct DeviceConfig: View { dc.buttonGpio = UInt32(buttonGPIO) dc.buzzerGpio = UInt32(buzzerGPIO) - let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/DisplayConfig.swift b/Meshtastic/Views/Settings/Config/DisplayConfig.swift index cd589a4c..fc2e2836 100644 --- a/Meshtastic/Views/Settings/Config/DisplayConfig.swift +++ b/Meshtastic/Views/Settings/Config/DisplayConfig.swift @@ -129,7 +129,7 @@ struct DisplayConfig: View { dc.oled = OledTypes(rawValue: oledType)!.protoEnumValue() dc.displaymode = DisplayModes(rawValue: displayMode)!.protoEnumValue() - let adminMessageId = bleManager.saveDisplayConfig(config: dc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveDisplayConfig(config: dc, fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true diff --git a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift index d4057971..f2add109 100644 --- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift @@ -242,7 +242,7 @@ struct CannedMessagesConfig: View { cmc.inputbrokerEventCw = InputEventChars(rawValue: inputbrokerEventCw)!.protoEnumValue() cmc.inputbrokerEventCcw = InputEventChars(rawValue: inputbrokerEventCcw)!.protoEnumValue() cmc.inputbrokerEventPress = InputEventChars(rawValue: inputbrokerEventPress)!.protoEnumValue() - let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save @@ -251,7 +251,7 @@ struct CannedMessagesConfig: View { } } if hasMessagesChanges { - let adminMessageId = bleManager.saveCannedMessageModuleMessages(messages: messages, fromUser: node!.user!, toUser: node!.user!, wantResponse: true) + let adminMessageId = bleManager.saveCannedMessageModuleMessages(messages: messages, fromUser: node!.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift index 2a6e5222..76d2b738 100644 --- a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift @@ -172,7 +172,7 @@ struct ExternalNotificationConfig: View { enc.outputVibra = UInt32(outputVibra) enc.outputMs = UInt32(outputMilliseconds) enc.usePwm = usePWM - let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, 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 // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index 7939a439..e3855377 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -154,7 +154,7 @@ struct MQTTConfig: View { mqtt.password = self.password mqtt.encryptionEnabled = self.encryptionEnabled mqtt.jsonEnabled = self.jsonEnabled - let adminMessageId = bleManager.saveMQTTConfig(config: mqtt, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveMQTTConfig(config: mqtt, 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 // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift index 26b47313..a66d926e 100644 --- a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift @@ -71,7 +71,7 @@ struct RangeTestConfig: View { rtc.enabled = enabled rtc.save = save rtc.sender = UInt32(sender) - let adminMessageId = bleManager.saveRangeTestModuleConfig(config: rtc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveRangeTestModuleConfig(config: rtc, 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 // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift index 5bd0409d..4678ca60 100644 --- a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift @@ -131,7 +131,7 @@ struct SerialConfig: View { sc.timeout = UInt32(timeout) sc.mode = SerialModeTypes(rawValue: mode)!.protoEnumValue() - let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, 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 diff --git a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift index 38b8bd05..88bc907d 100644 --- a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift @@ -87,7 +87,7 @@ struct TelemetryConfig: View { tc.environmentMeasurementEnabled = environmentMeasurementEnabled tc.environmentScreenEnabled = environmentScreenEnabled tc.environmentDisplayFahrenheit = environmentDisplayFahrenheit - let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, 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 // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/NetworkConfig.swift b/Meshtastic/Views/Settings/Config/NetworkConfig.swift index 2fafc701..db670c27 100644 --- a/Meshtastic/Views/Settings/Config/NetworkConfig.swift +++ b/Meshtastic/Views/Settings/Config/NetworkConfig.swift @@ -118,7 +118,7 @@ struct NetworkConfig: View { network.ethEnabled = self.ethEnabled //network.addressMode = Config.NetworkConfig.AddressMode.dhcp - let adminMessageId = bleManager.saveNetworkConfig(config: network, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveNetworkConfig(config: network, fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Config/PositionConfig.swift b/Meshtastic/Views/Settings/Config/PositionConfig.swift index 48301bdb..7c7af9ea 100644 --- a/Meshtastic/Views/Settings/Config/PositionConfig.swift +++ b/Meshtastic/Views/Settings/Config/PositionConfig.swift @@ -229,7 +229,7 @@ struct PositionConfig: View { if includeSpeed { pf.insert(.Speed) } if includeHeading { pf.insert(.Heading) } pc.positionFlags = UInt32(pf.rawValue) - let adminMessageId = bleManager.savePositionConfig(config: pc, fromUser: connectedNode.user!, toUser: node!.user!) + let adminMessageId = bleManager.savePositionConfig(config: pc, fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 93bb597e..9d11d10f 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -85,7 +85,7 @@ struct Settings: View { let adminMessageId = bleManager.requestDeviceMetadata(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode!.myInfo!.adminIndex, context: context) if adminMessageId > 0 { - print("Saved node metadata") + print("Sent node metadata request from node details") } } }