diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift
index 0de3b4cc..dc23c7c0 100644
--- a/Meshtastic/Helpers/BLEManager.swift
+++ b/Meshtastic/Helpers/BLEManager.swift
@@ -1318,9 +1318,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
public func saveCannedMessageModuleMessages(messages: String, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
- var newMessageId: Int64 = 0
-
var adminPacket = AdminMessage()
+
adminPacket.setCannedMessageModulePart1 = messages
var meshPacket: MeshPacket = MeshPacket()
@@ -1335,48 +1334,19 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
dataMessage.portnum = PortNum.adminApp
meshPacket.decoded = dataMessage
-
- var toRadio: ToRadio!
- toRadio = ToRadio()
- toRadio.packet = meshPacket
-
- let binaryData: Data = try! toRadio.serializedData()
- if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
-
- let newMessage = MessageEntity(context: context!)
- newMessage.messageId = Int64(meshPacket.id)
- newMessageId = newMessage.messageId
- newMessage.messageTimestamp = Int32(Date().timeIntervalSince1970)
- newMessage.receivedACK = false
- newMessage.admin = true
- newMessage.adminDescription = "Saved Canned Message Module Messages for \(toUser.longName ?? "Unknown")"
- newMessage.fromUser = fromUser
- newMessage.toUser = toUser
- newMessage.messagePayload = messages
+ let messageDescription = "Saved Canned Message Module Messages for \(toUser.longName ?? "Unknown")"
+
+ if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
- do {
-
- try context!.save()
-
- if meshLoggingEnabled { MeshLogger.log("💾 Saved Canned Message Module Messages Admin Message for node: \(String(toUser.num))") }
- connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
-
- } catch {
-
- context!.rollback()
-
- let nsError = error as NSError
- print("💥 Error Inserting New Core Data MessageEntity: \(nsError)")
- }
+ return Int64(meshPacket.id)
}
- return newMessageId
+
+ return 0
}
public func saveExternalNotificationModuleConfig(config: ModuleConfig.ExternalNotificationConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
-
- var newMessageId: Int64 = 0
-
+
var adminPacket = AdminMessage()
adminPacket.setModuleConfig.externalNotification = config
@@ -1393,47 +1363,18 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
meshPacket.decoded = dataMessage
- var toRadio: ToRadio!
- toRadio = ToRadio()
- toRadio.packet = meshPacket
-
- let binaryData: Data = try! toRadio.serializedData()
+ let messageDescription = "Saved External Notification Module Config for \(toUser.longName ?? "Unknown")"
- if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
-
- let newMessage = MessageEntity(context: context!)
- newMessage.messageId = Int64(meshPacket.id)
- newMessageId = newMessage.messageId
- newMessage.messageTimestamp = Int32(Date().timeIntervalSince1970)
- newMessage.receivedACK = false
- newMessage.admin = true
- newMessage.adminDescription = "Saved External Notification Module Config for \(toUser.longName ?? "Unknown")"
- newMessage.fromUser = fromUser
- newMessage.toUser = toUser
- newMessage.messagePayload = try! config.jsonString()
+ if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
- do {
-
- try context!.save()
-
- if meshLoggingEnabled { MeshLogger.log("💾 Saved External Notification Module Config Admin Message for node: \(String(toUser.num))") }
- connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
-
- } catch {
-
- context!.rollback()
-
- let nsError = error as NSError
- print("💥 Error Inserting New Core Data MessageEntity: \(nsError)")
- }
+ return Int64(meshPacket.id)
}
- return newMessageId
+
+ return 0
}
public func saveRangeTestModuleConfig(config: ModuleConfig.RangeTestConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
- var newMessageId: Int64 = 0
-
var adminPacket = AdminMessage()
adminPacket.setModuleConfig.rangeTest = config
@@ -1450,47 +1391,18 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
meshPacket.decoded = dataMessage
- var toRadio: ToRadio!
- toRadio = ToRadio()
- toRadio.packet = meshPacket
-
- let binaryData: Data = try! toRadio.serializedData()
+ let messageDescription = "Saved Range Test Module Config for \(toUser.longName ?? "Unknown")"
- if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
-
- let newMessage = MessageEntity(context: context!)
- newMessage.messageId = Int64(meshPacket.id)
- newMessageId = newMessage.messageId
- newMessage.messageTimestamp = Int32(Date().timeIntervalSince1970)
- newMessage.receivedACK = false
- newMessage.admin = true
- newMessage.adminDescription = "Saved Range Test Module Config for \(toUser.longName ?? "Unknown")"
- newMessage.fromUser = fromUser
- newMessage.toUser = toUser
- newMessage.messagePayload = try! config.jsonString()
+ if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
- do {
-
- try context!.save()
-
- if meshLoggingEnabled { MeshLogger.log("💾 Saved a new Range Test Module Config Admin Message for node: \(String(toUser.num))") }
- connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
-
- } catch {
-
- context!.rollback()
-
- let nsError = error as NSError
- print("💥 Error Inserting New Core Data MessageEntity: \(nsError)")
- }
+ return Int64(meshPacket.id)
}
- return newMessageId
+
+ return 0
}
public func saveSerialModuleConfig(config: ModuleConfig.SerialConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
- var newMessageId: Int64 = 0
-
var adminPacket = AdminMessage()
adminPacket.setModuleConfig.serial = config
@@ -1508,47 +1420,18 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
meshPacket.decoded = dataMessage
- var toRadio: ToRadio!
- toRadio = ToRadio()
- toRadio.packet = meshPacket
-
- let binaryData: Data = try! toRadio.serializedData()
+ let messageDescription = "Saved Serial Module Config for \(toUser.longName ?? "Unknown")"
- if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
-
- let newMessage = MessageEntity(context: context!)
- newMessage.messageId = Int64(meshPacket.id)
- newMessageId = newMessage.messageId
- newMessage.messageTimestamp = Int32(Date().timeIntervalSince1970)
- newMessage.receivedACK = false
- newMessage.admin = true
- newMessage.adminDescription = "Saved Serial Module Config for \(toUser.longName ?? "Unknown")"
- newMessage.fromUser = fromUser
- newMessage.toUser = toUser
- newMessage.messagePayload = try! config.jsonString()
+ if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
- do {
-
- try context!.save()
-
- if meshLoggingEnabled { MeshLogger.log("💾 Saved Serial Module Config Admin Message for node: \(String(toUser.num))") }
- connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
-
- } catch {
-
- context!.rollback()
-
- let nsError = error as NSError
- print("💥 Error Inserting New Core Data MessageEntity: \(nsError)")
- }
+ return Int64(meshPacket.id)
}
- return newMessageId
+
+ return 0
}
public func saveTelemetryModuleConfig(config: ModuleConfig.TelemetryConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
-
- var newMessageId: Int64 = 0
-
+
var adminPacket = AdminMessage()
adminPacket.setModuleConfig.telemetry = config
@@ -1565,6 +1448,19 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
meshPacket.decoded = dataMessage
+ let messageDescription = "Saved Telemetry Module Config for \(toUser.longName ?? "Unknown")"
+
+ if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
+
+ return Int64(meshPacket.id)
+ }
+
+ return 0
+ }
+
+ // Send an admin message to a radio, save a message to core data for logging
+ private func sendAdminMessageToRadio(meshPacket: MeshPacket, adminDescription: String, fromUser: UserEntity, toUser: UserEntity) -> Bool {
+
var toRadio: ToRadio!
toRadio = ToRadio()
toRadio.packet = meshPacket
@@ -1575,40 +1471,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
let newMessage = MessageEntity(context: context!)
newMessage.messageId = Int64(meshPacket.id)
- newMessageId = newMessage.messageId
- newMessage.messageTimestamp = Int32(Date().timeIntervalSince1970)
- newMessage.receivedACK = false
- newMessage.admin = true
- newMessage.adminDescription = "Saved Telemetry Module Config for \(toUser.longName ?? "Unknown")"
- newMessage.fromUser = fromUser
- newMessage.toUser = toUser
- newMessage.messagePayload = try! config.jsonString()
-
- do {
-
- try context!.save()
-
- if meshLoggingEnabled { MeshLogger.log("💾 Saved Telemetry Module Config Admin Message for node number: \(String(toUser.num))") }
- connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
-
- } catch {
-
- context!.rollback()
-
- let nsError = error as NSError
- print("💥 Error Inserting New Core Data MessageEntity: \(nsError)")
- }
- }
- return newMessageId
- }
-
- // Send an admin message to a radio, save a message to core data for logging
- private func sendAdminMessageToRadio(adminDescription: String, messageId: Int64, fromUser: UserEntity, toUser: UserEntity, binaryData: Data) {
-
- if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
-
- let newMessage = MessageEntity(context: context!)
- newMessage.messageId = Int64(messageId)
newMessage.messageTimestamp = Int32(Date().timeIntervalSince1970)
newMessage.receivedACK = false
newMessage.admin = true
@@ -1618,10 +1480,13 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
do {
+ connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
+
try context!.save()
if meshLoggingEnabled { MeshLogger.log("💾 \(adminDescription)") }
- connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
+
+ return true
} catch {
@@ -1630,6 +1495,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
let nsError = error as NSError
print("💥 Error inserting new core data MessageEntity: \(nsError)")
}
+
}
+ return false
}
}
diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 4.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 4.xcdatamodel/contents
index 4945a75d..d8b141ee 100644
--- a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 4.xcdatamodel/contents
+++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 4.xcdatamodel/contents
@@ -52,7 +52,7 @@
-
+
diff --git a/Meshtastic/Persistence/Persistence.swift b/Meshtastic/Persistence/Persistence.swift
index c37af6e4..8a317e9c 100644
--- a/Meshtastic/Persistence/Persistence.swift
+++ b/Meshtastic/Persistence/Persistence.swift
@@ -34,7 +34,7 @@ class PersistenceController {
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "Meshtastic")
- //self.clearDatabase()
+ self.clearDatabase()
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
diff --git a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift
index d6c19f29..af0e07b7 100644
--- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift
+++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift
@@ -105,6 +105,7 @@ struct CannedMessagesConfig: View {
@State private var isPresentingSaveConfirm: Bool = false
@State var initialLoad: Bool = true
@State var hasChanges = false
+ @State var hasMessagesChanges = false
@State var configPreset = 0
@State var enabled = false
@@ -278,7 +279,7 @@ struct CannedMessagesConfig: View {
Label("Save", systemImage: "square.and.arrow.down")
}
- .disabled(bleManager.connectedPeripheral == nil || !hasChanges)
+ .disabled(bleManager.connectedPeripheral == nil || (!hasChanges && !hasMessagesChanges))
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
@@ -290,40 +291,54 @@ struct CannedMessagesConfig: View {
) {
Button("Save Canned Messages Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
- var cmc = ModuleConfig.CannedMessageConfig()
- cmc.enabled = enabled
- cmc.sendBell = sendBell
- cmc.rotary1Enabled = rotary1Enabled
- cmc.updown1Enabled = updown1Enabled
- if rotary1Enabled {
-
- /// Input event origin accepted by the canned messages
- /// Can be e.g. "rotEnc1", "upDownEnc1", "cardkb", "faceskb" 623or keyword "_any"
- cmc.allowInputSource = "rotEnc1"
-
- } else if updown1Enabled {
-
- cmc.allowInputSource = "upDownEnc1"
-
- } else {
-
- cmc.allowInputSource = "_any"
- }
- cmc.inputbrokerPinA = UInt32(inputbrokerPinA)
- cmc.inputbrokerPinB = UInt32(inputbrokerPinB)
- cmc.inputbrokerPinPress = UInt32(inputbrokerPinPress)
- cmc.inputbrokerEventCw = InputEventChars(rawValue: inputbrokerEventCw)!.protoEnumValue()
- cmc.inputbrokerEventCcw = InputEventChars(rawValue: inputbrokerEventCcw)!.protoEnumValue()
- cmc.inputbrokerEventPress = InputEventChars(rawValue: inputbrokerEventPress)!.protoEnumValue()
+ if hasChanges {
- let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
+ var cmc = ModuleConfig.CannedMessageConfig()
+ cmc.enabled = enabled
+ cmc.sendBell = sendBell
+ cmc.rotary1Enabled = rotary1Enabled
+ cmc.updown1Enabled = updown1Enabled
+ if rotary1Enabled {
+
+ /// Input event origin accepted by the canned messages
+ /// Can be e.g. "rotEnc1", "upDownEnc1", "cardkb", "faceskb" 623or keyword "_any"
+ cmc.allowInputSource = "rotEnc1"
+
+ } else if updown1Enabled {
+
+ cmc.allowInputSource = "upDownEnc1"
+
+ } else {
+
+ cmc.allowInputSource = "_any"
+ }
+ cmc.inputbrokerPinA = UInt32(inputbrokerPinA)
+ cmc.inputbrokerPinB = UInt32(inputbrokerPinB)
+ cmc.inputbrokerPinPress = UInt32(inputbrokerPinPress)
+ cmc.inputbrokerEventCw = InputEventChars(rawValue: inputbrokerEventCw)!.protoEnumValue()
+ cmc.inputbrokerEventCcw = InputEventChars(rawValue: inputbrokerEventCcw)!.protoEnumValue()
+ cmc.inputbrokerEventPress = InputEventChars(rawValue: inputbrokerEventPress)!.protoEnumValue()
+
+ let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
+
+ 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
+ hasChanges = false
+ }
+ }
+
+ if hasMessagesChanges {
+
+ let adminMessageId = bleManager.saveCannedMessageModuleMessages(messages: messagesPart1, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
+
+ 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
+ hasMessagesChanges = false
+ }
- 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
- hasChanges = false
}
-
}
}
@@ -363,6 +378,12 @@ struct CannedMessagesConfig: View {
// TBeam Three Button 1.3" OLED Screen
updown1Enabled = true
rotary1Enabled = false
+ inputbrokerPinA = 25
+ inputbrokerPinB = 39
+ inputbrokerPinPress = 36
+ inputbrokerEventCw = InputEventChars.keyUp.rawValue
+ inputbrokerEventCcw = InputEventChars.keyDown.rawValue
+ inputbrokerEventPress = InputEventChars.keySelect.rawValue
}
hasChanges = true
@@ -410,6 +431,10 @@ struct CannedMessagesConfig: View {
if newKeyPress != node!.cannedMessageConfig!.inputbrokerEventPress { hasChanges = true }
}
+ .onChange(of: messagesPart1) { newMessagesChanges in
+
+ hasMessagesChanges = true
+ }
.navigationViewStyle(StackNavigationViewStyle())
}
}
diff --git a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift
index 188f6d22..492b433b 100644
--- a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift
+++ b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift
@@ -289,7 +289,7 @@ struct TelemetryConfig: View {
Label("Save", systemImage: "square.and.arrow.down")
}
- .disabled(bleManager.connectedPeripheral == nil || !hasChanges)
+ .disabled(bleManager.connectedPeripheral == nil || !hasChanges || node!.telemetryConfig == nil)
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
@@ -353,35 +353,59 @@ struct TelemetryConfig: View {
}
.onChange(of: deviceUpdateInterval) { newDeviceInterval in
- if newDeviceInterval != node!.telemetryConfig!.deviceUpdateInterval { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newDeviceInterval != node!.telemetryConfig!.deviceUpdateInterval { hasChanges = true }
+ }
}
.onChange(of: environmentUpdateInterval) { newEnvInterval in
- if newEnvInterval != node!.telemetryConfig!.environmentUpdateInterval { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newEnvInterval != node!.telemetryConfig!.environmentUpdateInterval { hasChanges = true }
+ }
}
.onChange(of: environmentMeasurementEnabled) { newEnvEnabled in
- if newEnvEnabled != node!.telemetryConfig!.environmentMeasurementEnabled { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newEnvEnabled != node!.telemetryConfig!.environmentMeasurementEnabled { hasChanges = true }
+ }
}
.onChange(of: environmentSensorType) { newEnvSensorType in
- if newEnvSensorType != node!.telemetryConfig!.environmentSensorType { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newEnvSensorType != node!.telemetryConfig!.environmentSensorType { hasChanges = true }
+ }
}
.onChange(of: environmentScreenEnabled) { newEnvScreenEnabled in
- if newEnvScreenEnabled != node!.telemetryConfig!.environmentScreenEnabled { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newEnvScreenEnabled != node!.telemetryConfig!.environmentScreenEnabled { hasChanges = true }
+ }
}
.onChange(of: environmentDisplayFahrenheit) { newEnvDisplayF in
- if newEnvDisplayF != node!.telemetryConfig!.environmentDisplayFahrenheit { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newEnvDisplayF != node!.telemetryConfig!.environmentDisplayFahrenheit { hasChanges = true }
+ }
}
.onChange(of: environmentRecoveryInterval) { newEnvRecoveryInterval in
- if newEnvRecoveryInterval != node!.telemetryConfig!.environmentRecoveryInterval { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newEnvRecoveryInterval != node!.telemetryConfig!.environmentRecoveryInterval { hasChanges = true }
+ }
}
.onChange(of: environmentReadErrorCountThreshold) { newEnvReadErrorCountThreshold in
- if newEnvReadErrorCountThreshold != node!.telemetryConfig!.environmentReadErrorCountThreshold { hasChanges = true }
+ if node!.telemetryConfig != nil {
+
+ if newEnvReadErrorCountThreshold != node!.telemetryConfig!.environmentReadErrorCountThreshold { hasChanges = true }
+ }
}
.navigationViewStyle(StackNavigationViewStyle())
}