mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #914 from meshtastic/2.5-admin-updates
2.5 Administration with session passkey
This commit is contained in:
commit
2788caea2b
32 changed files with 413 additions and 224 deletions
|
|
@ -109,7 +109,7 @@
|
|||
"%@ Channels?" : {
|
||||
|
||||
},
|
||||
"%@ config data was requested over the admin channel but no response has been returned from the remote node. You can check the status of admin message requests in the admin message log." : {
|
||||
"%@ config data was requested over the admin channel but no response has been returned from the remote node." : {
|
||||
|
||||
},
|
||||
"%@ dB" : {
|
||||
|
|
@ -1865,9 +1865,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Bluetooth Logs" : {
|
||||
|
||||
},
|
||||
"bluetooth.config" : {
|
||||
"localizations" : {
|
||||
|
|
@ -4584,9 +4581,6 @@
|
|||
},
|
||||
"Configure" : {
|
||||
|
||||
},
|
||||
"Configuring Node" : {
|
||||
|
||||
},
|
||||
"Connect to a Node" : {
|
||||
|
||||
|
|
@ -5070,6 +5064,9 @@
|
|||
},
|
||||
"Debug Log" : {
|
||||
|
||||
},
|
||||
"Debug Logs" : {
|
||||
|
||||
},
|
||||
"Debug Logs%@" : {
|
||||
|
||||
|
|
@ -5361,9 +5358,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Developer" : {
|
||||
|
||||
},
|
||||
"Developers" : {
|
||||
|
||||
|
|
@ -5429,10 +5423,7 @@
|
|||
"Device GPS" : {
|
||||
|
||||
},
|
||||
"Device is managed by a mesh administrator." : {
|
||||
|
||||
},
|
||||
"Device Logging Enabled" : {
|
||||
"Device is managed by a mesh administrator, the user is unable to access any of the device settings." : {
|
||||
|
||||
},
|
||||
"Device Metrics" : {
|
||||
|
|
@ -6929,9 +6920,6 @@
|
|||
},
|
||||
"Enabling Ethernet will disable the bluetooth connection to the app." : {
|
||||
|
||||
},
|
||||
"Enabling Managed mode will restrict access to all radio configurations, such as short/long names, regions, channels, modules, etc. and will only be accessible through the Admin channel. To avoid being locked out, make sure the Admin channel is working properly before enabling it." : {
|
||||
|
||||
},
|
||||
"Enabling WiFi will disable the bluetooth connection to the app." : {
|
||||
|
||||
|
|
@ -16076,7 +16064,7 @@
|
|||
"Other data sources" : {
|
||||
|
||||
},
|
||||
"Output live debug logging over serial." : {
|
||||
"Output live debug logging over serial, view and export position-redacted device logs over Bluetooth." : {
|
||||
|
||||
},
|
||||
"Output pin buzzer GPIO " : {
|
||||
|
|
@ -19276,9 +19264,6 @@
|
|||
},
|
||||
"Serial Console over the Stream API." : {
|
||||
|
||||
},
|
||||
"Serial Debug Logs" : {
|
||||
|
||||
},
|
||||
"serial.config" : {
|
||||
"localizations" : {
|
||||
|
|
@ -22511,12 +22496,6 @@
|
|||
},
|
||||
"Via Mqtt" : {
|
||||
|
||||
},
|
||||
"View and export position-redacted device logs over Bluetooth" : {
|
||||
|
||||
},
|
||||
"View Logs" : {
|
||||
|
||||
},
|
||||
"voltage" : {
|
||||
"localizations" : {
|
||||
|
|
|
|||
|
|
@ -719,8 +719,8 @@
|
|||
DD41582528582E9B009B0E59 /* DeviceConfig.swift */,
|
||||
DD8EBF42285058FA00426DCA /* DisplayConfig.swift */,
|
||||
DD2553562855B02500E55709 /* LoRaConfig.swift */,
|
||||
DD2553582855B52700E55709 /* PositionConfig.swift */,
|
||||
DD8ED9C42898D51F00B3B0AB /* NetworkConfig.swift */,
|
||||
DD2553582855B52700E55709 /* PositionConfig.swift */,
|
||||
D93068DA2B81C85E0066FBC8 /* PowerConfig.swift */,
|
||||
DD1BD0F22C63C65E008C0C70 /* SecurityConfig.swift */,
|
||||
DD61937B2863877A00E59241 /* Module */,
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ enum RoutingError: Int, CaseIterable, Identifiable {
|
|||
case .notAuthorized:
|
||||
return true
|
||||
case .pkiFailed:
|
||||
return false
|
||||
return true
|
||||
case .pkiUnknownPubkey:
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
import SwiftUI
|
||||
|
||||
public extension View {
|
||||
func onFirstAppear(_ action: @escaping () -> ()) -> some View {
|
||||
func onFirstAppear(_ action: @escaping () -> Void) -> some View {
|
||||
modifier(FirstAppear(action: action))
|
||||
}
|
||||
}
|
||||
|
||||
private struct FirstAppear: ViewModifier {
|
||||
let action: () -> ()
|
||||
let action: () -> Void
|
||||
|
||||
// Use this to only fire your block one time
|
||||
@State private var hasAppeared = false
|
||||
|
|
|
|||
|
|
@ -2564,6 +2564,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.getConfigRequest = AdminMessage.ConfigType.bluetoothConfig
|
||||
if UserDefaults.enableAdministration {
|
||||
adminPacket.sessionPasskey = toUser.userNode?.sessionPasskey ?? Data()
|
||||
}
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(toUser.num)
|
||||
meshPacket.from = UInt32(fromUser.num)
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ func generateMessageMarkdown (message: String) -> String {
|
|||
|
||||
func localConfig (config: Config, context: NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) {
|
||||
|
||||
let remote = nodeNum != UserDefaults.preferredPeripheralNum
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
|
||||
upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: nodeNum, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) {
|
||||
|
|
@ -365,7 +366,7 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
|
|||
fetchedNode[0].user = UserEntity(context: context)
|
||||
}
|
||||
// Set the public key for a user if it is empty, don't update
|
||||
if fetchedNode[0].user?.publicKey?.isEmpty == nil && !nodeInfo.user.publicKey.isEmpty {
|
||||
if fetchedNode[0].user?.publicKey == nil && !nodeInfo.user.publicKey.isEmpty {
|
||||
fetchedNode[0].user?.pkiEncrypted = true
|
||||
fetchedNode[0].user?.publicKey = nodeInfo.user.publicKey
|
||||
}
|
||||
|
|
@ -496,19 +497,19 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
|
|||
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getConfigResponse(adminMessage.getConfigResponse) {
|
||||
let config = adminMessage.getConfigResponse
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
|
||||
upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), context: context)
|
||||
upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) {
|
||||
upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), context: context)
|
||||
upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) {
|
||||
upsertDisplayConfigPacket(config: config.display, nodeNum: Int64(packet.from), context: context)
|
||||
upsertDisplayConfigPacket(config: config.display, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) {
|
||||
upsertLoRaConfigPacket(config: config.lora, nodeNum: Int64(packet.from), context: context)
|
||||
upsertLoRaConfigPacket(config: config.lora, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) {
|
||||
upsertNetworkConfigPacket(config: config.network, nodeNum: Int64(packet.from), context: context)
|
||||
upsertNetworkConfigPacket(config: config.network, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) {
|
||||
upsertPositionConfigPacket(config: config.position, nodeNum: Int64(packet.from), context: context)
|
||||
upsertPositionConfigPacket(config: config.position, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.power(config.power) {
|
||||
upsertPowerConfigPacket(config: config.power, nodeNum: Int64(packet.from), context: context)
|
||||
upsertPowerConfigPacket(config: config.power, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
} else if config.payloadVariant == Config.OneOf_PayloadVariant.security(config.security) {
|
||||
upsertSecurityConfigPacket(config: config.security, nodeNum: Int64(packet.from), sessionPasskey: adminMessage.sessionPasskey, context: context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,6 +209,8 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext)
|
|||
} else {
|
||||
if packet.from > Constants.minimumNodeNum {
|
||||
let newUser = createUser(num: Int64(packet.from), context: context)
|
||||
newNode.user?.pkiEncrypted = packet.pkiEncrypted
|
||||
newNode.user?.publicKey = packet.publicKey
|
||||
newNode.user = newUser
|
||||
}
|
||||
}
|
||||
|
|
@ -269,6 +271,11 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext)
|
|||
fetchedNode[0].user!.role = Int32(nodeInfoMessage.user.role.rawValue)
|
||||
fetchedNode[0].user!.hwModel = String(describing: nodeInfoMessage.user.hwModel).uppercased()
|
||||
fetchedNode[0].user!.hwModelId = Int32(nodeInfoMessage.user.hwModel.rawValue)
|
||||
|
||||
if !packet.publicKey.isEmpty {
|
||||
fetchedNode[0].user!.pkiEncrypted = packet.pkiEncrypted
|
||||
fetchedNode[0].user!.publicKey = packet.publicKey
|
||||
}
|
||||
Task {
|
||||
Api().loadDeviceHardwareData { (hw) in
|
||||
let dh = hw.first(where: { $0.hwModel == fetchedNode[0].user?.hwModelId ?? 0 })
|
||||
|
|
@ -409,13 +416,11 @@ func upsertBluetoothConfigPacket(config: Config.BluetoothConfig, nodeNum: Int64,
|
|||
newBluetoothConfig.enabled = config.enabled
|
||||
newBluetoothConfig.mode = Int32(config.mode.rawValue)
|
||||
newBluetoothConfig.fixedPin = Int32(config.fixedPin)
|
||||
newBluetoothConfig.deviceLoggingEnabled = config.deviceLoggingEnabled
|
||||
fetchedNode[0].bluetoothConfig = newBluetoothConfig
|
||||
} else {
|
||||
fetchedNode[0].bluetoothConfig?.enabled = config.enabled
|
||||
fetchedNode[0].bluetoothConfig?.mode = Int32(config.mode.rawValue)
|
||||
fetchedNode[0].bluetoothConfig?.fixedPin = Int32(config.fixedPin)
|
||||
fetchedNode[0].bluetoothConfig?.deviceLoggingEnabled = config.deviceLoggingEnabled
|
||||
}
|
||||
if sessionPasskey != nil {
|
||||
fetchedNode[0].sessionPasskey = sessionPasskey
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ struct UserList: View {
|
|||
NSSortDescriptor(key: "userNode.favorite", ascending: false),
|
||||
NSSortDescriptor(key: "pkiEncrypted", ascending: false),
|
||||
NSSortDescriptor(key: "longName", ascending: true)],
|
||||
predicate: NSPredicate(format: "hwModelId != nil"),
|
||||
animation: .default
|
||||
)
|
||||
private var users: FetchedResults<UserEntity>
|
||||
|
|
|
|||
|
|
@ -30,8 +30,22 @@ struct NodeListItem: View {
|
|||
}
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
if node.user?.pkiEncrypted ?? false {
|
||||
if !(node.user?.keyMatch ?? false) {
|
||||
/// Public Key on the User and the Public Key on the Last Message don't match
|
||||
Image(systemName: "key.slash")
|
||||
.foregroundColor(.red)
|
||||
} else {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
} else {
|
||||
Image(systemName: "lock.open.fill")
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
Text(node.user?.longName ?? "unknown".localized)
|
||||
.font(.headline)
|
||||
.fontWeight(.regular)
|
||||
.allowsTightening(true)
|
||||
if node.favorite {
|
||||
Spacer()
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ struct Channels: View {
|
|||
if channelKey == "AQ==" {
|
||||
positionPrecision = 13
|
||||
preciseLocation = false
|
||||
positionsEnabled = true
|
||||
}
|
||||
} else if !supportedVersion && channelRole == 2 {
|
||||
positionPrecision = 0
|
||||
|
|
@ -104,7 +103,7 @@ struct Channels: View {
|
|||
} else {
|
||||
if channelKey == "AQ==" {
|
||||
preciseLocation = false
|
||||
if positionPrecision < 10 || positionPrecision > 16 {
|
||||
if (positionPrecision > 0 && positionPrecision < 10) || positionPrecision > 16 {
|
||||
positionPrecision = 13
|
||||
}
|
||||
} else if positionPrecision == 32 {
|
||||
|
|
@ -226,7 +225,7 @@ struct Channels: View {
|
|||
} label: {
|
||||
Label("save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !hasValidKey)
|
||||
.disabled(bleManager.connectedPeripheral == nil)// || !hasChanges)// !hasValidKey)
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
|
|
@ -259,10 +258,9 @@ struct Channels: View {
|
|||
channelKey = key
|
||||
positionsEnabled = false
|
||||
preciseLocation = false
|
||||
positionPrecision = 13
|
||||
positionPrecision = 0
|
||||
uplink = false
|
||||
downlink = false
|
||||
hasChanges = true
|
||||
|
||||
let newChannel = ChannelEntity(context: context)
|
||||
newChannel.id = channelIndex
|
||||
|
|
@ -274,6 +272,7 @@ struct Channels: View {
|
|||
newChannel.psk = Data(base64Encoded: channelKey) ?? Data()
|
||||
newChannel.positionPrecision = Int32(positionPrecision)
|
||||
selectedChannel = newChannel
|
||||
hasChanges = true
|
||||
|
||||
} label: {
|
||||
Label("Add Channel", systemImage: "plus.square")
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ struct ChannelForm: View {
|
|||
}
|
||||
|
||||
Section(header: Text("position")) {
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(isOn: $positionsEnabled) {
|
||||
Label(channelRole == 1 ? "Positions Enabled" : "Allow Position Requests", systemImage: positionsEnabled ? "mappin" : "mappin.slash")
|
||||
|
|
@ -140,20 +139,21 @@ struct ChannelForm: View {
|
|||
}
|
||||
|
||||
if positionsEnabled {
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(isOn: $preciseLocation) {
|
||||
Label("Precise Location", systemImage: "scope")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.disabled(!supportedVersion)
|
||||
.listRowSeparator(.visible)
|
||||
.onChange(of: preciseLocation) { pl in
|
||||
if pl == false {
|
||||
positionPrecision = 13
|
||||
if channelKey != "AQ==" && channelRole > 0 {
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(isOn: $preciseLocation) {
|
||||
Label("Precise Location", systemImage: "scope")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.disabled(!supportedVersion)
|
||||
.listRowSeparator(.visible)
|
||||
.onChange(of: preciseLocation) { pl in
|
||||
if pl == false {
|
||||
positionPrecision = 13
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !preciseLocation {
|
||||
VStack(alignment: .leading) {
|
||||
Label("Approximate Location", systemImage: "location.slash.circle.fill")
|
||||
|
|
@ -213,7 +213,7 @@ struct ChannelForm: View {
|
|||
}
|
||||
.onChange(of: preciseLocation) { loc in
|
||||
if loc == true {
|
||||
if channelKey == "AQ==" && channelRole == 0 {
|
||||
if channelKey == "AQ==" {
|
||||
preciseLocation = false
|
||||
} else {
|
||||
positionPrecision = 32
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ struct BluetoothConfig: View {
|
|||
@State var mode = 0
|
||||
@State var fixedPin = "123456"
|
||||
@State var shortPin = false
|
||||
@State var deviceLoggingEnabled = false
|
||||
var pinLength: Int = 6
|
||||
let numberFormatter: NumberFormatter = {
|
||||
let formatter = NumberFormatter()
|
||||
|
|
@ -70,10 +69,6 @@ struct BluetoothConfig: View {
|
|||
.foregroundColor(.red)
|
||||
}
|
||||
}
|
||||
Toggle(isOn: $deviceLoggingEnabled) {
|
||||
Label("Device Logging Enabled", systemImage: "ladybug")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
}
|
||||
.disabled(self.bleManager.connectedPeripheral == nil || node?.bluetoothConfig == nil)
|
||||
|
|
@ -85,7 +80,6 @@ struct BluetoothConfig: View {
|
|||
bc.enabled = enabled
|
||||
bc.mode = BluetoothModes(rawValue: mode)?.protoEnumValue() ?? Config.BluetoothConfig.PairingMode.randomPin
|
||||
bc.fixedPin = UInt32(fixedPin) ?? 123456
|
||||
bc.deviceLoggingEnabled = deviceLoggingEnabled
|
||||
let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: connectedNode.user!, toUser: node!.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
if adminMessageId > 0 {
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
|
|
@ -106,13 +100,24 @@ struct BluetoothConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
// Need to request a BluetoothConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node, node.bluetoothConfig == nil {
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty bluetooth config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
_ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.bluetoothConfig == nil {
|
||||
_ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestBluetoothConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -125,15 +130,11 @@ struct BluetoothConfig: View {
|
|||
.onChange(of: fixedPin) { newFixedPin in
|
||||
if newFixedPin != String(node?.bluetoothConfig?.fixedPin ?? -1) { hasChanges = true }
|
||||
}
|
||||
.onChange(of: deviceLoggingEnabled) {
|
||||
if $0 != node?.bluetoothConfig?.deviceLoggingEnabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
func setBluetoothValues() {
|
||||
self.enabled = node?.bluetoothConfig?.enabled ?? true
|
||||
self.mode = Int(node?.bluetoothConfig?.mode ?? 0)
|
||||
self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456)
|
||||
self.deviceLoggingEnabled = node?.bluetoothConfig?.deviceLoggingEnabled ?? false
|
||||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ struct ConfigHeader<T>: View {
|
|||
|
||||
} else if node != nil && node?.num ?? 0 != bleManager.connectedPeripheral?.num ?? 0 {
|
||||
// Let users know what is going on if they are using remote admin and don't have the config yet
|
||||
if node?[keyPath: config] == nil {
|
||||
Text("\(title) config data was requested over the admin channel but no response has been returned from the remote node. You can check the status of admin message requests in the admin message log.")
|
||||
let expiration = node?.sessionExpiration ?? Date()
|
||||
if node?[keyPath: config] == nil || expiration < node?.sessionExpiration ?? Date() {
|
||||
Text("\(title) config data was requested over the admin channel but no response has been returned from the remote node.")
|
||||
.font(.callout)
|
||||
.foregroundColor(.orange)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ struct DeviceConfig: View {
|
|||
@State var nodeInfoBroadcastSecs = 10800
|
||||
@State var doubleTapAsButtonPress = false
|
||||
@State var ledHeartbeatEnabled = true
|
||||
@State var isManaged = false
|
||||
@State var tzdef = ""
|
||||
|
||||
var body: some View {
|
||||
|
|
@ -62,12 +61,6 @@ struct DeviceConfig: View {
|
|||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
|
||||
Toggle(isOn: $isManaged) {
|
||||
Label("Managed Device", systemImage: "gearshape.arrow.triangle.2.circlepath")
|
||||
Text("Enabling Managed mode will restrict access to all radio configurations, such as short/long names, regions, channels, modules, etc. and will only be accessible through the Admin channel. To avoid being locked out, make sure the Admin channel is working properly before enabling it.")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
Picker("Node Info Broadcast Interval", selection: $nodeInfoBroadcastSecs ) {
|
||||
ForEach(UpdateIntervals.allCases) { ui in
|
||||
if ui.rawValue >= 3600 {
|
||||
|
|
@ -213,13 +206,8 @@ struct DeviceConfig: View {
|
|||
dc.rebroadcastMode = RebroadcastModes(rawValue: rebroadcastMode)?.protoEnumValue() ?? RebroadcastModes.all.protoEnumValue()
|
||||
dc.nodeInfoBroadcastSecs = UInt32(nodeInfoBroadcastSecs)
|
||||
dc.doubleTapAsButtonPress = doubleTapAsButtonPress
|
||||
dc.isManaged = isManaged
|
||||
dc.tzdef = tzdef
|
||||
dc.ledHeartbeatDisabled = !ledHeartbeatEnabled
|
||||
if isManaged {
|
||||
serialEnabled = false
|
||||
debugLogEnabled = false
|
||||
}
|
||||
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
if adminMessageId > 0 {
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
|
|
@ -242,13 +230,26 @@ struct DeviceConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
// Need to request a DeviceConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.deviceConfig == nil {
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty device config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? -1, context: context)
|
||||
if node != nil && connectedNode != nil && connectedNode?.user != nil {
|
||||
_ = bleManager.requestDeviceConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.deviceConfig == nil {
|
||||
_ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
if node.deviceConfig == nil {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestDeviceConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -276,9 +277,6 @@ struct DeviceConfig: View {
|
|||
.onChange(of: doubleTapAsButtonPress) {
|
||||
if $0 != node?.deviceConfig?.doubleTapAsButtonPress { hasChanges = true }
|
||||
}
|
||||
.onChange(of: isManaged) {
|
||||
if $0 != node?.deviceConfig?.isManaged { hasChanges = true }
|
||||
}
|
||||
.onChange(of: tzdef) { newTzdef in
|
||||
if newTzdef != node?.deviceConfig?.tzdef { hasChanges = true }
|
||||
}
|
||||
|
|
@ -301,7 +299,6 @@ struct DeviceConfig: View {
|
|||
}
|
||||
self.doubleTapAsButtonPress = node?.deviceConfig?.doubleTapAsButtonPress ?? false
|
||||
self.ledHeartbeatEnabled = node?.deviceConfig?.ledHeartbeatEnabled ?? true
|
||||
self.isManaged = node?.deviceConfig?.isManaged ?? false
|
||||
self.tzdef = node?.deviceConfig?.tzdef ?? ""
|
||||
if self.tzdef.isEmpty {
|
||||
self.tzdef = TimeZone.current.posixDescription
|
||||
|
|
|
|||
|
|
@ -163,13 +163,24 @@ struct DisplayConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
// Need to request a LoRaConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.displayConfig == nil {
|
||||
.onFirstAppear {
|
||||
// Need to request a DisplayConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty display config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestDisplayConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.displayConfig == nil {
|
||||
_ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestDisplayConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,13 +232,24 @@ struct LoRaConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
// Need to request a LoRaConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.loRaConfig == nil {
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty lora config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestLoRaConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.loRaConfig == nil {
|
||||
_ = bleManager.requestLoRaConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestLoRaConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
import MeshtasticProtobufs
|
||||
import SwiftUI
|
||||
import OSLog
|
||||
|
||||
@available(iOS 17.0, macOS 14.0, *)
|
||||
struct AmbientLightingConfig: View {
|
||||
|
|
@ -85,12 +86,24 @@ struct AmbientLightingConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
// Need to request a Ambient Lighting Config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.ambientLightingConfig == nil {
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestAmbientLightingConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty ambient lighting config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.ambientLightingConfig == nil {
|
||||
_ = bleManager.requestAmbientLightingConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestAmbientLightingConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,13 +233,24 @@ struct CannedMessagesConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
// Need to request a CannedMessagesModuleConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.cannedMessageConfig == nil {
|
||||
Logger.mesh.info("empty canned messages module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestCannedMessagesModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty canned message config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.cannedMessageConfig == nil {
|
||||
_ = bleManager.requestCannedMessagesModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestCannedMessagesModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,13 +189,24 @@ struct DetectionSensorConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
// Need to request a Detection Sensor Module Config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.detectionSensorConfig == nil {
|
||||
Logger.mesh.info("empty detection sensor module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestDetectionSensorModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
.onFirstAppear {
|
||||
// Need to request a DetectionSensorModuleConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty detection sensor config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.detectionSensorConfig == nil {
|
||||
_ = bleManager.requestDetectionSensorModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestDetectionSensorModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,13 +199,24 @@ struct ExternalNotificationConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.externalNotificationConfig == nil {
|
||||
Logger.mesh.info("empty external notification module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestExternalNotificationModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
.onFirstAppear {
|
||||
// Need to request a ExternalNotificationModuleConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty external notificaiton module config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.externalNotificationConfig == nil {
|
||||
_ = bleManager.requestExternalNotificationModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestExternalNotificationModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -279,7 +290,7 @@ struct ExternalNotificationConfig: View {
|
|||
if newNagTimeout != node!.externalNotificationConfig!.nagTimeout { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: useI2SAsBuzzer) {
|
||||
.onChange(of: useI2SAsBuzzer) {
|
||||
if let val = node?.externalNotificationConfig?.useI2SAsBuzzer {
|
||||
hasChanges = $0 != val
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,13 +347,24 @@ struct MQTTConfig: View {
|
|||
if newMapPublishIntervalSecs != node!.mqttConfig!.mapPublishIntervalSecs { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.mqttConfig == nil {
|
||||
.onFirstAppear {
|
||||
// Need to request a MqttModuleConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty mqtt module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestMqttModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.mqttConfig == nil {
|
||||
_ = bleManager.requestMqttModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestMqttModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import MeshtasticProtobufs
|
||||
import SwiftUI
|
||||
import OSLog
|
||||
|
||||
struct PaxCounterConfig: View {
|
||||
@Environment(\.managedObjectContext) private var context
|
||||
|
|
@ -57,12 +58,24 @@ struct PaxCounterConfig: View {
|
|||
name: "\(bleManager.connectedPeripheral?.shortName ?? "?")"
|
||||
)
|
||||
})
|
||||
.onAppear {
|
||||
// Need to request a PAX Counter module config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.paxCounterConfig == nil {
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestPaxCounterModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
.onFirstAppear {
|
||||
// Need to request a PaxCounterModuleConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty pax counter module config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.paxCounterConfig == nil {
|
||||
_ = bleManager.requestPaxCounterModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestPaxCounterModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,13 +81,24 @@ struct RangeTestConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
// Need to request a RangeTestModule Config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.rangeTestConfig == nil {
|
||||
Logger.mesh.debug("empty range test module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestRangeTestModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
.onFirstAppear {
|
||||
// Need to request a RangeTestModuleConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty range test module config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.rangeTestConfig == nil {
|
||||
_ = bleManager.requestRangeTestModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestRangeTestModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import OSLog
|
||||
|
||||
struct RtttlConfig: View {
|
||||
@Environment(\.managedObjectContext) var context
|
||||
|
|
@ -71,12 +72,24 @@ struct RtttlConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
// Need to request a Rtttl Config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && (node?.rtttlConfig == nil || node?.rtttlConfig?.ringtone?.count ?? 0 == 0) {
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestRtttlConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
.onFirstAppear {
|
||||
// Need to request a RtttlConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty range test module config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.rtttlConfig == nil {
|
||||
_ = bleManager.requestRtttlConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestRtttlConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,20 +136,31 @@ struct SerialConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
// Need to request a SerialModuleConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.serialConfig == nil {
|
||||
Logger.mesh.debug("empty serial module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestSerialModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty serial module config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.serialConfig == nil {
|
||||
_ = bleManager.requestSerialModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestSerialModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: enabled) {
|
||||
if $0 != node?.serialConfig?.enabled { hasChanges = true }
|
||||
}
|
||||
.onChange(of: echo) {
|
||||
.onChange(of: echo) {
|
||||
if $0 != node?.serialConfig?.echo { hasChanges = true }
|
||||
}
|
||||
.onChange(of: rxd) { newRxd in
|
||||
|
|
|
|||
|
|
@ -146,13 +146,24 @@ struct StoreForwardConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
// Need to request a Detection Sensor Module Config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.storeForwardConfig == nil {
|
||||
Logger.mesh.debug("empty store and forward module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestStoreAndForwardModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
.onFirstAppear {
|
||||
// Need to request a StoreForwardModuleConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty store & forward module config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.storeForwardConfig == nil {
|
||||
_ = bleManager.requestStoreAndForwardModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestStoreAndForwardModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,13 +134,24 @@ struct TelemetryConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.telemetryConfig == nil {
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty telemetry module config")
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestTelemetryModuleConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration && node.num != connectedNode.num {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.telemetryConfig == nil {
|
||||
_ = bleManager.requestTelemetryModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestTelemetryModuleConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,6 +128,27 @@ struct NetworkConfig: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.onFirstAppear {
|
||||
// Need to request a NetworkConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty network config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.networkConfig == nil {
|
||||
_ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestNetworkConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: wifiEnabled) {
|
||||
if $0 != node?.networkConfig?.wifiEnabled { hasChanges = true }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,18 +376,25 @@ struct PositionConfig: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
supportedVersion = bleManager.connectedVersion == "0.0.0" || self.minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedAscending || minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedSame
|
||||
// Need to request a PositionConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, node?.positionConfig == nil {
|
||||
// Need to request a NetworkConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty position config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let node, let connectedNode {
|
||||
_ = bleManager.requestPositionConfig(
|
||||
fromUser: connectedNode.user!,
|
||||
toUser: node.user!,
|
||||
adminIndex: connectedNode.myInfo?.adminIndex ?? 0
|
||||
)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.positionConfig == nil {
|
||||
_ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestPositionConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import SwiftUI
|
||||
import MeshtasticProtobufs
|
||||
import OSLog
|
||||
|
||||
struct PowerConfig: View {
|
||||
@Environment(\.managedObjectContext) private var context
|
||||
|
|
@ -117,7 +118,7 @@ struct PowerConfig: View {
|
|||
.font(.subheadline)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
.onFirstAppear {
|
||||
Api().loadDeviceHardwareData { (hw) in
|
||||
for device in hw {
|
||||
let currentHardware = node?.user?.hwModel ?? "UNSET"
|
||||
|
|
@ -127,11 +128,23 @@ struct PowerConfig: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Need to request a Power config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.powerConfig == nil {
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestPowerConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
// Need to request a NetworkConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty power config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.powerConfig == nil {
|
||||
_ = bleManager.requestPowerConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestPowerConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ struct SecurityConfig: View {
|
|||
@State var isManaged = false
|
||||
@State var serialEnabled = false
|
||||
@State var debugLogApiEnabled = false
|
||||
@State var bluetoothLoggingEnabled = false
|
||||
@State var adminChannelEnabled = false
|
||||
|
||||
var body: some View {
|
||||
|
|
@ -71,10 +70,14 @@ struct SecurityConfig: View {
|
|||
}
|
||||
}
|
||||
Section(header: Text("Logs")) {
|
||||
Toggle(isOn: $bluetoothLoggingEnabled) {
|
||||
Label("Bluetooth Logs", systemImage: "dot.radiowaves.right")
|
||||
Text("View and export position-redacted device logs over Bluetooth")
|
||||
Link("View Logs", destination: URL(string: "meshtastic:///settings/debugLogs")!)
|
||||
Toggle(isOn: $serialEnabled) {
|
||||
Label("Serial Console", systemImage: "terminal")
|
||||
Text("Serial Console over the Stream API.")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
Toggle(isOn: $debugLogApiEnabled) {
|
||||
Label("Debug Logs", systemImage: "ant.fill")
|
||||
Text("Output live debug logging over serial, view and export position-redacted device logs over Bluetooth.")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
|
|
@ -82,7 +85,7 @@ struct SecurityConfig: View {
|
|||
if adminKey.length > 0 || adminChannelEnabled {
|
||||
Toggle(isOn: $isManaged) {
|
||||
Label("Managed Device", systemImage: "gearshape.arrow.triangle.2.circlepath")
|
||||
Text("Device is managed by a mesh administrator.")
|
||||
Text("Device is managed by a mesh administrator, the user is unable to access any of the device settings.")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
|
|
@ -92,20 +95,6 @@ struct SecurityConfig: View {
|
|||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
Section(header: Text("Developer")) {
|
||||
Toggle(isOn: $serialEnabled) {
|
||||
Label("Serial Console", systemImage: "terminal")
|
||||
Text("Serial Console over the Stream API.")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
if serialEnabled {
|
||||
Toggle(isOn: $debugLogApiEnabled) {
|
||||
Label("Serial Debug Logs", systemImage: "ant.fill")
|
||||
Text("Output live debug logging over serial.")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.scrollDismissesKeyboard(.immediately)
|
||||
|
|
@ -126,9 +115,6 @@ struct SecurityConfig: View {
|
|||
.onChange(of: debugLogApiEnabled) {
|
||||
if $0 != node?.securityConfig?.debugLogApiEnabled { hasChanges = true }
|
||||
}
|
||||
.onChange(of: bluetoothLoggingEnabled) {
|
||||
if $0 != node?.securityConfig?.bluetoothLoggingEnabled { hasChanges = true }
|
||||
}
|
||||
.onChange(of: adminChannelEnabled) {
|
||||
if $0 != node?.securityConfig?.adminChannelEnabled { hasChanges = true }
|
||||
}
|
||||
|
|
@ -162,11 +148,25 @@ struct SecurityConfig: View {
|
|||
hasChanges = true
|
||||
}
|
||||
.onFirstAppear {
|
||||
// Need to request a Power config from the remote node before allowing changes
|
||||
if bleManager.connectedPeripheral != nil && node?.securityConfig == nil {
|
||||
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context)
|
||||
if node != nil && connectedNode != nil {
|
||||
_ = bleManager.requestSecurityConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
// Need to request a DeviceConfig from the remote node before allowing changes
|
||||
if let connectedPeripheral = bleManager.connectedPeripheral, let node {
|
||||
Logger.mesh.info("empty security config")
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheral.num, context: context)
|
||||
if let connectedNode {
|
||||
if node.num != connectedNode.num {
|
||||
if UserDefaults.enableAdministration {
|
||||
/// 2.5 Administration with session passkey
|
||||
let expiration = node.sessionExpiration ?? Date()
|
||||
if expiration < Date() || node.securityConfig == nil {
|
||||
_ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
} else {
|
||||
if node.deviceConfig == nil {
|
||||
/// Legacy Administration
|
||||
_ = bleManager.requestSecurityConfig(fromUser: connectedNode.user!, toUser: node.user!, adminIndex: connectedNode.myInfo?.adminIndex ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +190,6 @@ struct SecurityConfig: View {
|
|||
config.isManaged = isManaged
|
||||
config.serialEnabled = serialEnabled
|
||||
config.debugLogApiEnabled = debugLogApiEnabled
|
||||
config.bluetoothLoggingEnabled = bluetoothLoggingEnabled
|
||||
config.adminChannelEnabled = adminChannelEnabled
|
||||
|
||||
let adminMessageId = bleManager.saveSecurityConfig(
|
||||
|
|
@ -215,7 +214,6 @@ struct SecurityConfig: View {
|
|||
self.isManaged = node?.securityConfig?.isManaged ?? false
|
||||
self.serialEnabled = node?.securityConfig?.serialEnabled ?? false
|
||||
self.debugLogApiEnabled = node?.securityConfig?.debugLogApiEnabled ?? false
|
||||
self.bluetoothLoggingEnabled = node?.securityConfig?.bluetoothLoggingEnabled ?? false
|
||||
self.adminChannelEnabled = node?.securityConfig?.adminChannelEnabled ?? false
|
||||
self.hasChanges = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ struct Settings: View {
|
|||
if bleManager.connectedPeripheral != nil {
|
||||
Section("Configure") {
|
||||
if node?.canRemoteAdmin ?? false {
|
||||
Picker("Configuring Node", selection: $selectedNode) {
|
||||
Picker("Node", selection: $selectedNode) {
|
||||
if selectedNode == 0 {
|
||||
Text("Connect to a Node").tag(0)
|
||||
}
|
||||
|
|
@ -365,6 +365,7 @@ struct Settings: View {
|
|||
} icon: {
|
||||
Image(systemName: "av.remote")
|
||||
}
|
||||
.font(.caption2)
|
||||
.tag(Int(node.num))
|
||||
} else if !UserDefaults.enableAdministration && node.metadata != nil { /// Nodes using the old admin system
|
||||
Label {
|
||||
|
|
@ -390,8 +391,7 @@ struct Settings: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.pickerStyle(.automatic)
|
||||
.labelsHidden()
|
||||
.pickerStyle(.navigationLink)
|
||||
.onChange(of: selectedNode) { newValue in
|
||||
if selectedNode > 0 {
|
||||
let node = nodes.first(where: { $0.num == newValue })
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue