diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 76be7679..2063cddb 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -312,7 +312,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { dataMessage.portnum = PortNum.adminApp dataMessage.wantResponse = true meshPacket.decoded = dataMessage - let messageDescription = "Requested Device Metadata for node \(toUser.longName ?? NSLocalizedString("unknown", comment: "Unknown")) by \(fromUser.longName ?? NSLocalizedString("unknown", comment: "Unknown"))" + let messageDescription = "πŸ›ŽοΈ Requested Device Metadata for node \(toUser.longName ?? NSLocalizedString("unknown", comment: "Unknown")) by \(fromUser.longName ?? NSLocalizedString("unknown", comment: "Unknown"))" if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) { return Int64(meshPacket.id) } @@ -1398,7 +1398,36 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { return false } - public func getLoRaConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool { + public func requestBluetoothConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool { + + var adminPacket = AdminMessage() + adminPacket.getConfigRequest = AdminMessage.ConfigType.bluetoothConfig + + 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.getConfigRequest = AdminMessage.ConfigType.loraConfig @@ -1417,7 +1446,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { meshPacket.decoded = dataMessage - let messageDescription = "πŸ›ŽοΈ Sent a Get LoRa Config request on the admin channel \(adminIndex) for node: \(String(connectedPeripheral.num))" + let messageDescription = "πŸ›ŽοΈ Requested LoRa Config on admin channel \(adminIndex) for node: \(String(connectedPeripheral.num))" if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) { @@ -1578,7 +1607,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject { do { connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse) try context!.save() - print("βš™οΈ \(adminDescription)") + print(adminDescription) return true } catch { context!.rollback() diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index efc248f4..628339b8 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -40,241 +40,17 @@ func localConfig (config: Config, context:NSManagedObjectContext, nodeNum: Int64 // We don't care about any of the Power settings, config is available for everyting else if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.bluetooth.config %@", comment: "Bluetooth 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].bluetoothConfig == nil { - let newBluetoothConfig = BluetoothConfigEntity(context: context) - newBluetoothConfig.enabled = config.bluetooth.enabled - newBluetoothConfig.mode = Int32(config.bluetooth.mode.rawValue) - newBluetoothConfig.fixedPin = Int32(config.bluetooth.fixedPin) - fetchedNode[0].bluetoothConfig = newBluetoothConfig - } else { - fetchedNode[0].bluetoothConfig?.enabled = config.bluetooth.enabled - fetchedNode[0].bluetoothConfig?.mode = Int32(config.bluetooth.mode.rawValue) - fetchedNode[0].bluetoothConfig?.fixedPin = Int32(config.bluetooth.fixedPin) - } - do { - try context.save() - print("πŸ’Ύ Updated Bluetooth Config for node number: \(String(nodeNum))") - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data BluetoothConfigEntity: \(nsError)") - } - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Bluetooth Config") - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data BluetoothConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.device.config %@", comment: "Device 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].deviceConfig == nil { - let newDeviceConfig = DeviceConfigEntity(context: context) - newDeviceConfig.role = Int32(config.device.role.rawValue) - newDeviceConfig.serialEnabled = config.device.serialEnabled - newDeviceConfig.debugLogEnabled = config.device.debugLogEnabled - newDeviceConfig.buttonGpio = Int32(config.device.buttonGpio) - newDeviceConfig.buzzerGpio = Int32(config.device.buzzerGpio) - fetchedNode[0].deviceConfig = newDeviceConfig - } else { - fetchedNode[0].deviceConfig?.role = Int32(config.device.role.rawValue) - fetchedNode[0].deviceConfig?.serialEnabled = config.device.serialEnabled - fetchedNode[0].deviceConfig?.debugLogEnabled = config.device.debugLogEnabled - fetchedNode[0].deviceConfig?.buttonGpio = Int32(config.device.buttonGpio) - fetchedNode[0].deviceConfig?.buzzerGpio = Int32(config.device.buzzerGpio) - } - do { - try context.save() - print("πŸ’Ύ Updated Device Config for node number: \(String(nodeNum))") - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data DeviceConfigEntity: \(nsError)") - } - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data DeviceConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.display.config %@", comment: "Display 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].displayConfig == nil { - - let newDisplayConfig = DisplayConfigEntity(context: context) - newDisplayConfig.gpsFormat = Int32(config.display.gpsFormat.rawValue) - newDisplayConfig.screenOnSeconds = Int32(config.display.screenOnSecs) - newDisplayConfig.screenCarouselInterval = Int32(config.display.autoScreenCarouselSecs) - newDisplayConfig.compassNorthTop = config.display.compassNorthTop - newDisplayConfig.flipScreen = config.display.flipScreen - newDisplayConfig.oledType = Int32(config.display.oled.rawValue) - fetchedNode[0].displayConfig = newDisplayConfig - - } else { - - fetchedNode[0].displayConfig?.gpsFormat = Int32(config.display.gpsFormat.rawValue) - fetchedNode[0].displayConfig?.screenOnSeconds = Int32(config.display.screenOnSecs) - fetchedNode[0].displayConfig?.screenCarouselInterval = Int32(config.display.autoScreenCarouselSecs) - fetchedNode[0].displayConfig?.compassNorthTop = config.display.compassNorthTop - fetchedNode[0].displayConfig?.flipScreen = config.display.flipScreen - fetchedNode[0].displayConfig?.oledType = Int32(config.display.oled.rawValue) - } - - do { - - try context.save() - print("πŸ’Ύ Updated Display Config for node number: \(String(nodeNum))") - - } catch { - - context.rollback() - - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data DisplayConfigEntity: \(nsError)") - } - } else { - - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Display Config") - } - - } catch { - - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data DisplayConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) { - - upsertLoraConfigPacket(config: config, nodeNum: nodeNum, context: context) - } - - if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.network.config %@", comment: "Network 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 WiFi Config - if !fetchedNode.isEmpty { - if fetchedNode[0].networkConfig == nil { - let newNetworkConfig = NetworkConfigEntity(context: context) - newNetworkConfig.wifiSsid = config.network.wifiSsid - newNetworkConfig.wifiPsk = config.network.wifiPsk - fetchedNode[0].networkConfig = newNetworkConfig - } else { - fetchedNode[0].networkConfig?.wifiSsid = config.network.wifiSsid - fetchedNode[0].networkConfig?.wifiPsk = config.network.wifiPsk - } - - do { - try context.save() - print("πŸ’Ύ Updated Network Config for node number: \(String(nodeNum))") - - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data WiFiConfigEntity: \(nsError)") - } - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Network Config") - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data NetworkConfigEntity failed: \(nsError)") - } - } - - if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) { - - let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.position.config %@", comment: "Positon 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 LoRa Config - if !fetchedNode.isEmpty { - if fetchedNode[0].positionConfig == nil { - let newPositionConfig = PositionConfigEntity(context: context) - newPositionConfig.smartPositionEnabled = config.position.positionBroadcastSmartEnabled - newPositionConfig.deviceGpsEnabled = config.position.gpsEnabled - newPositionConfig.fixedPosition = config.position.fixedPosition - newPositionConfig.gpsUpdateInterval = Int32(config.position.gpsUpdateInterval) - newPositionConfig.gpsAttemptTime = Int32(config.position.gpsAttemptTime) - newPositionConfig.positionBroadcastSeconds = Int32(config.position.positionBroadcastSecs) - newPositionConfig.positionFlags = Int32(config.position.positionFlags) - fetchedNode[0].positionConfig = newPositionConfig - } else { - fetchedNode[0].positionConfig?.smartPositionEnabled = config.position.positionBroadcastSmartEnabled - fetchedNode[0].positionConfig?.deviceGpsEnabled = config.position.gpsEnabled - fetchedNode[0].positionConfig?.fixedPosition = config.position.fixedPosition - fetchedNode[0].positionConfig?.gpsUpdateInterval = Int32(config.position.gpsUpdateInterval) - fetchedNode[0].positionConfig?.gpsAttemptTime = Int32(config.position.gpsAttemptTime) - fetchedNode[0].positionConfig?.positionBroadcastSeconds = Int32(config.position.positionBroadcastSecs) - fetchedNode[0].positionConfig?.positionFlags = Int32(config.position.positionFlags) - } - do { - try context.save() - print("πŸ’Ύ Updated Position Config for node number: \(String(nodeNum))") - } catch { - context.rollback() - let nsError = error as NSError - print("πŸ’₯ Error Updating Core Data PositionConfigEntity: \(nsError)") - } - } else { - print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Position Config") - } - } catch { - let nsError = error as NSError - print("πŸ’₯ Fetching node for core data PositionConfigEntity failed: \(nsError)") - } + upsertBluetoothConfigPacket(config: config, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) { + upsertDeviceConfigPacket(config: config, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) { + upsertDisplayConfigPacket(config: config, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) { + upsertLoRaConfigPacket(config: config, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) { + upsertNetworkConfigPacket(config: config, nodeNum: nodeNum, context: context) + } else if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) { + upsertPositionConfigPacket(config: config, nodeNum: nodeNum, context: context) } } @@ -1020,10 +796,16 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) { } else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getConfigResponse(adminMessage.getConfigResponse) { if let config = try? Config(serializedData: packet.decoded.payload) { + if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) { - //upsertLoraConfigPacket(config: config, nodeNum: Int64(packet.from), context: context) + upsertBluetoothConfigPacket(config: config, nodeNum: Int64(packet.from), context: context) + + } else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) { + upsertDeviceConfigPacket(config: config, nodeNum: Int64(packet.from), context: context) + } else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) { - upsertLoraConfigPacket(config: config, nodeNum: Int64(packet.from), context: context) + upsertLoRaConfigPacket(config: config, nodeNum: Int64(packet.from), context: context) + } } } else { diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV6.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV6.xcdatamodel/contents index cabe58ef..5602f840 100644 --- a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV6.xcdatamodel/contents +++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV6.xcdatamodel/contents @@ -274,7 +274,7 @@ - + diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index 53c05627..c739ecde 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -101,7 +101,150 @@ public func clearCoreDataDatabase(context: NSManagedObjectContext) { } } -func upsertLoraConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) { +func upsertBluetoothConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.bluetooth.config %@", comment: "Bluetooth 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].bluetoothConfig == nil { + let newBluetoothConfig = BluetoothConfigEntity(context: context) + newBluetoothConfig.enabled = config.bluetooth.enabled + newBluetoothConfig.mode = Int32(config.bluetooth.mode.rawValue) + newBluetoothConfig.fixedPin = Int32(config.bluetooth.fixedPin) + fetchedNode[0].bluetoothConfig = newBluetoothConfig + } else { + fetchedNode[0].bluetoothConfig?.enabled = config.bluetooth.enabled + fetchedNode[0].bluetoothConfig?.mode = Int32(config.bluetooth.mode.rawValue) + fetchedNode[0].bluetoothConfig?.fixedPin = Int32(config.bluetooth.fixedPin) + } + do { + try context.save() + print("πŸ’Ύ Updated Bluetooth Config for node number: \(String(nodeNum))") + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data BluetoothConfigEntity: \(nsError)") + } + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Bluetooth Config") + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data BluetoothConfigEntity failed: \(nsError)") + } +} + +func upsertDeviceConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.device.config %@", comment: "Device 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].deviceConfig == nil { + let newDeviceConfig = DeviceConfigEntity(context: context) + newDeviceConfig.role = Int32(config.device.role.rawValue) + newDeviceConfig.serialEnabled = config.device.serialEnabled + newDeviceConfig.debugLogEnabled = config.device.debugLogEnabled + newDeviceConfig.buttonGpio = Int32(config.device.buttonGpio) + newDeviceConfig.buzzerGpio = Int32(config.device.buzzerGpio) + fetchedNode[0].deviceConfig = newDeviceConfig + } else { + fetchedNode[0].deviceConfig?.role = Int32(config.device.role.rawValue) + fetchedNode[0].deviceConfig?.serialEnabled = config.device.serialEnabled + fetchedNode[0].deviceConfig?.debugLogEnabled = config.device.debugLogEnabled + fetchedNode[0].deviceConfig?.buttonGpio = Int32(config.device.buttonGpio) + fetchedNode[0].deviceConfig?.buzzerGpio = Int32(config.device.buzzerGpio) + } + do { + try context.save() + print("πŸ’Ύ Updated Device Config for node number: \(String(nodeNum))") + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data DeviceConfigEntity: \(nsError)") + } + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data DeviceConfigEntity failed: \(nsError)") + } +} + +func upsertDisplayConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.display.config %@", comment: "Display 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].displayConfig == nil { + + let newDisplayConfig = DisplayConfigEntity(context: context) + newDisplayConfig.gpsFormat = Int32(config.display.gpsFormat.rawValue) + newDisplayConfig.screenOnSeconds = Int32(config.display.screenOnSecs) + newDisplayConfig.screenCarouselInterval = Int32(config.display.autoScreenCarouselSecs) + newDisplayConfig.compassNorthTop = config.display.compassNorthTop + newDisplayConfig.flipScreen = config.display.flipScreen + newDisplayConfig.oledType = Int32(config.display.oled.rawValue) + fetchedNode[0].displayConfig = newDisplayConfig + + } else { + + fetchedNode[0].displayConfig?.gpsFormat = Int32(config.display.gpsFormat.rawValue) + fetchedNode[0].displayConfig?.screenOnSeconds = Int32(config.display.screenOnSecs) + fetchedNode[0].displayConfig?.screenCarouselInterval = Int32(config.display.autoScreenCarouselSecs) + fetchedNode[0].displayConfig?.compassNorthTop = config.display.compassNorthTop + fetchedNode[0].displayConfig?.flipScreen = config.display.flipScreen + fetchedNode[0].displayConfig?.oledType = Int32(config.display.oled.rawValue) + } + + do { + + try context.save() + print("πŸ’Ύ Updated Display Config for node number: \(String(nodeNum))") + + } catch { + + context.rollback() + + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data DisplayConfigEntity: \(nsError)") + } + } else { + + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Display Config") + } + + } catch { + + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data DisplayConfigEntity failed: \(nsError)") + } +} + +func upsertLoRaConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) { let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.lora.config %@", comment: "LoRa config received: %@"), String(nodeNum)) MeshLogger.log("πŸ“» \(logString)") @@ -113,8 +256,9 @@ func upsertLoraConfigPacket(config: Config, nodeNum: Int64, context: NSManagedOb let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity] // Found a node, save LoRa Config - if !fetchedNode.isEmpty { + if fetchedNode.count > 0 { if fetchedNode[0].loRaConfig == nil { + // No lora config for node, save a new lora config let newLoRaConfig = LoRaConfigEntity(context: context) newLoRaConfig.regionCode = Int32(config.lora.region.rawValue) newLoRaConfig.usePreset = config.lora.usePreset @@ -157,3 +301,93 @@ func upsertLoraConfigPacket(config: Config, nodeNum: Int64, context: NSManagedOb print("πŸ’₯ Fetching node for core data LoRaConfigEntity failed: \(nsError)") } } + +func upsertNetworkConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.network.config %@", comment: "Network 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 WiFi Config + if !fetchedNode.isEmpty { + if fetchedNode[0].networkConfig == nil { + let newNetworkConfig = NetworkConfigEntity(context: context) + newNetworkConfig.wifiSsid = config.network.wifiSsid + newNetworkConfig.wifiPsk = config.network.wifiPsk + fetchedNode[0].networkConfig = newNetworkConfig + } else { + fetchedNode[0].networkConfig?.wifiSsid = config.network.wifiSsid + fetchedNode[0].networkConfig?.wifiPsk = config.network.wifiPsk + } + + do { + try context.save() + print("πŸ’Ύ Updated Network Config for node number: \(String(nodeNum))") + + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data WiFiConfigEntity: \(nsError)") + } + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Network Config") + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data NetworkConfigEntity failed: \(nsError)") + } +} + +func upsertPositionConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) { + + let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.position.config %@", comment: "Positon 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 LoRa Config + if !fetchedNode.isEmpty { + if fetchedNode[0].positionConfig == nil { + let newPositionConfig = PositionConfigEntity(context: context) + newPositionConfig.smartPositionEnabled = config.position.positionBroadcastSmartEnabled + newPositionConfig.deviceGpsEnabled = config.position.gpsEnabled + newPositionConfig.fixedPosition = config.position.fixedPosition + newPositionConfig.gpsUpdateInterval = Int32(config.position.gpsUpdateInterval) + newPositionConfig.gpsAttemptTime = Int32(config.position.gpsAttemptTime) + newPositionConfig.positionBroadcastSeconds = Int32(config.position.positionBroadcastSecs) + newPositionConfig.positionFlags = Int32(config.position.positionFlags) + fetchedNode[0].positionConfig = newPositionConfig + } else { + fetchedNode[0].positionConfig?.smartPositionEnabled = config.position.positionBroadcastSmartEnabled + fetchedNode[0].positionConfig?.deviceGpsEnabled = config.position.gpsEnabled + fetchedNode[0].positionConfig?.fixedPosition = config.position.fixedPosition + fetchedNode[0].positionConfig?.gpsUpdateInterval = Int32(config.position.gpsUpdateInterval) + fetchedNode[0].positionConfig?.gpsAttemptTime = Int32(config.position.gpsAttemptTime) + fetchedNode[0].positionConfig?.positionBroadcastSeconds = Int32(config.position.positionBroadcastSecs) + fetchedNode[0].positionConfig?.positionFlags = Int32(config.position.positionFlags) + } + do { + try context.save() + print("πŸ’Ύ Updated Position Config for node number: \(String(nodeNum))") + } catch { + context.rollback() + let nsError = error as NSError + print("πŸ’₯ Error Updating Core Data PositionConfigEntity: \(nsError)") + } + } else { + print("πŸ’₯ No Nodes found in local database matching node number \(nodeNum) unable to save Position Config") + } + } catch { + let nsError = error as NSError + print("πŸ’₯ Fetching node for core data PositionConfigEntity failed: \(nsError)") + } +} diff --git a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index dcc10981..c4c5a00f 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -14,6 +14,7 @@ struct BluetoothConfig: View { @Environment(\.dismiss) private var goBack var node: NodeInfoEntity? + var connectedNode: NodeInfoEntity? @State private var isPresentingSaveConfirm: Bool = false @State var hasChanges = false @@ -125,6 +126,13 @@ struct BluetoothConfig: View { self.mode = Int(node?.bluetoothConfig?.mode ?? 0) self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456) self.hasChanges = false + + // Need to request a LoRaConfig from the remote node before allowing changes + if node?.bluetoothConfig == nil { + print("empty bluetooth config") + + } + let adminMessageId = bleManager.requestBluetoothConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) } .onChange(of: enabled) { newEnabled in if node != nil && node!.bluetoothConfig != nil { diff --git a/Meshtastic/Views/Settings/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index ac4d277a..bf96724a 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -51,6 +51,8 @@ struct LoRaConfig: View { } Section(header: Text("Mesh Options")) { Picker("Number of hops", selection: $hopLimit) { + Text("Please Select") + .tag(0) ForEach(HopValues.allCases) { hop in Text(hop.description) } @@ -115,10 +117,10 @@ struct LoRaConfig: View { // Need to request a LoRaConfig from the remote node before allowing changes if node?.loRaConfig == nil { - - let adminMessageId = bleManager.getLoRaConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) + print("empty lora config") + let adminMessageId = bleManager.requestLoRaConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0) } - + print(node?.loRaConfig?.regionCode) } .onChange(of: region) { newRegion in if node != nil && node!.loRaConfig != nil { diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 263c0975..258db8e0 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -107,13 +107,13 @@ struct Settings: View { .disabled(selectedNode > 0 && selectedNode != connectedNodeNum) NavigationLink() { - BluetoothConfig(node: nodes.first(where: { $0.num == selectedNode })) + BluetoothConfig(node: nodes.first(where: { $0.num == selectedNode }), connectedNode: nodes.first(where: { $0.num == connectedNodeNum })) } label: { Image(systemName: "antenna.radiowaves.left.and.right") .symbolRenderingMode(.hierarchical) Text("bluetooth") } - .disabled(selectedNode > 0 && selectedNode != connectedNodeNum) + .disabled(selectedNode == 0) NavigationLink { DeviceConfig(node: nodes.first(where: { $0.num == selectedNode })) @@ -221,7 +221,7 @@ struct Settings: View { Text("mesh.log") } NavigationLink { - let connectedNode = nodes.first(where: { $0.num == selectedNode }) + let connectedNode = nodes.first(where: { $0.num == connectedNodeNum }) AdminMessageList(user: connectedNode?.user) } label: { Image(systemName: "building.columns") @@ -243,13 +243,12 @@ struct Settings: View { .onAppear { self.bleManager.context = context self.bleManager.userSettings = userSettings + self.connectedNodeNum = Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.num : 0) if initialLoad { selectedNode = Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.num : 0) initialLoad = false } - connectedNodeNum = Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.num : 0) - //let node = nodes.first(where: { $0.num == connectedNodeNum }) - //selectedNode = node?.num ?? 0 + } .listStyle(GroupedListStyle()) .navigationTitle("settings")