Admin messages, improved role picker

This commit is contained in:
Garth Vander Houwen 2023-01-31 22:08:03 -08:00
parent 921f95cc63
commit 5165548e05
11 changed files with 253 additions and 99 deletions

View file

@ -14,8 +14,29 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
case clientMute = 1
case router = 2
case routerClient = 3
case repeater = 4
case tracker = 5
var id: Int { self.rawValue }
var name: String {
get {
switch self {
case .client:
return "Client"
case .clientMute:
return "Muted Client"
case .router:
return "Router"
case .routerClient:
return "Router & Client"
case .repeater:
return "Repeater"
case .tracker:
return "Tracker"
}
}
}
var description: String {
get {
switch self {
@ -28,6 +49,10 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return NSLocalizedString("device.role.router", comment: "Router - Mesh packets will prefer to be routed over this node. This node will not be used by client apps. The wifi/ble radios and the oled screen will be put to sleep.")
case .routerClient:
return NSLocalizedString("device.role.routerclient", comment: "Router Client - Mesh packets will prefer to be routed over this node. The Router Client can be used as both a Router and an app connected Client.")
case .repeater:
return "Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate."
case .tracker:
return "Position Mesh packets will be prioritized higher and sent more frequently by default."
}
}
}
@ -43,6 +68,10 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return Config.DeviceConfig.Role.router
case .routerClient:
return Config.DeviceConfig.Role.routerClient
case .repeater:
return Config.DeviceConfig.Role.repeater
case .tracker:
return Config.DeviceConfig.Role.tracker
}
}
}

View file

@ -1419,10 +1419,62 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
let messageDescription = "🛎️ Requested Bluetooth Config on admin channel \(adminIndex) for node: \(String(connectedPeripheral.num))"
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
return true
}
return false
}
public func requestDeviceConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool {
var adminPacket = AdminMessage()
adminPacket.getConfigRequest = AdminMessage.ConfigType.deviceConfig
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 = "🛎️ Requested Device Config on admin channel \(adminIndex) for node: \(String(connectedPeripheral.num))"
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
return true
}
return false
}
public func requestDisplayConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool {
var adminPacket = AdminMessage()
adminPacket.getConfigRequest = AdminMessage.ConfigType.displayConfig
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 = "🛎️ Requested Display Config on admin channel \(adminIndex) for node: \(String(connectedPeripheral.num))"
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
return true
}
return false
}
@ -1455,6 +1507,58 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
return false
}
public func requestNetworkConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool {
var adminPacket = AdminMessage()
adminPacket.getConfigRequest = AdminMessage.ConfigType.networkConfig
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 = "🛎️ Requested Network Config on admin channel \(adminIndex) for node: \(String(connectedPeripheral.num))"
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
return true
}
return false
}
public func requestPositionConfig(fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Bool {
var adminPacket = AdminMessage()
adminPacket.getConfigRequest = AdminMessage.ConfigType.positionConfig
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 = "🛎️ Requested Position Config on 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()
@ -1499,12 +1603,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
meshPacket.decoded = dataMessage
let messageDescription = "Saved WiFi Config for \(toUser.longName ?? NSLocalizedString("unknown", comment: "Unknown"))"
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
return Int64(meshPacket.id)
}
return 0
}

View file

@ -40,11 +40,11 @@ func localConfig (config: Config, context:NSManagedObjectContext, nodeNum: Int64
// We don't care about any of the Power settings, config is available for everything else
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
upsertBluetoothConfigPacket(config: config, nodeNum: nodeNum, context: context)
upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: nodeNum, context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) {
upsertDeviceConfigPacket(config: config, nodeNum: nodeNum, context: context)
upsertDeviceConfigPacket(config: config.device, nodeNum: nodeNum, context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) {
upsertDisplayConfigPacket(config: config, nodeNum: nodeNum, context: context)
upsertDisplayConfigPacket(config: config.display, nodeNum: nodeNum, context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) {
upsertLoRaConfigPacket(config: config.lora, nodeNum: nodeNum, context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) {
@ -800,26 +800,24 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
deviceMetadataPacket(metadata: adminMessage.getDeviceMetadataResponse, fromNum: Int64(packet.from), context: context)
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getConfigResponse(adminMessage.getConfigResponse) {
if let config = try? Config(serializedData: packet.decoded.payload) {
let config = adminMessage.getConfigResponse
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), context: context)
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
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) {
let lc = try? Config.LoRaConfig(serializedData: packet.decoded.payload)
upsertLoRaConfigPacket(config: lc!, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) {
upsertNetworkConfigPacket(config: config, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) {
upsertPositionConfigPacket(config: config, nodeNum: Int64(packet.from), context: context)
}
} else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) {
upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) {
upsertLoRaConfigPacket(config: config.lora, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) {
upsertNetworkConfigPacket(config: config, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) {
upsertPositionConfigPacket(config: config, nodeNum: Int64(packet.from), context: context)
}
} else {
MeshLogger.log("🕸️ MESH PACKET received for Admin App \(try! packet.decoded.jsonString())")

View file

@ -159,7 +159,7 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)
}
}
func upsertBluetoothConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) {
func upsertBluetoothConfigPacket(config: Meshtastic.Config.BluetoothConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.bluetooth.config %@", comment: "Bluetooth config received: %@"), String(nodeNum))
MeshLogger.log("📶 \(logString)")
@ -174,14 +174,14 @@ func upsertBluetoothConfigPacket(config: Config, nodeNum: Int64, context: NSMana
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)
newBluetoothConfig.enabled = config.enabled
newBluetoothConfig.mode = Int32(config.mode.rawValue)
newBluetoothConfig.fixedPin = Int32(config.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)
fetchedNode[0].bluetoothConfig?.enabled = config.enabled
fetchedNode[0].bluetoothConfig?.mode = Int32(config.mode.rawValue)
fetchedNode[0].bluetoothConfig?.fixedPin = Int32(config.fixedPin)
}
do {
try context.save()
@ -200,7 +200,7 @@ func upsertBluetoothConfigPacket(config: Config, nodeNum: Int64, context: NSMana
}
}
func upsertDeviceConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) {
func upsertDeviceConfigPacket(config: Meshtastic.Config.DeviceConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.device.config %@", comment: "Device config received: %@"), String(nodeNum))
MeshLogger.log("📟 \(logString)")
@ -214,18 +214,18 @@ func upsertDeviceConfigPacket(config: Config, nodeNum: Int64, context: NSManaged
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)
newDeviceConfig.role = Int32(config.role.rawValue)
newDeviceConfig.serialEnabled = config.serialEnabled
newDeviceConfig.debugLogEnabled = config.debugLogEnabled
newDeviceConfig.buttonGpio = Int32(config.buttonGpio)
newDeviceConfig.buzzerGpio = Int32(config.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)
fetchedNode[0].deviceConfig?.role = Int32(config.role.rawValue)
fetchedNode[0].deviceConfig?.serialEnabled = config.serialEnabled
fetchedNode[0].deviceConfig?.debugLogEnabled = config.debugLogEnabled
fetchedNode[0].deviceConfig?.buttonGpio = Int32(config.buttonGpio)
fetchedNode[0].deviceConfig?.buzzerGpio = Int32(config.buzzerGpio)
}
do {
try context.save()
@ -242,7 +242,7 @@ func upsertDeviceConfigPacket(config: Config, nodeNum: Int64, context: NSManaged
}
}
func upsertDisplayConfigPacket(config: Config, nodeNum: Int64, context: NSManagedObjectContext) {
func upsertDisplayConfigPacket(config: Meshtastic.Config.DisplayConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.display.config %@", comment: "Display config received: %@"), String(nodeNum))
MeshLogger.log("🖥️ \(logString)")
@ -260,24 +260,24 @@ func upsertDisplayConfigPacket(config: Config, nodeNum: Int64, context: NSManage
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)
newDisplayConfig.displayMode = Int32(config.display.displaymode.rawValue)
newDisplayConfig.gpsFormat = Int32(config.gpsFormat.rawValue)
newDisplayConfig.screenOnSeconds = Int32(config.screenOnSecs)
newDisplayConfig.screenCarouselInterval = Int32(config.autoScreenCarouselSecs)
newDisplayConfig.compassNorthTop = config.compassNorthTop
newDisplayConfig.flipScreen = config.flipScreen
newDisplayConfig.oledType = Int32(config.oled.rawValue)
newDisplayConfig.displayMode = Int32(config.displaymode.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)
fetchedNode[0].displayConfig?.displayMode = Int32(config.display.displaymode.rawValue)
fetchedNode[0].displayConfig?.gpsFormat = Int32(config.gpsFormat.rawValue)
fetchedNode[0].displayConfig?.screenOnSeconds = Int32(config.screenOnSecs)
fetchedNode[0].displayConfig?.screenCarouselInterval = Int32(config.autoScreenCarouselSecs)
fetchedNode[0].displayConfig?.compassNorthTop = config.compassNorthTop
fetchedNode[0].displayConfig?.flipScreen = config.flipScreen
fetchedNode[0].displayConfig?.oledType = Int32(config.oled.rawValue)
fetchedNode[0].displayConfig?.displayMode = Int32(config.displaymode.rawValue)
}
do {

View file

@ -14,7 +14,6 @@ struct BluetoothConfig: View {
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
var connectedNode: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@ -80,7 +79,7 @@ struct BluetoothConfig: View {
}
}
}
.disabled(bleManager.connectedPeripheral == nil)
.disabled(self.bleManager.connectedPeripheral == nil || node?.loRaConfig == nil)
Button {
isPresentingSaveConfirm = true
@ -97,14 +96,15 @@ struct BluetoothConfig: 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) {
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
var bc = Config.BluetoothConfig()
bc.enabled = enabled
bc.mode = BluetoothModes(rawValue: mode)?.protoEnumValue() ?? Config.BluetoothConfig.PairingMode.randomPin
bc.fixedPin = UInt32(fixedPin) ?? 123456
let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: node!.user!, toUser: node!.user!)
let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: connectedNode.user!, toUser: node!.user!)
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
@ -127,15 +127,13 @@ struct BluetoothConfig: View {
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")
}
// Need to request a BluetoothConfig from the remote node before allowing changes
if connectedNode != nil && node?.bluetoothConfig == nil {
_ = bleManager.requestBluetoothConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
if bleManager.connectedPeripheral != nil && node?.loRaConfig == nil {
print("empty bluetooth config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if connectedNode.id > 0 {
_ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
}
}
}
.onChange(of: enabled) { newEnabled in

View file

@ -35,12 +35,14 @@ struct DeviceConfig: View {
Picker("Device Role", selection: $deviceRole ) {
ForEach(DeviceRoles.allCases) { dr in
Text(dr.description)
Text(dr.name)
}
}
.pickerStyle(DefaultPickerStyle())
.padding(.top, 10)
.padding(.bottom, 10)
Text(DeviceRoles(rawValue: deviceRole)?.description ?? "")
.foregroundColor(.gray)
.font(.caption)
}
Section(header: Text("Debug")) {
@ -83,7 +85,7 @@ struct DeviceConfig: View {
}
}
.disabled(bleManager.connectedPeripheral == nil)
.disabled(self.bleManager.connectedPeripheral == nil || node?.loRaConfig == nil)
HStack {
@ -138,11 +140,9 @@ struct DeviceConfig: View {
HStack {
Button {
isPresentingSaveConfirm = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
@ -156,10 +156,10 @@ struct DeviceConfig: 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) {
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
var dc = Config.DeviceConfig()
dc.role = DeviceRoles(rawValue: deviceRole)!.protoEnumValue()
dc.serialEnabled = serialEnabled
@ -167,7 +167,7 @@ struct DeviceConfig: View {
dc.buttonGpio = UInt32(buttonGPIO)
dc.buzzerGpio = UInt32(buzzerGPIO)
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: node!.user!, toUser: node!.user!)
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: connectedNode.user!, toUser: node!.user!)
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
@ -195,6 +195,15 @@ struct DeviceConfig: View {
self.buttonGPIO = Int(node?.deviceConfig?.buttonGpio ?? 0)
self.buzzerGPIO = Int(node?.deviceConfig?.buzzerGpio ?? 0)
self.hasChanges = false
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.deviceConfig == nil {
print("empty device config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if connectedNode.id > 0 {
_ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
}
}
}
.onChange(of: deviceRole) { newRole in

View file

@ -97,7 +97,7 @@ struct DisplayConfig: View {
.listRowSeparator(.visible)
}
}
.disabled(bleManager.connectedPeripheral == nil)
.disabled(self.bleManager.connectedPeripheral == nil || node?.loRaConfig == nil)
Button {
@ -116,9 +116,10 @@ struct DisplayConfig: View {
"are.you.sure",
isPresented: $isPresentingSaveConfirm
) {
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) {
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
var dc = Config.DisplayConfig()
dc.gpsFormat = GpsFormats(rawValue: gpsFormat)!.protoEnumValue()
dc.screenOnSecs = UInt32(screenOnSeconds)
@ -128,7 +129,7 @@ struct DisplayConfig: View {
dc.oled = OledTypes(rawValue: oledType)!.protoEnumValue()
dc.displaymode = DisplayModes(rawValue: displayMode)!.protoEnumValue()
let adminMessageId = bleManager.saveDisplayConfig(config: dc, fromUser: node!.user!, toUser: node!.user!)
let adminMessageId = bleManager.saveDisplayConfig(config: dc, fromUser: connectedNode.user!, toUser: node!.user!)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
@ -156,6 +157,15 @@ struct DisplayConfig: View {
self.oledType = Int(node?.displayConfig?.oledType ?? 0)
self.displayMode = Int(node?.displayConfig?.displayMode ?? 0)
self.hasChanges = false
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.displayConfig == nil {
print("empty display config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if connectedNode.id > 0 {
_ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
}
}
}
.onChange(of: screenOnSeconds) { newScreenSecs in
if node != nil && node!.displayConfig != nil {

View file

@ -61,7 +61,7 @@ struct LoRaConfig: View {
.font(.caption)
}
}
.disabled(self.bleManager.connectedPeripheral == nil)
.disabled(self.bleManager.connectedPeripheral == nil || node?.loRaConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {

View file

@ -25,7 +25,6 @@ struct NetworkConfig: View {
@State var ethEnabled = false
@State var ethMode = 0
var body: some View {
VStack {
@ -108,9 +107,10 @@ struct NetworkConfig: 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) {
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
var network = Config.NetworkConfig()
network.wifiEnabled = self.wifiEnabled
network.wifiSsid = self.wifiSsid
@ -118,7 +118,7 @@ struct NetworkConfig: View {
network.ethEnabled = self.ethEnabled
//network.addressMode = Config.NetworkConfig.AddressMode.dhcp
let adminMessageId = bleManager.saveNetworkConfig(config: network, fromUser: node!.user!, toUser: node!.user!)
let adminMessageId = bleManager.saveNetworkConfig(config: network, fromUser: connectedNode.user!, toUser: node!.user!)
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
@ -143,6 +143,15 @@ struct NetworkConfig: View {
self.wifiMode = Int(node?.networkConfig?.wifiMode ?? 0)
self.ethEnabled = node?.networkConfig?.ethEnabled ?? false
self.hasChanges = false
// Need to request a NetworkConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.positionConfig == nil {
print("empty network config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if connectedNode.id > 0 {
_ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
}
}
}
.onChange(of: wifiEnabled) { newEnabled in
if node != nil && node!.networkConfig != nil {

View file

@ -185,14 +185,11 @@ struct PositionConfig: View {
}
}
}
.disabled(bleManager.connectedPeripheral == nil)
.disabled(self.bleManager.connectedPeripheral == nil || node?.loRaConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
@ -205,14 +202,14 @@ struct PositionConfig: 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) {
if fixedPosition {
_ = bleManager.sendPosition(destNum: bleManager.connectedPeripheral.num, wantResponse: false)
}
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
var pc = Config.PositionConfig()
pc.positionBroadcastSmartEnabled = smartPositionEnabled
pc.gpsEnabled = deviceGpsEnabled
@ -232,7 +229,7 @@ struct PositionConfig: View {
if includeSpeed { pf.insert(.Speed) }
if includeHeading { pf.insert(.Heading) }
pc.positionFlags = UInt32(pf.rawValue)
let adminMessageId = bleManager.savePositionConfig(config: pc, fromUser: node!.user!, toUser: node!.user!)
let adminMessageId = bleManager.savePositionConfig(config: pc, fromUser: connectedNode.user!, toUser: node!.user!)
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
@ -278,6 +275,14 @@ struct PositionConfig: View {
self.hasChanges = false
// Need to request a PositionConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.positionConfig == nil {
print("empty position config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if connectedNode.id > 0 {
_ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
}
}
}
.onChange(of: deviceGpsEnabled) { newDeviceGps in
if node != nil && node!.positionConfig != nil {

View file

@ -135,14 +135,13 @@ struct Settings: View {
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
NavigationLink() {
BluetoothConfig(node: nodes.first(where: { $0.num == selectedNode }), connectedNode: nodes.first(where: { $0.num == connectedNodeNum }))
BluetoothConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
Image(systemName: "antenna.radiowaves.left.and.right")
.symbolRenderingMode(.hierarchical)
Text("bluetooth")
}
.tag(SettingsSidebar.bluetoothConfig)
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
NavigationLink {
DeviceConfig(node: nodes.first(where: { $0.num == selectedNode }))
@ -152,7 +151,6 @@ struct Settings: View {
Text("device")
}
.tag(SettingsSidebar.deviceConfig)
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
NavigationLink {
DisplayConfig(node: nodes.first(where: { $0.num == selectedNode }))
@ -162,7 +160,6 @@ struct Settings: View {
Text("display")
}
.tag(SettingsSidebar.displayConfig)
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
NavigationLink {
NetworkConfig(node: nodes.first(where: { $0.num == selectedNode }))
@ -173,7 +170,6 @@ struct Settings: View {
Text("network")
}
.tag(SettingsSidebar.networkConfig)
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
NavigationLink {
PositionConfig(node: nodes.first(where: { $0.num == selectedNode }))
@ -184,7 +180,6 @@ struct Settings: View {
Text("position")
}
.tag(SettingsSidebar.positionConfig)
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
}
Section("module.configuration") {