mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
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:
parent
52af088d8c
commit
3c623d3441
6 changed files with 98 additions and 42 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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!)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue