mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Admin messages updates
This commit is contained in:
parent
79bc59adc9
commit
338cfa946f
6 changed files with 115 additions and 66 deletions
|
|
@ -1188,17 +1188,19 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveLoRaConfig(config: Config.LoRaConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
public func saveLoRaConfig(config: Config.LoRaConfig, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.lora = config
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedPeripheral.num)
|
||||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.to = UInt32(toUser.num)
|
||||
meshPacket.from = UInt32(fromUser.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
if adminIndex > 0 {
|
||||
meshPacket.channel = UInt32(adminIndex)
|
||||
}
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
|
|
@ -1392,6 +1394,35 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
|
|||
return false
|
||||
}
|
||||
|
||||
public func getLoRaConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.getConfigRequest = AdminMessage.ConfigType.loraConfig
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(toUser.num)
|
||||
meshPacket.from = UInt32(fromUser.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.channel = UInt32(adminIndex)
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
dataMessage.wantResponse = true
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
let messageDescription = "🛎️ Sent a Get LoRa Config request on the admin channel \(adminIndex) for node: \(String(connectedPeripheral.num))"
|
||||
|
||||
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public func saveExternalNotificationModuleConfig(config: ModuleConfig.ExternalNotificationConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
|
|
|
|||
|
|
@ -184,59 +184,7 @@ func localConfig (config: Config, context:NSManagedObjectContext, nodeNum: Int64
|
|||
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) {
|
||||
|
||||
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", Int64(nodeNum))
|
||||
|
||||
do {
|
||||
|
||||
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
|
||||
// Found a node, save LoRa Config
|
||||
if !fetchedNode.isEmpty {
|
||||
if fetchedNode[0].loRaConfig == nil {
|
||||
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)")
|
||||
}
|
||||
upsertLoraConfigPacket(config: config, nodeNum: nodeNum, context: context)
|
||||
}
|
||||
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) {
|
||||
|
|
@ -911,7 +859,6 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
|
|||
fetchedNode[0].snr = nodeInfo.snr
|
||||
fetchedNode[0].channel = Int32(channel)
|
||||
|
||||
|
||||
if nodeInfo.hasUser {
|
||||
|
||||
fetchedNode[0].user!.userId = nodeInfo.user.id
|
||||
|
|
@ -1074,10 +1021,14 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
|
|||
channelPacket(channel: adminMessage.getChannelResponse, fromNum: Int64(packet.from), context: context)
|
||||
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getDeviceMetadataResponse(adminMessage.getDeviceMetadataResponse) {
|
||||
deviceMetadataPacket(metadata: adminMessage.getDeviceMetadataResponse, fromNum: Int64(packet.from), context: context)
|
||||
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getConfigResponse(adminMessage.getConfigResponse) {
|
||||
|
||||
print(try! adminMessage.getDeviceMetadataResponse.jsonString())
|
||||
|
||||
|
||||
if let config = try? Config(serializedData: packet.decoded.payload) {
|
||||
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) {
|
||||
upsertLoraConfigPacket(config: config, nodeNum: Int64(packet.from), context: context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,3 +100,61 @@ public func clearCoreDataDatabase(context: NSManagedObjectContext) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)")
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", nodeNum)
|
||||
|
||||
do {
|
||||
|
||||
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
|
||||
// Found a node, save LoRa Config
|
||||
if !fetchedNode.isEmpty {
|
||||
if fetchedNode[0].loRaConfig == nil {
|
||||
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()
|
||||
context.refreshAllObjects()
|
||||
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)")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ struct Connect: View {
|
|||
if isUnsetRegion {
|
||||
HStack {
|
||||
NavigationLink {
|
||||
LoRaConfig(node: node)
|
||||
LoRaConfig(node: node, connectedNode: node)
|
||||
} label: {
|
||||
Label("set.region", systemImage: "globe.americas.fill")
|
||||
.foregroundColor(.red)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ struct LoRaConfig: View {
|
|||
@Environment(\.dismiss) private var goBack
|
||||
|
||||
var node: NodeInfoEntity?
|
||||
var connectedNode: NodeInfoEntity?
|
||||
|
||||
@State var isPresentingSaveConfirm = false
|
||||
@State var hasChanges = false
|
||||
|
|
@ -75,7 +76,7 @@ struct LoRaConfig: 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) {
|
||||
var lc = Config.LoRaConfig()
|
||||
|
|
@ -84,7 +85,7 @@ struct LoRaConfig: View {
|
|||
lc.modemPreset = ModemPresets(rawValue: modemPreset)!.protoEnumValue()
|
||||
lc.usePreset = true
|
||||
lc.txEnabled = true
|
||||
let adminMessageId = bleManager.saveLoRaConfig(config: lc, fromUser: node!.user!, toUser: node!.user!)
|
||||
let adminMessageId = bleManager.saveLoRaConfig(config: lc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0)
|
||||
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
|
||||
|
|
@ -102,14 +103,22 @@ struct LoRaConfig: View {
|
|||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
self.bleManager.context = context
|
||||
self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 0)
|
||||
self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 3)
|
||||
self.region = Int(node?.loRaConfig?.regionCode ?? 0)
|
||||
self.usePreset = node?.loRaConfig?.usePreset ?? true
|
||||
self.modemPreset = Int(node?.loRaConfig?.modemPreset ?? 0)
|
||||
self.txEnabled = node?.loRaConfig?.txEnabled ?? true
|
||||
self.txPower = Int(node?.loRaConfig?.txPower ?? 0)
|
||||
self.hasChanges = false
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
.onChange(of: region) { newRegion in
|
||||
if node != nil && node!.loRaConfig != nil {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ struct Settings: View {
|
|||
.disabled(selectedNode == 0)
|
||||
|
||||
NavigationLink() {
|
||||
LoRaConfig(node: nodes.first(where: { $0.num == selectedNode }))
|
||||
LoRaConfig(node: nodes.first(where: { $0.num == selectedNode }), connectedNode: nodes.first(where: { $0.num == connectedNodeNum }))
|
||||
} label: {
|
||||
Image(systemName: "dot.radiowaves.left.and.right")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue