2022-10-03 16:52:00 -07:00
//
// U p d a t e C o r e D a t a . s w i f t
// M e s h t a s t i c
//
// C o p y r i g h t ( c ) G a r t h V a n d e r H o u w e n 1 0 / 3 / 2 2 .
2022-10-03 20:13:33 -07:00
2022-10-03 16:52:00 -07:00
import CoreData
public func clearPositions ( destNum : Int64 , context : NSManagedObjectContext ) -> Bool {
let fetchNodeInfoRequest : NSFetchRequest < NSFetchRequestResult > = 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 )
do {
try context . save ( )
return true
} catch {
context . rollback ( )
return false
}
} catch {
print ( " 💥 Fetch NodeInfoEntity Error " )
return false
}
2022-10-03 20:13:33 -07:00
}
public func clearTelemetry ( destNum : Int64 , metricsType : Int32 , context : NSManagedObjectContext ) -> Bool {
let fetchNodeInfoRequest : NSFetchRequest < NSFetchRequestResult > = 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 )
do {
try context . save ( )
return true
} catch {
context . rollback ( )
return false
}
2022-10-03 16:52:00 -07:00
2022-10-03 20:13:33 -07:00
} catch {
print ( " 💥 Fetch NodeInfoEntity Error " )
return false
}
2022-10-03 16:52:00 -07:00
}
2022-10-03 21:19:10 -07:00
2022-12-17 23:53:06 -08:00
public func deleteChannelMessages ( channel : ChannelEntity , context : NSManagedObjectContext ) {
2022-11-24 23:25:44 -08:00
do {
2023-01-25 23:01:45 -08:00
let objects = channel . allPrivateMessages
2022-12-03 01:08:06 -08:00
for object in objects {
context . delete ( object )
}
2022-11-24 23:25:44 -08:00
try context . save ( )
} catch let error as NSError {
print ( " Error: \( error . localizedDescription ) " )
}
}
2022-11-25 00:22:51 -08:00
public func deleteUserMessages ( user : UserEntity , context : NSManagedObjectContext ) {
do {
2023-01-25 23:01:45 -08:00
let objects = user . messageList
2022-12-03 01:08:06 -08:00
for object in objects {
context . delete ( object )
}
2022-11-25 00:22:51 -08:00
try context . save ( )
} catch let error as NSError {
print ( " Error: \( error . localizedDescription ) " )
}
}
2022-10-03 21:19:10 -07:00
public func clearCoreDataDatabase ( context : NSManagedObjectContext ) {
let persistenceController = PersistenceController . shared . container
for i in 0. . . persistenceController . managedObjectModel . entities . count - 1 {
let entity = persistenceController . managedObjectModel . entities [ i ]
2022-10-06 08:56:15 -07:00
let query = NSFetchRequest < NSFetchRequestResult > ( entityName : entity . name ! )
let deleteRequest = NSBatchDeleteRequest ( fetchRequest : query )
2022-11-24 23:25:44 -08:00
do {
try context . executeAndMergeChanges ( using : deleteRequest )
2022-11-25 00:26:13 -08:00
} catch let error as NSError {
2022-11-24 23:25:44 -08:00
print ( error )
2022-11-25 00:26:13 -08:00
}
2022-10-03 21:19:10 -07:00
}
}
2023-01-20 19:14:49 -08:00
2023-01-25 23:01:45 -08:00
func upsertPositionPacket ( packet : MeshPacket , context : NSManagedObjectContext ) {
let logString = String . localizedStringWithFormat ( NSLocalizedString ( " mesh.log.position.received %@ " , comment : " Position Packet received from node: %@ " ) , String ( packet . from ) )
MeshLogger . log ( " 📍 \( logString ) " )
let fetchNodePositionRequest : NSFetchRequest < NSFetchRequestResult > = NSFetchRequest . init ( entityName : " NodeInfoEntity " )
fetchNodePositionRequest . predicate = NSPredicate ( format : " num == %lld " , Int64 ( packet . from ) )
do {
if let positionMessage = try ? Position ( serializedData : packet . decoded . payload ) {
// D o n ' t s a v e e m p t y p o s i t i o n p a c k e t s
if positionMessage . longitudeI > 0 || positionMessage . latitudeI > 0 && ( positionMessage . latitudeI != 373346000 && positionMessage . longitudeI != - 1220090000 )
{
let fetchedNode = try context . fetch ( fetchNodePositionRequest ) as ! [ NodeInfoEntity ]
if fetchedNode . count = = 1 {
let position = PositionEntity ( context : context )
position . snr = packet . rxSnr
position . seqNo = Int32 ( positionMessage . seqNumber )
position . latitudeI = positionMessage . latitudeI
position . longitudeI = positionMessage . longitudeI
position . altitude = positionMessage . altitude
position . satsInView = Int32 ( positionMessage . satsInView )
position . speed = Int32 ( positionMessage . groundSpeed )
position . heading = Int32 ( positionMessage . groundTrack )
if positionMessage . timestamp != 0 {
position . time = Date ( timeIntervalSince1970 : TimeInterval ( Int64 ( positionMessage . timestamp ) ) )
} else {
position . time = Date ( timeIntervalSince1970 : TimeInterval ( Int64 ( positionMessage . time ) ) )
}
let mutablePositions = fetchedNode [ 0 ] . positions ! . mutableCopy ( ) as ! NSMutableOrderedSet
mutablePositions . add ( position )
fetchedNode [ 0 ] . id = Int64 ( packet . from )
fetchedNode [ 0 ] . num = Int64 ( packet . from )
fetchedNode [ 0 ] . lastHeard = Date ( timeIntervalSince1970 : TimeInterval ( Int64 ( positionMessage . time ) ) )
fetchedNode [ 0 ] . snr = packet . rxSnr
fetchedNode [ 0 ] . positions = mutablePositions . copy ( ) as ? NSOrderedSet
do {
try context . save ( )
print ( " 💾 Updated Node Position Coordinates, SNR and Time from Position App Packet For: \( fetchedNode [ 0 ] . num ) " )
} catch {
context . rollback ( )
let nsError = error as NSError
print ( " 💥 Error Saving NodeInfoEntity from POSITION_APP \( nsError ) " )
}
}
} else {
print ( " 💥 Empty POSITION_APP Packet " )
print ( try ! packet . jsonString ( ) )
}
}
} catch {
print ( " 💥 Error Deserializing POSITION_APP packet. " )
}
}
2023-01-23 17:56:04 -08:00
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 < NSFetchRequestResult > = NSFetchRequest . init ( entityName : " NodeInfoEntity " )
fetchNodeInfoRequest . predicate = NSPredicate ( format : " num == %lld " , Int64 ( nodeNum ) )
do {
let fetchedNode = try context . fetch ( fetchNodeInfoRequest ) as ! [ NodeInfoEntity ]
// F o u n d a n o d e , s a v e D e v i c e C o n f i g
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 < NSFetchRequestResult > = NSFetchRequest . init ( entityName : " NodeInfoEntity " )
fetchNodeInfoRequest . predicate = NSPredicate ( format : " num == %lld " , Int64 ( nodeNum ) )
do {
let fetchedNode = try context . fetch ( fetchNodeInfoRequest ) as ! [ NodeInfoEntity ]
// F o u n d a n o d e , s a v e D e v i c e C o n f i g
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 < NSFetchRequestResult > = NSFetchRequest . init ( entityName : " NodeInfoEntity " )
fetchNodeInfoRequest . predicate = NSPredicate ( format : " num == %lld " , Int64 ( nodeNum ) )
do {
let fetchedNode = try context . fetch ( fetchNodeInfoRequest ) as ! [ NodeInfoEntity ]
// F o u n d a n o d e , s a v e D e v i c e C o n f i g
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 )
2023-01-25 23:01:45 -08:00
newDisplayConfig . displayMode = Int32 ( config . display . displaymode . rawValue )
2023-01-23 17:56:04 -08:00
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 )
2023-01-25 23:01:45 -08:00
fetchedNode [ 0 ] . displayConfig ? . displayMode = Int32 ( config . display . displaymode . rawValue )
2023-01-23 17:56:04 -08:00
}
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 ) {
2023-01-20 19:14:49 -08:00
let logString = String . localizedStringWithFormat ( NSLocalizedString ( " mesh.log.lora.config %@ " , comment : " LoRa config received: %@ " ) , String ( nodeNum ) )
MeshLogger . log ( " 📻 \( logString ) " )
let fetchNodeInfoRequest : NSFetchRequest < NSFetchRequestResult > = NSFetchRequest . init ( entityName : " NodeInfoEntity " )
fetchNodeInfoRequest . predicate = NSPredicate ( format : " num == %lld " , nodeNum )
do {
let fetchedNode = try context . fetch ( fetchNodeInfoRequest ) as ! [ NodeInfoEntity ]
// F o u n d a n o d e , s a v e L o R a C o n f i g
2023-01-23 17:56:04 -08:00
if fetchedNode . count > 0 {
2023-01-20 19:14:49 -08:00
if fetchedNode [ 0 ] . loRaConfig = = nil {
2023-01-23 17:56:04 -08:00
// N o l o r a c o n f i g f o r n o d e , s a v e a n e w l o r a c o n f i g
2023-01-20 19:14:49 -08:00
let newLoRaConfig = LoRaConfigEntity ( context : context )
newLoRaConfig . regionCode = Int32 ( config . lora . region . rawValue )
newLoRaConfig . usePreset = config . lora . usePreset
newLoRaConfig . modemPreset = Int32 ( config . lora . modemPreset . rawValue )
newLoRaConfig . bandwidth = Int32 ( config . lora . bandwidth )
newLoRaConfig . spreadFactor = Int32 ( config . lora . spreadFactor )
newLoRaConfig . codingRate = Int32 ( config . lora . codingRate )
newLoRaConfig . frequencyOffset = config . lora . frequencyOffset
newLoRaConfig . hopLimit = Int32 ( config . lora . hopLimit )
newLoRaConfig . txPower = Int32 ( config . lora . txPower )
newLoRaConfig . txEnabled = config . lora . txEnabled
newLoRaConfig . channelNum = Int32 ( config . lora . channelNum )
fetchedNode [ 0 ] . loRaConfig = newLoRaConfig
} else {
fetchedNode [ 0 ] . loRaConfig ? . regionCode = Int32 ( config . lora . region . rawValue )
fetchedNode [ 0 ] . loRaConfig ? . usePreset = config . lora . usePreset
fetchedNode [ 0 ] . loRaConfig ? . modemPreset = Int32 ( config . lora . modemPreset . rawValue )
fetchedNode [ 0 ] . loRaConfig ? . bandwidth = Int32 ( config . lora . bandwidth )
fetchedNode [ 0 ] . loRaConfig ? . spreadFactor = Int32 ( config . lora . spreadFactor )
fetchedNode [ 0 ] . loRaConfig ? . codingRate = Int32 ( config . lora . codingRate )
fetchedNode [ 0 ] . loRaConfig ? . frequencyOffset = config . lora . frequencyOffset
fetchedNode [ 0 ] . loRaConfig ? . hopLimit = Int32 ( config . lora . hopLimit )
fetchedNode [ 0 ] . loRaConfig ? . txPower = Int32 ( config . lora . txPower )
fetchedNode [ 0 ] . loRaConfig ? . txEnabled = config . lora . txEnabled
fetchedNode [ 0 ] . loRaConfig ? . channelNum = Int32 ( config . lora . channelNum )
}
do {
try context . save ( )
print ( " 💾 Updated LoRa Config for node number: \( String ( nodeNum ) ) " )
} catch {
context . rollback ( )
let nsError = error as NSError
print ( " 💥 Error Updating Core Data LoRaConfigEntity: \( nsError ) " )
}
} else {
print ( " 💥 No Nodes found in local database matching node number \( nodeNum ) unable to save Lora Config " )
}
} catch {
let nsError = error as NSError
print ( " 💥 Fetching node for core data LoRaConfigEntity failed: \( nsError ) " )
}
}
2023-01-23 17:56:04 -08:00
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 < NSFetchRequestResult > = NSFetchRequest . init ( entityName : " NodeInfoEntity " )
fetchNodeInfoRequest . predicate = NSPredicate ( format : " num == %lld " , Int64 ( nodeNum ) )
do {
let fetchedNode = try context . fetch ( fetchNodeInfoRequest ) as ! [ NodeInfoEntity ]
// F o u n d a n o d e , s a v e W i F i C o n f i g
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 < NSFetchRequestResult > = NSFetchRequest . init ( entityName : " NodeInfoEntity " )
fetchNodeInfoRequest . predicate = NSPredicate ( format : " num == %lld " , Int64 ( nodeNum ) )
do {
let fetchedNode = try context . fetch ( fetchNodeInfoRequest ) as ! [ NodeInfoEntity ]
// F o u n d a n o d e , s a v e L o R a C o n f i g
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 ) " )
}
}