Traceroute has position flag

Fix MQTT server port crash
Adjust device metrics grid colums
Fix some index issues in the channel editor
Clean up settings view, add duty cycle warning
This commit is contained in:
Garth Vander Houwen 2024-02-20 18:50:49 -08:00
parent 52af088d8c
commit 3c623d3441
6 changed files with 98 additions and 42 deletions

View file

@ -409,7 +409,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
}
let receivingNode = fetchedNodes.first(where: { $0.num == destNum })
let connectedNode = fetchedNodes.first(where: { $0.num == self.connectedPeripheral.num })
traceRoute.id = Int64(meshPacket.id)
traceRoute.time = Date()
traceRoute.node = receivingNode
@ -524,7 +523,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
var nowKnown = false
// MyInfo from initial connection
if decodedInfo.myInfo.isInitialized && decodedInfo.myInfo.myNodeNum > 0 {
if context != nil && decodedInfo.myInfo.isInitialized && decodedInfo.myInfo.myNodeNum > 0 {
let myInfo = myInfoPacket(myInfo: decodedInfo.myInfo, peripheralId: self.connectedPeripheral.id, context: context!)
if myInfo != nil {
@ -660,6 +659,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
let traceRouteHop = TraceRouteHopEntity(context: context!)
traceRouteHop.time = Date()
if hopNode?.hasPositions ?? false {
traceRoute?.hasPositions = true
let mostRecent = hopNode?.positions?.lastObject as! PositionEntity
if mostRecent.time! >= Calendar.current.date(byAdding: .minute, value: -60, to: Date())! {
traceRouteHop.altitude = mostRecent.altitude

View file

@ -162,6 +162,7 @@ func channelPacket (channel: Channel, fromNum: Int64, context: NSManagedObjectCo
if newChannel.name?.lowercased() == "admin" {
fetchedMyInfo[0].adminIndex = newChannel.index
}
context.refresh(newChannel, mergeChanges: true)
do {
try context.save()
} catch {

View file

@ -33,7 +33,7 @@ class MqttClientProxyManager {
} else if host != nil && host!.contains(":") {
if let fullHost = host {
host = fullHost.components(separatedBy: ":")[0]
defaultServerPort = Int(fullHost.components(separatedBy: ":")[1]) ?? 1883
defaultServerPort = Int(fullHost.components(separatedBy: ":")[1]) ?? (useSsl ? 8883 : 1883)
}
}
if let host = host {

View file

@ -114,10 +114,10 @@ struct DeviceMetricsLog: View {
} else {
ScrollView {
let columns = [
GridItem(.flexible(minimum: 30, maximum: 45), spacing: 0.1),
GridItem(.flexible(minimum: 30, maximum: 50), spacing: 0.1),
GridItem(.flexible(minimum: 30, maximum: 70), spacing: 0.1),
GridItem(.flexible(minimum: 30, maximum: 65), spacing: 0.1),
GridItem(.flexible(minimum: 35, maximum: 55), spacing: 0.1),
GridItem(.flexible(minimum: 35, maximum: 60), spacing: 0.1),
GridItem(.flexible(minimum: 35, maximum: 70), spacing: 0.1),
GridItem(.flexible(minimum: 35, maximum: 65), spacing: 0.1),
GridItem(.flexible(minimum: 130, maximum: 200), spacing: 0.1)
]
LazyVGrid(columns: columns, alignment: .leading, spacing: 1) {

View file

@ -43,7 +43,6 @@ struct Channels: View {
var body: some View {
VStack {
List {
if #available(iOS 17.0, macOS 14.0, *) {
TipView(CreateChannelsTip(), arrowEdge: .bottom)
@ -98,16 +97,18 @@ struct Channels: View {
if node?.myInfo?.channels?.array.count ?? 0 < 8 && node != nil {
Button {
let lastChannel = node?.myInfo?.channels?.lastObject as? ChannelEntity
var lastChannelIndex = lastChannel?.index ?? 0
channelKeySize = 16
let key = generateChannelKey(size: channelKeySize)
channelName = ""
channelIndex = Int32(node!.myInfo!.channels!.array.count)
channelIndex = Int32(lastChannelIndex + 1)
channelRole = 2
channelKey = key
uplink = false
downlink = false
hasChanges = false
hasChanges = true
isPresentingEditView = true
} label: {
@ -270,11 +271,38 @@ struct Channels: View {
channel.index = channelIndex
channel.role = ChannelRoles(rawValue: channelRole)?.protoEnumValue() ?? .secondary
if channel.role != Channel.Role.disabled {
channel.settings.id = UInt32(channelIndex)
channel.index = channelIndex
channel.settings.name = channelName
channel.settings.psk = Data(base64Encoded: channelKey) ?? Data()
channel.settings.uplinkEnabled = uplink
channel.settings.downlinkEnabled = downlink
let newChannel = ChannelEntity(context: context)
newChannel.id = Int32(channel.index)
newChannel.index = Int32(channel.index)
newChannel.uplinkEnabled = channel.settings.uplinkEnabled
newChannel.downlinkEnabled = channel.settings.downlinkEnabled
newChannel.name = channel.settings.name
newChannel.role = Int32(channel.role.rawValue)
newChannel.psk = channel.settings.psk
guard let mutableChannels = node?.myInfo?.channels?.mutableCopy() as? NSMutableOrderedSet else {
return
}
if mutableChannels.contains(newChannel) {
mutableChannels.replaceObject(at: Int(newChannel.index), with: newChannel)
} else {
mutableChannels.add(newChannel)
}
node!.myInfo!.channels = mutableChannels.copy() as? NSOrderedSet
context.refresh(newChannel, mergeChanges: true)
do {
try context.save()
print("💾 Saved Channel: \(channel.settings.name)")
} catch {
context.rollback()
let nsError = error as NSError
print("💥 Unresolved Core Data error in the channel editor. Error: \(nsError)")
}
} else {
if channelIndex <= node!.myInfo!.channels?.count ?? 0 {
guard let channelEntity = node!.myInfo!.channels?[Int(channelIndex)] as? ChannelEntity else {
@ -297,6 +325,7 @@ struct Channels: View {
if adminMessageId > 0 {
self.isPresentingEditView = false
channelName = ""
channelRole = 2
hasChanges = false
_ = bleManager.getChannel(channel: channel, fromUser: node!.user!, toUser: node!.user!)
}

View file

@ -81,46 +81,72 @@ struct Settings: View {
let node = nodes.first(where: { $0.num == preferredNodeNum })
let hasAdmin = node?.myInfo?.adminIndex ?? 0 > 0 ? true : false
if !(node?.deviceConfig?.isManaged ?? false) {
Section("Configure") {
if hasAdmin {
Picker("Configuring Node", selection: $selectedNode) {
if selectedNode == 0 {
Text("Connect to a Node").tag(0)
}
ForEach(nodes) { node in
if node.num == bleManager.connectedPeripheral?.num ?? 0 {
Text("BLE Config: \(node.user?.longName ?? "unknown".localized)")
.tag(Int(node.num))
} else if node.metadata != nil {
Text("Remote Config: \(node.user?.longName ?? "unknown".localized)")
.tag(Int(node.num))
} else if hasAdmin {
Text("Request Admin: \(node.user?.longName ?? "unknown".localized)")
.tag(Int(node.num))
if bleManager.connectedPeripheral != nil {
Section("Configure") {
if hasAdmin {
Picker("Configuring Node", selection: $selectedNode) {
if selectedNode == 0 {
Text("Connect to a Node").tag(0)
}
}
}
.pickerStyle(.automatic)
.labelsHidden()
.onChange(of: selectedNode) { newValue in
if selectedNode > 0 {
let node = nodes.first(where: { $0.num == newValue })
let connectedNode = nodes.first(where: { $0.num == preferredNodeNum })
preferredNodeNum = Int(connectedNode?.num ?? 0)// Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral?.num ?? 0 : 0)
if connectedNode != nil && connectedNode?.user != nil && connectedNode?.myInfo != nil && node?.user != nil && node?.metadata == nil {
let adminMessageId = bleManager.requestDeviceMetadata(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode!.myInfo!.adminIndex, context: context)
if adminMessageId > 0 {
print("Sent node metadata request from node details")
ForEach(nodes) { node in
if node.num == bleManager.connectedPeripheral?.num ?? 0 {
Text("BLE Config: \(node.user?.longName ?? "unknown".localized)")
.tag(Int(node.num))
} else if node.metadata != nil {
Text("Remote Config: \(node.user?.longName ?? "unknown".localized)")
.tag(Int(node.num))
} else if hasAdmin {
Text("Request Admin: \(node.user?.longName ?? "unknown".localized)")
.tag(Int(node.num))
}
}
}
.pickerStyle(.automatic)
.labelsHidden()
.onChange(of: selectedNode) { newValue in
if selectedNode > 0 {
let node = nodes.first(where: { $0.num == newValue })
let connectedNode = nodes.first(where: { $0.num == preferredNodeNum })
preferredNodeNum = Int(connectedNode?.num ?? 0)// Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral?.num ?? 0 : 0)
if connectedNode != nil && connectedNode?.user != nil && connectedNode?.myInfo != nil && node?.user != nil && node?.metadata == nil {
let adminMessageId = bleManager.requestDeviceMetadata(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode!.myInfo!.adminIndex, context: context)
if adminMessageId > 0 {
print("Sent node metadata request from node details")
}
}
}
}
} else {
if bleManager.connectedPeripheral != nil {
Text("Connected Node \(node?.user?.longName ?? "unknown".localized)")
}
}
} else {
Text("Connected Node \(node?.user?.longName ?? "unknown".localized)")
}
}
Section("radio.configuration") {
if node != nil && node?.loRaConfig != nil {
let rc = RegionCodes(rawValue: Int(node?.loRaConfig?.regionCode ?? 0))
if rc?.dutyCycle ?? 0 < 1 {
Label {
Text("Hourly Duty Cycle")
} icon: {
Image(systemName: "clock.arrow.circlepath")
.symbolRenderingMode(.hierarchical)
.foregroundColor(.red)
}
Text("Your region has a \(rc?.dutyCycle ?? 0)% hourly duty cycle, your radio will stop sending packets when it reaches the hourly limit.")
.foregroundColor(.orange)
.font(.caption)
Text("Limit all periodic broadcasts intervals especially telemetry and position. If you need to increase hops, do it on nodes at the edges, not the ones in the middle. MQTT is not advised when you are duty cycle restricted because the gateway node is then doing all the work.")
.font(.caption2)
.foregroundColor(.gray)
}
}
NavigationLink {
LoRaConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {