Canned Message

This commit is contained in:
Garth Vander Houwen 2022-07-02 11:28:25 -07:00
parent b0c3ff10ab
commit bdc36610e6
5 changed files with 320 additions and 15 deletions

View file

@ -331,6 +331,107 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) {
// We don't care about any of the WiFi related MQTT settings
if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.cannedMessage(config.cannedMessage) {
var isDefault = false
if (try! config.serial.jsonString()) == "{}" {
isDefault = true
print("🥫 Default Canned Message Module config")
}
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]
// Found a node, save Device Config
if !fetchedNode.isEmpty {
if fetchedNode[0].cannedMessageConfig == nil {
let newCannedMessageConfig = CannedMessageConfigEntity(context: context)
if isDefault {
newCannedMessageConfig.enabled = false
newCannedMessageConfig.sendBell = false
newCannedMessageConfig.rotary1Enabled = false
newCannedMessageConfig.updown1Enabled = false
newCannedMessageConfig.inputbrokerPinA = 0
newCannedMessageConfig.inputbrokerPinB = 0
newCannedMessageConfig.inputbrokerPinPress = 0
newCannedMessageConfig.inputbrokerEventCw = 0
newCannedMessageConfig.inputbrokerEventCcw = 0
newCannedMessageConfig.inputbrokerEventPress = 0
} else {
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 {
if isDefault {
fetchedNode[0].cannedMessageConfig?.enabled = false
fetchedNode[0].cannedMessageConfig?.sendBell = false
fetchedNode[0].cannedMessageConfig?.rotary1Enabled = false
fetchedNode[0].cannedMessageConfig?.updown1Enabled = false
fetchedNode[0].cannedMessageConfig?.inputbrokerPinA = 0
fetchedNode[0].cannedMessageConfig?.inputbrokerPinB = 0
fetchedNode[0].cannedMessageConfig?.inputbrokerPinPress = 0
fetchedNode[0].cannedMessageConfig?.inputbrokerEventCw = 0
fetchedNode[0].cannedMessageConfig?.inputbrokerEventCcw = 0
fetchedNode[0].cannedMessageConfig?.inputbrokerEventPress = 0
} 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()
if meshlogging { MeshLogger.log("💾 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)")
}
}
} catch {
}
}
if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.rangeTest(config.rangeTest) {
var isDefault = false
@ -403,6 +504,95 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
}
}
if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.serial(config.serial) {
var isDefault = false
if (try! config.serial.jsonString()) == "{}" {
isDefault = true
print("🤖 Default Serial Module config")
}
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]
// Found a node, save Device Config
if !fetchedNode.isEmpty {
if fetchedNode[0].serialConfig == nil {
let newSerialConfig = SerialConfigEntity(context: context)
if isDefault {
newSerialConfig.enabled = false
newSerialConfig.echo = false
newSerialConfig.rxd = 0
newSerialConfig.txd = 0
newSerialConfig.baudRate = 0
newSerialConfig.timeout = 0
newSerialConfig.mode = 0
} else {
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 {
if isDefault {
fetchedNode[0].serialConfig?.enabled = false
fetchedNode[0].serialConfig?.echo = false
fetchedNode[0].serialConfig?.rxd = 0
fetchedNode[0].serialConfig?.txd = 0
fetchedNode[0].serialConfig?.baudRate = 0
fetchedNode[0].serialConfig?.timeout = 0
fetchedNode[0].serialConfig?.mode = 0
} 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()
if meshlogging { MeshLogger.log("💾 Updated Serial Module Config for node number: \(String(nodeNum))") }
} catch {
context.rollback()
let nsError = error as NSError
print("💥 Error Updating Core Data SerialConfigEntity: \(nsError)")
}
}
} catch {
}
}
}
func myInfoPacket (myInfo: MyNodeInfo, meshLogging: Bool, context: NSManagedObjectContext) -> MyInfoEntity? {

View file

@ -1,7 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21F79" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="CannedMessageConfig" representedClassName="CannedMessageConfig" syncable="YES" codeGenerationType="class">
<entity name="CannedMessageConfigEntity" representedClassName="CannedMessageConfigEntity" syncable="YES" codeGenerationType="class">
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="inputbrokerEventCcw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="inputbrokerEventCw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="inputbrokerEventPress" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="inputbrokerPinA" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="inputbrokerPinB" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
<attribute name="inputbrokerPinPress" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
@ -9,7 +12,7 @@
<attribute name="rotary1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="sendBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="updown1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<relationship name="cannedMessagesConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="cannedMessagesConfig" inverseEntity="NodeInfoEntity"/>
<relationship name="cannedMessagesConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="cannedMessageConfig" inverseEntity="NodeInfoEntity"/>
</entity>
<entity name="DeviceConfigEntity" representedClassName="DeviceConfigEntity" syncable="YES" codeGenerationType="class">
<attribute name="debugLogEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
@ -79,7 +82,7 @@
<attribute name="lastHeard" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<relationship name="cannedMessagesConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CannedMessageConfig" inverseName="cannedMessagesConfigNode" inverseEntity="CannedMessageConfig"/>
<relationship name="cannedMessageConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CannedMessageConfigEntity" inverseName="cannedMessagesConfigNode" inverseEntity="CannedMessageConfigEntity"/>
<relationship name="deviceConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DeviceConfigEntity" inverseName="deviceConfigNode" inverseEntity="DeviceConfigEntity"/>
<relationship name="displayConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DisplayConfigEntity" inverseName="displayConfigNode" inverseEntity="DisplayConfigEntity"/>
<relationship name="loRaConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="LoRaConfigEntity" inverseName="loRaConfigNode" inverseEntity="LoRaConfigEntity"/>
@ -87,6 +90,7 @@
<relationship name="positionConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PositionConfigEntity" inverseName="positionConfigNode" inverseEntity="PositionConfigEntity"/>
<relationship name="positions" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PositionEntity" inverseName="nodePosition" inverseEntity="PositionEntity"/>
<relationship name="rangeTestConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RangeTestConfigEntity" inverseName="rangeTestConfigNode" inverseEntity="RangeTestConfigEntity"/>
<relationship name="serialConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SerialConfigEntity" inverseName="serialConfigNode" inverseEntity="SerialConfigEntity"/>
<relationship name="telemetries" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="TelemetryEntity" inverseName="nodeTelemetry" inverseEntity="TelemetryEntity"/>
<relationship name="user" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="userNode" inverseEntity="UserEntity"/>
<uniquenessConstraints>
@ -120,6 +124,17 @@
<attribute name="sender" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
<relationship name="rangeTestConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="rangeTestConfig" inverseEntity="NodeInfoEntity"/>
</entity>
<entity name="SerialConfigEntity" representedClassName="SerialConfigEntity" syncable="YES" codeGenerationType="class">
<attribute name="baudRate" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="echo" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="rxd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="timeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="txd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="serialConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="serialConfig" inverseEntity="NodeInfoEntity"/>
</entity>
<entity name="TelemetryEntity" representedClassName="TelemetryEntity" syncable="YES" codeGenerationType="class">
<attribute name="airUtilTx" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="barometricPressure" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
@ -149,17 +164,18 @@
</fetchedProperty>
</entity>
<elements>
<element name="CannedMessageConfig" positionX="45" positionY="144" width="128" height="164"/>
<element name="CannedMessageConfigEntity" positionX="45" positionY="144" width="128" height="209"/>
<element name="DeviceConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
<element name="DisplayConfigEntity" positionX="54" positionY="153" width="128" height="104"/>
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
<element name="MessageEntity" positionX="-36" positionY="63" width="128" height="230"/>
<element name="MyInfoEntity" positionX="-18" positionY="81" width="128" height="209"/>
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="254"/>
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="269"/>
<element name="PositionConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
<element name="PositionEntity" positionX="-54" positionY="54" width="128" height="119"/>
<element name="RangeTestConfigEntity" positionX="72" positionY="171" width="128" height="104"/>
<element name="TelemetryEntity" positionX="160" positionY="192" width="128" height="194"/>
<element name="UserEntity" positionX="0" positionY="144" width="128" height="200"/>
<element name="SerialConfigEntity" positionX="54" positionY="153" width="128" height="164"/>
</elements>
</model>

View file

@ -307,12 +307,12 @@ struct CannedMessagesConfig: View {
if self.initialLoad{
self.bleManager.context = context
self.enabled = node.cannedMessagesConfig?.enabled ?? false
self.rotary1Enabled = node.cannedMessagesConfig?.rotary1Enabled ?? false
self.updown1Enabled = node.cannedMessagesConfig?.updown1Enabled ?? false
self.inputbrokerPinA = Int(node.cannedMessagesConfig?.inputbrokerPinA ?? 0)
self.inputbrokerPinB = Int(node.cannedMessagesConfig?.inputbrokerPinB ?? 0)
self.inputbrokerPinPress = Int(node.cannedMessagesConfig?.inputbrokerPinPress ?? 0)
self.enabled = node.cannedMessageConfig?.enabled ?? false
self.rotary1Enabled = node.cannedMessageConfig?.rotary1Enabled ?? false
self.updown1Enabled = node.cannedMessageConfig?.updown1Enabled ?? false
self.inputbrokerPinA = Int(node.cannedMessageConfig?.inputbrokerPinA ?? 0)
self.inputbrokerPinB = Int(node.cannedMessageConfig?.inputbrokerPinB ?? 0)
self.inputbrokerPinPress = Int(node.cannedMessageConfig?.inputbrokerPinPress ?? 0)
self.hasChanges = false
self.initialLoad = false
}

View file

@ -65,6 +65,45 @@ enum SerialBaudRates: Int, CaseIterable, Identifiable {
}
}
}
func protoEnumValue() -> ModuleConfig.SerialConfig.Serial_Baud {
switch self {
case .baudDefault:
return ModuleConfig.SerialConfig.Serial_Baud.baudDefault
case .baud110:
return ModuleConfig.SerialConfig.Serial_Baud.baud110
case .baud300:
return ModuleConfig.SerialConfig.Serial_Baud.baud300
case .baud600:
return ModuleConfig.SerialConfig.Serial_Baud.baud600
case .baud1200:
return ModuleConfig.SerialConfig.Serial_Baud.baud1200
case .baud2400:
return ModuleConfig.SerialConfig.Serial_Baud.baud2400
case .baud4800:
return ModuleConfig.SerialConfig.Serial_Baud.baud4800
case .baud9600:
return ModuleConfig.SerialConfig.Serial_Baud.baud9600
case .baud19200:
return ModuleConfig.SerialConfig.Serial_Baud.baud19200
case .baud38400:
return ModuleConfig.SerialConfig.Serial_Baud.baud38400
case .baud57600:
return ModuleConfig.SerialConfig.Serial_Baud.baud57600
case .baud115200:
return ModuleConfig.SerialConfig.Serial_Baud.baud115200
case .baud230400:
return ModuleConfig.SerialConfig.Serial_Baud.baud230400
case .baud460800:
return ModuleConfig.SerialConfig.Serial_Baud.baud460800
case .baud576000:
return ModuleConfig.SerialConfig.Serial_Baud.baud576000
case .baud921600:
return ModuleConfig.SerialConfig.Serial_Baud.baud921600
}
}
}
enum SerialModeTypes: Int, CaseIterable, Identifiable {
@ -86,6 +125,18 @@ enum SerialModeTypes: Int, CaseIterable, Identifiable {
}
}
}
func protoEnumValue() -> ModuleConfig.SerialConfig.Serial_Mode {
switch self {
case .modeDefault:
return ModuleConfig.SerialConfig.Serial_Mode.modeDefault
case .modeSimple:
return ModuleConfig.SerialConfig.Serial_Mode.modeSimple
case .modeProto:
return ModuleConfig.SerialConfig.Serial_Mode.modeProto
}
}
}
enum SerialTimeoutIntervals: Int, CaseIterable, Identifiable {
@ -127,6 +178,8 @@ struct SerialConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
var node: NodeInfoEntity
@State private var isPresentingSaveConfirm: Bool = false
@State var initialLoad: Bool = true
@State var hasChanges = false
@ -242,8 +295,12 @@ struct SerialConfig: View {
var sc = ModuleConfig.SerialConfig()
sc.enabled = enabled
//sc.save = save
//sc.sender = sender ? 1 : 0
sc.echo = echo
sc.rxd = UInt32(rxd)
sc.txd = UInt32(txd)
sc.baud = SerialBaudRates(rawValue: baudRate)!.protoEnumValue()
sc.timeout = UInt32(timeout)
sc.mode = SerialModeTypes(rawValue: mode)!.protoEnumValue()
if bleManager.saveSerialModuleConfig(config: sc, destNum: bleManager.connectedPeripheral.num, wantResponse: false) {
@ -266,7 +323,49 @@ struct SerialConfig: View {
})
.onAppear {
self.bleManager.context = context
if self.initialLoad{
self.bleManager.context = context
self.enabled = node.serialConfig?.enabled ?? false
self.echo = node.serialConfig?.echo ?? false
self.rxd = Int(node.serialConfig?.rxd ?? 0)
self.txd = Int(node.serialConfig?.txd ?? 0)
self.baudRate = Int(node.serialConfig?.baudRate ?? 0)
self.timeout = Int(node.serialConfig?.timeout ?? 0)
self.mode = Int(node.serialConfig?.mode ?? 0)
self.hasChanges = false
self.initialLoad = false
}
}
.onChange(of: enabled) { newEnabled in
if newEnabled != node.serialConfig!.enabled { hasChanges = true }
}
.onChange(of: echo) { newEcho in
if newEcho != node.serialConfig!.echo { hasChanges = true }
}
.onChange(of: rxd) { newRxd in
if newRxd != node.serialConfig!.rxd { hasChanges = true }
}
.onChange(of: txd) { newTxd in
if newTxd != node.serialConfig!.txd { hasChanges = true }
}
.onChange(of: baudRate) { newBaud in
if newBaud != node.serialConfig!.baudRate { hasChanges = true }
}
.onChange(of: timeout) { newTimeout in
if newTimeout != node.serialConfig!.timeout { hasChanges = true }
}
.onChange(of: mode) { newMode in
if newMode != node.serialConfig!.mode { hasChanges = true }
}
.navigationViewStyle(StackNavigationViewStyle())
}

View file

@ -151,7 +151,7 @@ struct Settings: View {
// nodes.first(where: { $0.num == connectedNodeNum })!.rangeTestConfig != nil)
NavigationLink {
SerialConfig()
SerialConfig(node: nodes.first(where: { $0.num == connectedNodeNum }) ?? NodeInfoEntity())
} label: {
Image(systemName: "terminal")