From 57dbc7b71f550ed577d425c96335e798b2e865f9 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 1 Feb 2023 09:19:45 -0800 Subject: [PATCH] Remote Admin for Module Config --- Meshtastic/Helpers/BLEManager.swift | 104 +++++ Meshtastic/Helpers/MeshPackets.swift | 373 ++---------------- Meshtastic/Persistence/UpdateCoreData.swift | 372 ++++++++++++++++- .../Config/Module/CannedMessagesConfig.swift | 11 +- .../Module/ExternalNotificationConfig.swift | 16 +- .../Settings/Config/Module/MQTTConfig.swift | 16 +- .../Settings/Config/Module/SerialConfig.swift | 16 +- Meshtastic/Views/Settings/Settings.swift | 4 - 8 files changed, 544 insertions(+), 368 deletions(-) diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 22628421..5e7d84e1 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -1559,6 +1559,58 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { return false } + public func requestCannedMessagesModuleConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool { + + var adminPacket = AdminMessage() + adminPacket.getModuleConfigRequest = AdminMessage.ModuleConfigType.cannedmsgConfig + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { + + var adminPacket = AdminMessage() + adminPacket.getModuleConfigRequest = AdminMessage.ModuleConfigType.extnotifConfig + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { var adminPacket = AdminMessage() @@ -1585,6 +1637,58 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { return false } + public func requestMqttModuleConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool { + + var adminPacket = AdminMessage() + adminPacket.getModuleConfigRequest = AdminMessage.ModuleConfigType.mqttConfig + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { + + var adminPacket = AdminMessage() + adminPacket.getModuleConfigRequest = AdminMessage.ModuleConfigType.serialConfig + + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(toUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { var adminPacket = AdminMessage() diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index b1335c5d..9498af21 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -57,338 +57,17 @@ func localConfig (config: Config, context:NSManagedObjectContext, nodeNum: Int64 func moduleConfig (config: ModuleConfig, context:NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) { if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.cannedMessage(config.cannedMessage) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.cannedmessage.config %@", comment: "Canned Message module config received: %@"), String(nodeNum)) - MeshLogger.log("πŸ₯« \(logString)") - - let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) - - do { - - let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - - // Found a node, save Canned Message Config - if !fetchedNode.isEmpty { - - if fetchedNode[0].cannedMessageConfig == nil { - - let newCannedMessageConfig = CannedMessageConfigEntity(context: context) - - newCannedMessageConfig.enabled = config.cannedMessage.enabled - newCannedMessageConfig.sendBell = config.cannedMessage.sendBell - newCannedMessageConfig.rotary1Enabled = config.cannedMessage.rotary1Enabled - newCannedMessageConfig.updown1Enabled = config.cannedMessage.updown1Enabled - newCannedMessageConfig.inputbrokerPinA = Int32(config.cannedMessage.inputbrokerPinA) - newCannedMessageConfig.inputbrokerPinB = Int32(config.cannedMessage.inputbrokerPinB) - newCannedMessageConfig.inputbrokerPinPress = Int32(config.cannedMessage.inputbrokerPinPress) - newCannedMessageConfig.inputbrokerEventCw = Int32(config.cannedMessage.inputbrokerEventCw.rawValue) - newCannedMessageConfig.inputbrokerEventCcw = Int32(config.cannedMessage.inputbrokerEventCcw.rawValue) - newCannedMessageConfig.inputbrokerEventPress = Int32(config.cannedMessage.inputbrokerEventPress.rawValue) - - fetchedNode[0].cannedMessageConfig = newCannedMessageConfig - - } else { - - fetchedNode[0].cannedMessageConfig?.enabled = config.cannedMessage.enabled - fetchedNode[0].cannedMessageConfig?.sendBell = config.cannedMessage.sendBell - fetchedNode[0].cannedMessageConfig?.rotary1Enabled = config.cannedMessage.rotary1Enabled - fetchedNode[0].cannedMessageConfig?.updown1Enabled = config.cannedMessage.updown1Enabled - fetchedNode[0].cannedMessageConfig?.inputbrokerPinA = Int32(config.cannedMessage.inputbrokerPinA) - fetchedNode[0].cannedMessageConfig?.inputbrokerPinB = Int32(config.cannedMessage.inputbrokerPinB) - fetchedNode[0].cannedMessageConfig?.inputbrokerPinPress = Int32(config.cannedMessage.inputbrokerPinPress) - fetchedNode[0].cannedMessageConfig?.inputbrokerEventCw = Int32(config.cannedMessage.inputbrokerEventCw.rawValue) - fetchedNode[0].cannedMessageConfig?.inputbrokerEventCcw = Int32(config.cannedMessage.inputbrokerEventCcw.rawValue) - fetchedNode[0].cannedMessageConfig?.inputbrokerEventPress = Int32(config.cannedMessage.inputbrokerEventPress.rawValue) - } - - do { - try context.save() - print("πŸ’Ύ Updated Canned Message Module Config for node number: \(String(nodeNum))") - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data CannedMessageConfigEntity: \(nsError)") - } - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Canned Message Module Config") - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data CannedMessageConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.externalNotification(config.externalNotification) { - - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.externalnotification.config %@", comment: "External Notifiation module config received: %@"), String(nodeNum)) - MeshLogger.log("πŸ“£ \(logString)") - - let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) - - do { - - let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - // Found a node, save External Notificaitone Config - if !fetchedNode.isEmpty { - - if fetchedNode[0].externalNotificationConfig == nil { - let newExternalNotificationConfig = ExternalNotificationConfigEntity(context: context) - newExternalNotificationConfig.enabled = config.externalNotification.enabled - newExternalNotificationConfig.usePWM = config.externalNotification.usePwm - newExternalNotificationConfig.alertBell = config.externalNotification.alertBell - newExternalNotificationConfig.alertBellBuzzer = config.externalNotification.alertBellBuzzer - newExternalNotificationConfig.alertBellVibra = config.externalNotification.alertBellVibra - newExternalNotificationConfig.alertMessage = config.externalNotification.alertMessage - newExternalNotificationConfig.alertMessageBuzzer = config.externalNotification.alertMessageBuzzer - newExternalNotificationConfig.alertMessageVibra = config.externalNotification.alertMessageVibra - newExternalNotificationConfig.active = config.externalNotification.active - newExternalNotificationConfig.output = Int32(config.externalNotification.output) - newExternalNotificationConfig.outputBuzzer = Int32(config.externalNotification.outputBuzzer) - newExternalNotificationConfig.outputVibra = Int32(config.externalNotification.outputVibra) - newExternalNotificationConfig.outputMilliseconds = Int32(config.externalNotification.outputMs) - newExternalNotificationConfig.nagTimeout = Int32(config.externalNotification.nagTimeout) - fetchedNode[0].externalNotificationConfig = newExternalNotificationConfig - - } else { - fetchedNode[0].externalNotificationConfig?.enabled = config.externalNotification.enabled - fetchedNode[0].externalNotificationConfig?.usePWM = config.externalNotification.usePwm - fetchedNode[0].externalNotificationConfig?.alertBell = config.externalNotification.alertBell - fetchedNode[0].externalNotificationConfig?.alertBellBuzzer = config.externalNotification.alertBellBuzzer - fetchedNode[0].externalNotificationConfig?.alertBellVibra = config.externalNotification.alertBellVibra - fetchedNode[0].externalNotificationConfig?.alertMessage = config.externalNotification.alertMessage - fetchedNode[0].externalNotificationConfig?.alertMessageBuzzer = config.externalNotification.alertMessageBuzzer - fetchedNode[0].externalNotificationConfig?.alertMessageVibra = config.externalNotification.alertMessageVibra - fetchedNode[0].externalNotificationConfig?.active = config.externalNotification.active - fetchedNode[0].externalNotificationConfig?.output = Int32(config.externalNotification.output) - fetchedNode[0].externalNotificationConfig?.outputBuzzer = Int32(config.externalNotification.outputBuzzer) - fetchedNode[0].externalNotificationConfig?.outputVibra = Int32(config.externalNotification.outputVibra) - fetchedNode[0].externalNotificationConfig?.outputMilliseconds = Int32(config.externalNotification.outputMs) - fetchedNode[0].externalNotificationConfig?.nagTimeout = Int32(config.externalNotification.nagTimeout) - } - - do { - try context.save() - print("πŸ’Ύ Updated External Notification Module Config for node number: \(String(nodeNum))") - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data ExternalNotificationConfigEntity: \(nsError)") - } - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save External Notifiation Module Config") - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data ExternalNotificationConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.mqtt(config.mqtt) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.mqtt.config %@", comment: "MQTT module config received: %@"), String(nodeNum)) - MeshLogger.log("πŸŒ‰ \(logString)") - - let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) - - do { - - let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - // Found a node, save MQTT Config - if !fetchedNode.isEmpty { - - if fetchedNode[0].mqttConfig == nil { - let newMQTTConfig = MQTTConfigEntity(context: context) - newMQTTConfig.enabled = config.mqtt.enabled - newMQTTConfig.address = config.mqtt.address - newMQTTConfig.address = config.mqtt.username - newMQTTConfig.password = config.mqtt.password - newMQTTConfig.encryptionEnabled = config.mqtt.encryptionEnabled - newMQTTConfig.jsonEnabled = config.mqtt.jsonEnabled - fetchedNode[0].mqttConfig = newMQTTConfig - } else { - fetchedNode[0].mqttConfig?.enabled = config.mqtt.enabled - fetchedNode[0].mqttConfig?.address = config.mqtt.address - fetchedNode[0].mqttConfig?.address = config.mqtt.username - fetchedNode[0].mqttConfig?.password = config.mqtt.password - fetchedNode[0].mqttConfig?.encryptionEnabled = config.mqtt.encryptionEnabled - fetchedNode[0].mqttConfig?.jsonEnabled = config.mqtt.jsonEnabled - } - do { - try context.save() - print("πŸ’Ύ Updated MQTT Config for node number: \(String(nodeNum))") - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data MQTTConfigEntity: \(nsError)") - } - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save MQTT Module Config") - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data MQTTConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.rangeTest(config.rangeTest) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.rangetest.config %@", comment: "Range Test module config received: %@"), String(nodeNum)) - MeshLogger.log("⛰️ \(logString)") - - let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) - - do { - - let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - // Found a node, save Device Config - if !fetchedNode.isEmpty { - if fetchedNode[0].rangeTestConfig == nil { - let newRangeTestConfig = RangeTestConfigEntity(context: context) - newRangeTestConfig.sender = Int32(config.rangeTest.sender) - newRangeTestConfig.enabled = config.rangeTest.enabled - newRangeTestConfig.save = config.rangeTest.save - fetchedNode[0].rangeTestConfig = newRangeTestConfig - } else { - fetchedNode[0].rangeTestConfig?.sender = Int32(config.rangeTest.sender) - fetchedNode[0].rangeTestConfig?.enabled = config.rangeTest.enabled - fetchedNode[0].rangeTestConfig?.save = config.rangeTest.save - } - do { - try context.save() - print("πŸ’Ύ Updated Range Test Config for node number: \(String(nodeNum))") - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data RangeTestConfigEntity: \(nsError)") - } - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Range Test Module Config") - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data RangeTestConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.serial(config.serial) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.serial.config %@", comment: "Serial module config received: %@"), String(nodeNum)) - MeshLogger.log("πŸ€– \(logString)") - - let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) - - do { - - let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - - // Found a node, save Device Config - if !fetchedNode.isEmpty { - - if fetchedNode[0].serialConfig == nil { - - let newSerialConfig = SerialConfigEntity(context: context) - newSerialConfig.enabled = config.serial.enabled - newSerialConfig.echo = config.serial.echo - newSerialConfig.rxd = Int32(config.serial.rxd) - newSerialConfig.txd = Int32(config.serial.txd) - newSerialConfig.baudRate = Int32(config.serial.baud.rawValue) - newSerialConfig.timeout = Int32(config.serial.timeout) - newSerialConfig.mode = Int32(config.serial.mode.rawValue) - fetchedNode[0].serialConfig = newSerialConfig - - } else { - fetchedNode[0].serialConfig?.enabled = config.serial.enabled - fetchedNode[0].serialConfig?.echo = config.serial.echo - fetchedNode[0].serialConfig?.rxd = Int32(config.serial.rxd) - fetchedNode[0].serialConfig?.txd = Int32(config.serial.txd) - fetchedNode[0].serialConfig?.baudRate = Int32(config.serial.baud.rawValue) - fetchedNode[0].serialConfig?.timeout = Int32(config.serial.timeout) - fetchedNode[0].serialConfig?.mode = Int32(config.serial.mode.rawValue) - } - - do { - try context.save() - print("πŸ’Ύ Updated Serial Module Config for node number: \(String(nodeNum))") - - } catch { - - context.rollback() - - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data SerialConfigEntity: \(nsError)") - } - - } else { - - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Serial Module Config") - } - - } catch { - - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data SerialConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.telemetry(config.telemetry) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.telemetry.config %@", comment: "Telemetry module config received: %@"), String(nodeNum)) - MeshLogger.log("πŸ“ˆ \(logString)") - - let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") - fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) - - do { - - let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - // Found a node, save Telemetry Config - if !fetchedNode.isEmpty { - - if fetchedNode[0].telemetryConfig == nil { - - let newTelemetryConfig = TelemetryConfigEntity(context: context) - - newTelemetryConfig.deviceUpdateInterval = Int32(config.telemetry.deviceUpdateInterval) - newTelemetryConfig.environmentUpdateInterval = Int32(config.telemetry.environmentUpdateInterval) - newTelemetryConfig.environmentMeasurementEnabled = config.telemetry.environmentMeasurementEnabled - newTelemetryConfig.environmentScreenEnabled = config.telemetry.environmentScreenEnabled - newTelemetryConfig.environmentDisplayFahrenheit = config.telemetry.environmentDisplayFahrenheit - - fetchedNode[0].telemetryConfig = newTelemetryConfig - - } else { - - fetchedNode[0].telemetryConfig?.deviceUpdateInterval = Int32(config.telemetry.deviceUpdateInterval) - fetchedNode[0].telemetryConfig?.environmentUpdateInterval = Int32(config.telemetry.environmentUpdateInterval) - fetchedNode[0].telemetryConfig?.environmentMeasurementEnabled = config.telemetry.environmentMeasurementEnabled - fetchedNode[0].telemetryConfig?.environmentScreenEnabled = config.telemetry.environmentScreenEnabled - fetchedNode[0].telemetryConfig?.environmentDisplayFahrenheit = config.telemetry.environmentDisplayFahrenheit - } - - do { - try context.save() - print("πŸ’Ύ Updated Telemetry Module Config for node number: \(String(nodeNum))") - - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data TelemetryConfigEntity: \(nsError)") - } - - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Telemetry Module Config") - } - - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data TelemetryConfigEntity failed: \(nsError)") - } + upsertCannedMessagesModuleConfigPacket(config: config.cannedMessage, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.externalNotification(config.externalNotification) { + upsertExternalNotificationModuleConfigPacket(config: config.externalNotification, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.mqtt(config.mqtt) { + upsertMqttModuleConfigPacket(config: config.mqtt, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.rangeTest(config.rangeTest) { + upsertRangeTestModuleConfigPacket(config: config.rangeTest, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.serial(config.serial) { + upsertSerialModuleConfigPacket(config: config.serial, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.telemetry(config.telemetry) { + upsertTelemetryModuleConfigPacket(config: config.telemetry, nodeNum: nodeNum, context: context) } } @@ -800,9 +479,9 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) { deviceMetadataPacket(metadata: adminMessage.getDeviceMetadataResponse, fromNum: Int64(packet.from), context: context) } else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getConfigResponse(adminMessage.getConfigResponse) { - + let config = adminMessage.getConfigResponse - + if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) { upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), context: context) @@ -817,8 +496,32 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) { } else if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) { upsertPositionConfigPacket(config: config.position, nodeNum: Int64(packet.from), context: context) - + } + } else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getModuleConfigResponse(adminMessage.getModuleConfigResponse) { + + let moduleConfig = adminMessage.getModuleConfigResponse + + if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.cannedMessage(moduleConfig.cannedMessage) { + upsertCannedMessagesModuleConfigPacket(config: moduleConfig.cannedMessage, nodeNum: Int64(packet.from), context: context) + + } else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.externalNotification(moduleConfig.externalNotification) { + upsertExternalNotificationModuleConfigPacket(config: moduleConfig.externalNotification, nodeNum: Int64(packet.from), context: context) + + } else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.mqtt(moduleConfig.mqtt) { + upsertMqttModuleConfigPacket(config: moduleConfig.mqtt, nodeNum: Int64(packet.from), context: context) + + } else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.rangeTest(moduleConfig.rangeTest) { + upsertRangeTestModuleConfigPacket(config: moduleConfig.rangeTest, nodeNum: Int64(packet.from), context: context) + + } else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.serial(moduleConfig.serial) { + upsertSerialModuleConfigPacket(config: moduleConfig.serial, nodeNum: Int64(packet.from), context: context) + + } else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.telemetry(moduleConfig.telemetry) { + upsertTelemetryModuleConfigPacket(config: moduleConfig.telemetry, nodeNum: Int64(packet.from), context: context) + + } + } else { MeshLogger.log("πŸ•ΈοΈ MESH PACKET received for Admin App \(try! packet.decoded.jsonString())") } diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index 13d56039..b78dacd6 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -7,14 +7,14 @@ import CoreData public func clearPositions(destNum: Int64, context: NSManagedObjectContext) -> Bool { - + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(destNum)) - + do { - + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - + let newPostions = [PositionEntity]() fetchedNode[0].positions? = NSOrderedSet(array: newPostions) @@ -26,7 +26,7 @@ public func clearPositions(destNum: Int64, context: NSManagedObjectContext) -> B context.rollback() return false } - + } catch { print("πŸ’₯ Fetch NodeInfoEntity Error") return false @@ -37,11 +37,11 @@ public func clearTelemetry(destNum: Int64, metricsType: Int32, context: NSManage let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(destNum)) - + do { - + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] - + let emptyTelemetry = [TelemetryEntity]() fetchedNode[0].telemetries? = NSOrderedSet(array: emptyTelemetry) @@ -53,7 +53,7 @@ public func clearTelemetry(destNum: Int64, metricsType: Int32, context: NSManage context.rollback() return false } - + } catch { print("πŸ’₯ Fetch NodeInfoEntity Error") return false @@ -63,9 +63,9 @@ public func clearTelemetry(destNum: Int64, metricsType: Int32, context: NSManage public func deleteChannelMessages(channel: ChannelEntity, context: NSManagedObjectContext) { do { let objects = channel.allPrivateMessages - for object in objects { - context.delete(object) - } + for object in objects { + context.delete(object) + } try context.save() } catch let error as NSError { print("Error: \(error.localizedDescription)") @@ -73,12 +73,12 @@ public func deleteChannelMessages(channel: ChannelEntity, context: NSManagedObje } public func deleteUserMessages(user: UserEntity, context: NSManagedObjectContext) { - + do { let objects = user.messageList - for object in objects { - context.delete(object) - } + for object in objects { + context.delete(object) + } try context.save() } catch let error as NSError { print("Error: \(error.localizedDescription)") @@ -92,11 +92,11 @@ public func clearCoreDataDatabase(context: NSManagedObjectContext) { let entity = persistenceController.managedObjectModel.entities[i] let query = NSFetchRequest(entityName: entity.name!) let deleteRequest = NSBatchDeleteRequest(fetchRequest: query) - + do { try context.executeAndMergeChanges(using: deleteRequest) } catch let error as NSError { - print(error) + print(error) } } } @@ -112,7 +112,7 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext) do { if let positionMessage = try? Position(serializedData: packet.decoded.payload) { - + // Don't save empty position packets if positionMessage.longitudeI > 0 || positionMessage.latitudeI > 0 && (positionMessage.latitudeI != 373346000 && positionMessage.longitudeI != -1220090000) { @@ -456,3 +456,337 @@ func upsertPositionConfigPacket(config: Meshtastic.Config.PositionConfig, nodeNu print("πŸ’₯ Fetching node for core data PositionConfigEntity failed: \(nsError)") } } + +func upsertCannedMessagesModuleConfigPacket(config: Meshtastic.ModuleConfig.CannedMessageConfig, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.cannedmessage.config %@", comment: "Canned Message module config received: %@"), String(nodeNum)) + MeshLogger.log("πŸ₯« \(logString)") + + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) + + do { + + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] + + // Found a node, save Canned Message Config + if !fetchedNode.isEmpty { + + if fetchedNode[0].cannedMessageConfig == nil { + + let newCannedMessageConfig = CannedMessageConfigEntity(context: context) + + newCannedMessageConfig.enabled = config.enabled + newCannedMessageConfig.sendBell = config.sendBell + newCannedMessageConfig.rotary1Enabled = config.rotary1Enabled + newCannedMessageConfig.updown1Enabled = config.updown1Enabled + newCannedMessageConfig.inputbrokerPinA = Int32(config.inputbrokerPinA) + newCannedMessageConfig.inputbrokerPinB = Int32(config.inputbrokerPinB) + newCannedMessageConfig.inputbrokerPinPress = Int32(config.inputbrokerPinPress) + newCannedMessageConfig.inputbrokerEventCw = Int32(config.inputbrokerEventCw.rawValue) + newCannedMessageConfig.inputbrokerEventCcw = Int32(config.inputbrokerEventCcw.rawValue) + newCannedMessageConfig.inputbrokerEventPress = Int32(config.inputbrokerEventPress.rawValue) + + fetchedNode[0].cannedMessageConfig = newCannedMessageConfig + + } else { + + fetchedNode[0].cannedMessageConfig?.enabled = config.enabled + fetchedNode[0].cannedMessageConfig?.sendBell = config.sendBell + fetchedNode[0].cannedMessageConfig?.rotary1Enabled = config.rotary1Enabled + fetchedNode[0].cannedMessageConfig?.updown1Enabled = config.updown1Enabled + fetchedNode[0].cannedMessageConfig?.inputbrokerPinA = Int32(config.inputbrokerPinA) + fetchedNode[0].cannedMessageConfig?.inputbrokerPinB = Int32(config.inputbrokerPinB) + fetchedNode[0].cannedMessageConfig?.inputbrokerPinPress = Int32(config.inputbrokerPinPress) + fetchedNode[0].cannedMessageConfig?.inputbrokerEventCw = Int32(config.inputbrokerEventCw.rawValue) + fetchedNode[0].cannedMessageConfig?.inputbrokerEventCcw = Int32(config.inputbrokerEventCcw.rawValue) + fetchedNode[0].cannedMessageConfig?.inputbrokerEventPress = Int32(config.inputbrokerEventPress.rawValue) + } + + do { + try context.save() + print("πŸ’Ύ Updated Canned Message Module Config for node number: \(String(nodeNum))") + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data CannedMessageConfigEntity: \(nsError)") + } + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Canned Message Module Config") + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data CannedMessageConfigEntity failed: \(nsError)") + } +} + +func upsertExternalNotificationModuleConfigPacket(config: Meshtastic.ModuleConfig.ExternalNotificationConfig, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.externalnotification.config %@", comment: "External Notifiation module config received: %@"), String(nodeNum)) + MeshLogger.log("πŸ“£ \(logString)") + + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) + + do { + + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] + // Found a node, save External Notificaitone Config + if !fetchedNode.isEmpty { + + if fetchedNode[0].externalNotificationConfig == nil { + let newExternalNotificationConfig = ExternalNotificationConfigEntity(context: context) + newExternalNotificationConfig.enabled = config.enabled + newExternalNotificationConfig.usePWM = config.usePwm + newExternalNotificationConfig.alertBell = config.alertBell + newExternalNotificationConfig.alertBellBuzzer = config.alertBellBuzzer + newExternalNotificationConfig.alertBellVibra = config.alertBellVibra + newExternalNotificationConfig.alertMessage = config.alertMessage + newExternalNotificationConfig.alertMessageBuzzer = config.alertMessageBuzzer + newExternalNotificationConfig.alertMessageVibra = config.alertMessageVibra + newExternalNotificationConfig.active = config.active + newExternalNotificationConfig.output = Int32(config.output) + newExternalNotificationConfig.outputBuzzer = Int32(config.outputBuzzer) + newExternalNotificationConfig.outputVibra = Int32(config.outputVibra) + newExternalNotificationConfig.outputMilliseconds = Int32(config.outputMs) + newExternalNotificationConfig.nagTimeout = Int32(config.nagTimeout) + fetchedNode[0].externalNotificationConfig = newExternalNotificationConfig + + } else { + fetchedNode[0].externalNotificationConfig?.enabled = config.enabled + fetchedNode[0].externalNotificationConfig?.usePWM = config.usePwm + fetchedNode[0].externalNotificationConfig?.alertBell = config.alertBell + fetchedNode[0].externalNotificationConfig?.alertBellBuzzer = config.alertBellBuzzer + fetchedNode[0].externalNotificationConfig?.alertBellVibra = config.alertBellVibra + fetchedNode[0].externalNotificationConfig?.alertMessage = config.alertMessage + fetchedNode[0].externalNotificationConfig?.alertMessageBuzzer = config.alertMessageBuzzer + fetchedNode[0].externalNotificationConfig?.alertMessageVibra = config.alertMessageVibra + fetchedNode[0].externalNotificationConfig?.active = config.active + fetchedNode[0].externalNotificationConfig?.output = Int32(config.output) + fetchedNode[0].externalNotificationConfig?.outputBuzzer = Int32(config.outputBuzzer) + fetchedNode[0].externalNotificationConfig?.outputVibra = Int32(config.outputVibra) + fetchedNode[0].externalNotificationConfig?.outputMilliseconds = Int32(config.outputMs) + fetchedNode[0].externalNotificationConfig?.nagTimeout = Int32(config.nagTimeout) + } + + do { + try context.save() + print("πŸ’Ύ Updated External Notification Module Config for node number: \(String(nodeNum))") + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data ExternalNotificationConfigEntity: \(nsError)") + } + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save External Notifiation Module Config") + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data ExternalNotificationConfigEntity failed: \(nsError)") + } +} + +func upsertMqttModuleConfigPacket(config: Meshtastic.ModuleConfig.MQTTConfig, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.mqtt.config %@", comment: "MQTT module config received: %@"), String(nodeNum)) + MeshLogger.log("πŸŒ‰ \(logString)") + + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) + + do { + + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] + // Found a node, save MQTT Config + if !fetchedNode.isEmpty { + + if fetchedNode[0].mqttConfig == nil { + let newMQTTConfig = MQTTConfigEntity(context: context) + newMQTTConfig.enabled = config.enabled + newMQTTConfig.address = config.address + newMQTTConfig.address = config.username + newMQTTConfig.password = config.password + newMQTTConfig.encryptionEnabled = config.encryptionEnabled + newMQTTConfig.jsonEnabled = config.jsonEnabled + fetchedNode[0].mqttConfig = newMQTTConfig + } else { + fetchedNode[0].mqttConfig?.enabled = config.enabled + fetchedNode[0].mqttConfig?.address = config.address + fetchedNode[0].mqttConfig?.address = config.username + fetchedNode[0].mqttConfig?.password = config.password + fetchedNode[0].mqttConfig?.encryptionEnabled = config.encryptionEnabled + fetchedNode[0].mqttConfig?.jsonEnabled = config.jsonEnabled + } + do { + try context.save() + print("πŸ’Ύ Updated MQTT Config for node number: \(String(nodeNum))") + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data MQTTConfigEntity: \(nsError)") + } + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save MQTT Module Config") + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data MQTTConfigEntity failed: \(nsError)") + } +} + +func upsertRangeTestModuleConfigPacket(config: Meshtastic.ModuleConfig.RangeTestConfig, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.rangetest.config %@", comment: "Range Test module config received: %@"), String(nodeNum)) + MeshLogger.log("⛰️ \(logString)") + + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) + + do { + + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] + // Found a node, save Device Config + if !fetchedNode.isEmpty { + if fetchedNode[0].rangeTestConfig == nil { + let newRangeTestConfig = RangeTestConfigEntity(context: context) + newRangeTestConfig.sender = Int32(config.sender) + newRangeTestConfig.enabled = config.enabled + newRangeTestConfig.save = config.save + fetchedNode[0].rangeTestConfig = newRangeTestConfig + } else { + fetchedNode[0].rangeTestConfig?.sender = Int32(config.sender) + fetchedNode[0].rangeTestConfig?.enabled = config.enabled + fetchedNode[0].rangeTestConfig?.save = config.save + } + do { + try context.save() + print("πŸ’Ύ Updated Range Test Config for node number: \(String(nodeNum))") + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data RangeTestConfigEntity: \(nsError)") + } + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Range Test Module Config") + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data RangeTestConfigEntity failed: \(nsError)") + } +} + +func upsertSerialModuleConfigPacket(config: Meshtastic.ModuleConfig.SerialConfig, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.serial.config %@", comment: "Serial module config received: %@"), String(nodeNum)) + MeshLogger.log("πŸ€– \(logString)") + + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) + + do { + + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] + + // Found a node, save Device Config + if !fetchedNode.isEmpty { + + if fetchedNode[0].serialConfig == nil { + + let newSerialConfig = SerialConfigEntity(context: context) + newSerialConfig.enabled = config.enabled + newSerialConfig.echo = config.echo + newSerialConfig.rxd = Int32(config.rxd) + newSerialConfig.txd = Int32(config.txd) + newSerialConfig.baudRate = Int32(config.baud.rawValue) + newSerialConfig.timeout = Int32(config.timeout) + newSerialConfig.mode = Int32(config.mode.rawValue) + fetchedNode[0].serialConfig = newSerialConfig + + } else { + fetchedNode[0].serialConfig?.enabled = config.enabled + fetchedNode[0].serialConfig?.echo = config.echo + fetchedNode[0].serialConfig?.rxd = Int32(config.rxd) + fetchedNode[0].serialConfig?.txd = Int32(config.txd) + fetchedNode[0].serialConfig?.baudRate = Int32(config.baud.rawValue) + fetchedNode[0].serialConfig?.timeout = Int32(config.timeout) + fetchedNode[0].serialConfig?.mode = Int32(config.mode.rawValue) + } + + do { + try context.save() + print("πŸ’Ύ Updated Serial Module Config for node number: \(String(nodeNum))") + + } catch { + + context.rollback() + + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data SerialConfigEntity: \(nsError)") + } + + } else { + + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Serial Module Config") + } + + } catch { + + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data SerialConfigEntity failed: \(nsError)") + } +} + +func upsertTelemetryModuleConfigPacket(config: Meshtastic.ModuleConfig.TelemetryConfig, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.telemetry.config %@", comment: "Telemetry module config received: %@"), String(nodeNum)) + MeshLogger.log("πŸ“ˆ \(logString)") + + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "NodeInfoEntity") + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) + + do { + + let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] + // Found a node, save Telemetry Config + if !fetchedNode.isEmpty { + + if fetchedNode[0].telemetryConfig == nil { + + let newTelemetryConfig = TelemetryConfigEntity(context: context) + + newTelemetryConfig.deviceUpdateInterval = Int32(config.deviceUpdateInterval) + newTelemetryConfig.environmentUpdateInterval = Int32(config.environmentUpdateInterval) + newTelemetryConfig.environmentMeasurementEnabled = config.environmentMeasurementEnabled + newTelemetryConfig.environmentScreenEnabled = config.environmentScreenEnabled + newTelemetryConfig.environmentDisplayFahrenheit = config.environmentDisplayFahrenheit + + fetchedNode[0].telemetryConfig = newTelemetryConfig + + } else { + + fetchedNode[0].telemetryConfig?.deviceUpdateInterval = Int32(config.deviceUpdateInterval) + fetchedNode[0].telemetryConfig?.environmentUpdateInterval = Int32(config.environmentUpdateInterval) + fetchedNode[0].telemetryConfig?.environmentMeasurementEnabled = config.environmentMeasurementEnabled + fetchedNode[0].telemetryConfig?.environmentScreenEnabled = config.environmentScreenEnabled + fetchedNode[0].telemetryConfig?.environmentDisplayFahrenheit = config.environmentDisplayFahrenheit + } + + do { + try context.save() + print("πŸ’Ύ Updated Telemetry Module Config for node number: \(String(nodeNum))") + + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data TelemetryConfigEntity: \(nsError)") + } + + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Telemetry Module Config") + } + + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data TelemetryConfigEntity failed: \(nsError)") + } +} diff --git a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift index c9c5374f..d4057971 100644 --- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift @@ -200,7 +200,7 @@ struct CannedMessagesConfig: View { .disabled(configPreset > 0) } .scrollDismissesKeyboard(.immediately) - .disabled(bleManager.connectedPeripheral == nil) + .disabled(self.bleManager.connectedPeripheral == nil || node?.cannedMessageConfig == nil) Button { isPresentingSaveConfirm = true @@ -287,6 +287,15 @@ struct CannedMessagesConfig: View { self.messages = node?.cannedMessageConfig?.messages ?? "" self.hasChanges = false self.hasMessagesChanges = false + + // Need to request a CannedMessagesModuleConfig from the remote node before allowing changes + if bleManager.connectedPeripheral != nil && node?.cannedMessageConfig == nil { + print("empty canned messages module config") + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + if connectedNode.id > 0 { + _ = bleManager.requestCannedMessagesModuleConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } .onChange(of: configPreset) { newPreset in diff --git a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift index 90b8e759..2a6e5222 100644 --- a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift @@ -138,7 +138,7 @@ struct ExternalNotificationConfig: View { } } } - .disabled(bleManager.connectedPeripheral == nil) + .disabled(self.bleManager.connectedPeripheral == nil || node?.externalNotificationConfig == nil) Button { isPresentingSaveConfirm = true } label: { @@ -154,7 +154,8 @@ struct ExternalNotificationConfig: View { isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { - let nodeName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : NSLocalizedString("unknown", comment: "Unknown") + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + let nodeName = node?.user?.longName ?? NSLocalizedString("unknown", comment: "Unknown") let buttonText = String.localizedStringWithFormat(NSLocalizedString("save.config %@", comment: "Save Config for %@"), nodeName) Button(buttonText) { var enc = ModuleConfig.ExternalNotificationConfig() @@ -171,7 +172,7 @@ struct ExternalNotificationConfig: View { enc.outputVibra = UInt32(outputVibra) enc.outputMs = UInt32(outputMilliseconds) enc.usePwm = usePWM - let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: node!.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: connectedNode.user!, toUser: node!.user!) if adminMessageId > 0{ // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save @@ -205,6 +206,15 @@ struct ExternalNotificationConfig: View { self.nagTimeout = Int(node?.externalNotificationConfig?.nagTimeout ?? 0) self.usePWM = node?.externalNotificationConfig?.usePWM ?? false self.hasChanges = false + + // Need to request a TelemetryModuleConfig from the remote node before allowing changes + if bleManager.connectedPeripheral != nil && node?.externalNotificationConfig == nil { + print("empty external notification module config") + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + if connectedNode.id > 0 { + _ = bleManager.requestExternalNotificationModuleConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } .onChange(of: enabled) { newEnabled in if node != nil && node!.externalNotificationConfig != nil { diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index 54f63e6d..7939a439 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -126,7 +126,7 @@ struct MQTTConfig: View { .font(.callout) } .scrollDismissesKeyboard(.interactively) - .disabled(!(node != nil)) + .disabled(self.bleManager.connectedPeripheral == nil || node?.mqttConfig == nil) Button { isPresentingSaveConfirm = true @@ -143,7 +143,8 @@ struct MQTTConfig: View { isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { - let nodeName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : NSLocalizedString("unknown", comment: "Unknown") + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + let nodeName = node?.user?.longName ?? NSLocalizedString("unknown", comment: "Unknown") let buttonText = String.localizedStringWithFormat(NSLocalizedString("save.config %@", comment: "Save Config for %@"), nodeName) Button(buttonText) { var mqtt = ModuleConfig.MQTTConfig() @@ -153,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: node!.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveMQTTConfig(config: mqtt, fromUser: connectedNode.user!, toUser: node!.user!) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true // for now just disable the button after a successful save @@ -179,6 +180,15 @@ struct MQTTConfig: View { self.encryptionEnabled = (node?.mqttConfig?.encryptionEnabled ?? false) self.jsonEnabled = (node?.mqttConfig?.jsonEnabled ?? false) self.hasChanges = false + + // Need to request a TelemetryModuleConfig from the remote node before allowing changes + if bleManager.connectedPeripheral != nil && node?.telemetryConfig == nil { + print("empty mqtt module config") + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + if connectedNode.id > 0 { + _ = bleManager.requestMqttModuleConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } .onChange(of: enabled) { newEnabled in if node != nil && node?.mqttConfig != nil { diff --git a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift index e515244c..5bd0409d 100644 --- a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift @@ -97,7 +97,7 @@ struct SerialConfig: View { .font(.caption) } } - .disabled(node == nil) + .disabled(self.bleManager.connectedPeripheral == nil || node?.serialConfig == nil) Button { @@ -118,9 +118,10 @@ struct SerialConfig: View { isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { - let nodeName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : NSLocalizedString("unknown", comment: "Unknown") + let nodeName = node?.user?.longName ?? NSLocalizedString("unknown", comment: "Unknown") let buttonText = String.localizedStringWithFormat(NSLocalizedString("save.config %@", comment: "Save Config for %@"), nodeName) Button(buttonText) { + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) var sc = ModuleConfig.SerialConfig() sc.enabled = enabled sc.echo = echo @@ -130,7 +131,7 @@ struct SerialConfig: View { sc.timeout = UInt32(timeout) sc.mode = SerialModeTypes(rawValue: mode)!.protoEnumValue() - let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: node!.user!, toUser: node!.user!) + let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: connectedNode.user!, toUser: node!.user!) if adminMessageId > 0 { // Should show a saved successfully alert once I know that to be true @@ -160,6 +161,15 @@ struct SerialConfig: View { self.timeout = Int(node?.serialConfig?.timeout ?? 0) self.mode = Int(node?.serialConfig?.mode ?? 0) self.hasChanges = false + + // Need to request a SerialModuleConfig from the remote node before allowing changes + if bleManager.connectedPeripheral != nil && node?.serialConfig == nil { + print("empty serial module config") + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + if connectedNode.id > 0 { + _ = bleManager.requestSerialModuleConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0) + } + } } .onChange(of: enabled) { newEnabled in diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index cd11ca6f..93bb597e 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -194,7 +194,6 @@ struct Settings: View { Text("canned.messages") } .tag(SettingsSidebar.cannedMessagesConfig) - .disabled(selectedNode > 0 && selectedNode != connectedNodeNum) NavigationLink { ExternalNotificationConfig(node: nodes.first(where: { $0.num == selectedNode })) @@ -204,7 +203,6 @@ struct Settings: View { Text("external.notification") } .tag(SettingsSidebar.externalNotificationConfig) - .disabled(selectedNode > 0 && selectedNode != connectedNodeNum) NavigationLink { MQTTConfig(node: nodes.first(where: { $0.num == selectedNode })) @@ -214,7 +212,6 @@ struct Settings: View { Text("mqtt") } .tag(SettingsSidebar.mqttConfig) - .disabled(selectedNode > 0 && selectedNode != connectedNodeNum) NavigationLink { RangeTestConfig(node: nodes.first(where: { $0.num == selectedNode })) @@ -233,7 +230,6 @@ struct Settings: View { Text("serial") } .tag(SettingsSidebar.serialConfig) - .disabled(selectedNode > 0 && selectedNode != connectedNodeNum) NavigationLink { TelemetryConfig(node: nodes.first(where: { $0.num == selectedNode }))