Finish new node info view with positions array

This commit is contained in:
Garth Vander Houwen 2021-12-18 01:01:56 -08:00
parent 544c584237
commit 883fcc0974
8 changed files with 191 additions and 129 deletions

View file

@ -19,6 +19,7 @@
DD5394FC276993AD00AD86B1 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = DD5394FB276993AD00AD86B1 /* SwiftProtobuf */; };
DD5394FE276BA0EF00AD86B1 /* PositionEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5394FD276BA0EF00AD86B1 /* PositionEntityExtension.swift */; };
DD539500276C452400AD86B1 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5394FF276C452400AD86B1 /* Preferences.swift */; };
DD539502276DAA6A00AD86B1 /* MapLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD539501276DAA6A00AD86B1 /* MapLocation.swift */; };
DD8169F9271F1A6100F4AB02 /* MeshLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8169F8271F1A6100F4AB02 /* MeshLogger.swift */; };
DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */; };
DD8169FF272476C700F4AB02 /* LogDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8169FE272476C700F4AB02 /* LogDocument.swift */; };
@ -78,6 +79,7 @@
DD4A911F2708C66600501B7E /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
DD5394FD276BA0EF00AD86B1 /* PositionEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionEntityExtension.swift; sourceTree = "<group>"; };
DD5394FF276C452400AD86B1 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
DD539501276DAA6A00AD86B1 /* MapLocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLocation.swift; sourceTree = "<group>"; };
DD8169F8271F1A6100F4AB02 /* MeshLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshLogger.swift; sourceTree = "<group>"; };
DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshLog.swift; sourceTree = "<group>"; };
DD8169FE272476C700F4AB02 /* LogDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogDocument.swift; sourceTree = "<group>"; };
@ -276,6 +278,7 @@
isa = PBXGroup;
children = (
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */,
DD539501276DAA6A00AD86B1 /* MapLocation.swift */,
);
path = Model;
sourceTree = "<group>";
@ -517,6 +520,7 @@
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */,
DD47E3D926F3093800029299 /* MessageBubble.swift in Sources */,
DD8169F9271F1A6100F4AB02 /* MeshLogger.swift in Sources */,
DD539502276DAA6A00AD86B1 /* MapLocation.swift in Sources */,
DDAF8C6726ED0C8C0058C060 /* remote_hardware.pb.swift in Sources */,
DDAF8C6526ED0A490058C060 /* channel.pb.swift in Sources */,
DD47E3DD26F390A000029299 /* Messages.swift in Sources */,

View file

@ -112,38 +112,6 @@
landmarkType = "24">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "973F199D-5292-450E-ABD4-973A3103AA17"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "397"
endingLineNumber = "397"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "37995C5C-4B75-4276-8CB3-120AB0A705D7"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "456"
endingLineNumber = "456"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
@ -176,5 +144,21 @@
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "FCCE5870-E475-42D6-AB90-5632098DC9FB"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "482"
endingLineNumber = "482"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View file

@ -480,7 +480,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
newNode.user = newUser
}
if false && decodedInfo.nodeInfo.hasPosition && decodedInfo.nodeInfo.position.latitudeI != 0 {
if decodedInfo.nodeInfo.hasPosition && decodedInfo.nodeInfo.position.latitudeI != 0 {
let position = PositionEntity(context: context!)
position.latitudeI = decodedInfo.nodeInfo.position.latitudeI
@ -491,7 +491,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
var newPostions = [PositionEntity]()
newPostions.append(position)
newNode.positions? = NSSet(array : newPostions)
newNode.positions? = NSOrderedSet(array : newPostions)
}
// Look for a MyInfo
@ -534,9 +534,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
position.time = Date(timeIntervalSince1970: TimeInterval(Int64(decodedInfo.nodeInfo.position.time)))
if position.latitudeI != 0 {
let mutablePositions = fetchedNode[0].positions!.mutableCopy() as! NSMutableSet
let mutablePositions = fetchedNode[0].positions!.mutableCopy() as! NSMutableOrderedSet
mutablePositions.add(position)
fetchedNode[0].positions = mutablePositions.copy() as? NSSet
fetchedNode[0].positions = mutablePositions.copy() as? NSOrderedSet
}
}
// Look for a MyInfo
@ -769,7 +769,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
if meshLoggingEnabled { MeshLogger.log("BLE Config Complete Packet Id: \(decodedInfo.configCompleteID)") }
print("BLE Config Complete Packet Id: \(decodedInfo.configCompleteID)")
self.connectedPeripheral.subscribed = true
peripherals.removeAll(where: { $0.peripheral.state != CBPeripheralState.connected })
peripherals.removeAll(where: { $0.peripheral.state == CBPeripheralState.disconnected })
}
default:

View file

@ -0,0 +1,15 @@
//
// MapLocation.swift
// MeshtasticClient
//
// Created by Garth Vander Houwen on 12/17/21.
//
import Foundation
import MapKit
struct MapLocation: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}

View file

@ -81,11 +81,13 @@ struct Connect: View {
if value {
if bleManager.connectedPeripheral != nil {
let deviceName = (bleManager.connectedPeripheral.peripheral.name ?? "")
userSettings.preferredPeripheralName = deviceName
} else {
userSettings.preferredPeripheralName = bleManager.connectedPeripheral.peripheral.name ?? "Unknown Device"
userSettings.preferredPeripheralName = bleManager.connectedPeripheral.longName
}
userSettings.preferredPeripheralId = bleManager.connectedPeripheral!.peripheral.identifier.uuidString

View file

@ -48,7 +48,7 @@ struct Messages: View {
ForEach(messages) { message in
HStack(alignment: .top) {
let currentUser: Bool = (message.fromUser != nil && bleManager.connectedPeripheral.num == message.fromUser!.num)
let currentUser: Bool = false// (message.fromUser != nil && bleManager.connectedPeripheral.num == message.fromUser!.num)
CircleText(text: (message.fromUser?.longName ?? "???"), color: currentUser ? .accentColor : Color(.darkGray)).padding(.all, 5)

View file

@ -9,19 +9,14 @@ import CoreLocation
struct NodeDetail: View {
// CoreData
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
var node: NodeInfoEntity
struct MapLocation: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}
var body: some View {
let mostRecent = node.positions?.lastObject as! PositionEntity
GeometryReader { bounds in
@ -29,34 +24,46 @@ struct NodeDetail: View {
if node.positions != nil && node.positions!.count > 0 {
// let mostRecentPositions = node.positions.max(by: {
// $0. < $1.timeIntervalSinceReferenceDate
// })
// let nodeCoordinatePosition = CLLocationCoordinate2D(latitude: node.positions.latitude!, longitude: node.position.longitude!)
//
// let regionBinding = Binding<MKCoordinateRegion>(
// get: {
// MKCoordinateRegion(center: nodeCoordinatePosition, span: MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005))
// },
// set: { _ in }
// )
// let annotations = [MapLocation(name: node.user!.shortName, coordinate: node.positions?.first(where: <#T##(Any) throws -> Bool#>).coordinate!)]
//
// Map(coordinateRegion: regionBinding, showsUserLocation: true, userTrackingMode: .none, annotationItems: annotations) { location in
// MapAnnotation(
// coordinate: location.coordinate,
// content: {
// CircleText(text: node.user.shortName, color: .accentColor)
// }
// )
// }.frame(idealWidth: bounds.size.width, minHeight: bounds.size.height / 2)
let nodeCoordinatePosition = CLLocationCoordinate2D(latitude: mostRecent.latitude!, longitude: mostRecent.longitude!)
let regionBinding = Binding<MKCoordinateRegion>(
get: {
MKCoordinateRegion(center: nodeCoordinatePosition, span: MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005))
},
set: { _ in }
)
let annotations = [MapLocation(name: node.user!.shortName ?? "???", coordinate: mostRecent.coordinate!)]
Map(coordinateRegion: regionBinding, showsUserLocation: true, userTrackingMode: .none, annotationItems: annotations) { location in
MapAnnotation(
coordinate: location.coordinate,
content: {
CircleText(text: node.user!.shortName ?? "???", color: .accentColor)
}
)
}
.frame(idealWidth: bounds.size.width, maxHeight: bounds.size.height / 3)
} else {
Image(node.user?.hwModel ?? "UNSET")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: bounds.size.width, height: bounds.size.height / 2)
.frame(width: bounds.size.width, height: bounds.size.height / 3)
}
ScrollView {
if node.lastHeard != nil {
HStack {
Image(systemName: "clock").font(.title2).foregroundColor(.accentColor)
Text("Last Heard: \(node.lastHeard!, style: .relative) ago").font(.title3)
}
.padding()
Divider()
}
HStack {
@ -67,7 +74,20 @@ struct NodeDetail: View {
}
.padding([.leading, .trailing, .bottom])
Divider()
if node.snr > 0 {
VStack {
Image(node.user!.hwModel ?? "UNSET")
.resizable()
.frame(width: 50, height: 50)
.cornerRadius(5)
Text(String(node.user!.hwModel ?? "UNSET"))
.font(.subheadline).fixedSize()
}
.padding()
if true {//node.snr > 0 {
Divider()
VStack(alignment: .center) {
Image(systemName: "waveform.path")
@ -78,67 +98,39 @@ struct NodeDetail: View {
Text(String(node.snr))
.font(.title2)
.foregroundColor(.gray)
.fixedSize()
}
Divider()
.padding([.leading, .trailing, .bottom])
}
// VStack(alignment: .center) {
// BatteryIcon(batteryLevel: node.position.batteryLevel, font: .title, color: .accentColor)
// if node.position.batteryLevel != nil && node.position.batteryLevel! > 0 {
// Text("Battery").font(.title2).fixedSize()
// Text(String(node.position.batteryLevel!) + "%")
// .font(.title2)
// .foregroundColor(.gray)
// .symbolRenderingMode(.hierarchical)
// } else {
// Text("Powered").font(.title2)
// }
// }
}.padding(4)
Divider()
HStack {
Image(node.user!.hwModel ?? "UNSET")
.resizable()
.frame(width: 60, height: 60)
.cornerRadius(5)
Text("Model: " + String(node.user!.hwModel ?? "UNSET"))
.font(.title3)
if node.positions!.count > 0 {
Divider()
VStack(alignment: .center) {
BatteryIcon(batteryLevel: mostRecent.batteryLevel, font: .title, color: .accentColor)
.padding(.bottom)
if mostRecent.batteryLevel > 0 {
Text("Battery").font(.title2).fixedSize()
Text(String(mostRecent.batteryLevel) + "%")
.font(.title2)
.foregroundColor(.gray)
.symbolRenderingMode(.hierarchical)
} else {
Text("Powered")
.font(.callout)
.fixedSize()
}
}
.padding([.leading, .trailing, .bottom])
}
}
.padding()
.padding(4)
Divider()
if node.lastHeard != nil {
HStack {
Image(systemName: "clock").font(.title2).foregroundColor(.accentColor)
Text("Last Heard: \(node.lastHeard!, style: .relative) ago").font(.title3)
}.padding()
Divider()
}
// if node.position.coordinate != nil {
// HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 14) {
// Image(systemName: "mappin").font(.title).foregroundColor(.accentColor)
// VStack(alignment: .leading) {
// Text("Latitude").font(.headline)
// Text(String(node.position.latitude ?? 0)).font(.caption).foregroundColor(.gray)
// }
// Divider()
// VStack(alignment: .leading) {
// Text("Longitude").font(.headline)
// Text(String(node.position.longitude ?? 0)).font(.caption).foregroundColor(.gray)
// }
// Divider()
// VStack(alignment: .leading) {
// Text("Altitude").font(.headline)
// Text(String(node.position.altitude ?? 0) + " m").font(.caption).foregroundColor(.gray)
// }
// }.padding()
// Divider()
// }
HStack(alignment: .center) {
VStack {
HStack {
@ -156,6 +148,63 @@ struct NodeDetail: View {
Text(String(node.num)).font(.headline).foregroundColor(.gray)
}
}.padding()
if node.positions != nil && node.positions!.count > 0 {
Divider()
HStack {
Image(systemName: "map.circle.fill").font(.title).foregroundColor(.accentColor)
Text("Position History (\(node.positions?.count ?? 0) Points)").font(.title2)
}
.padding()
Divider()
ForEach(node.positions!.array as! [PositionEntity], id: \.self) { (mappin: PositionEntity) in
VStack {
HStack {
Image(systemName: "mappin.and.ellipse").foregroundColor(.accentColor) //.font(.subheadline)
Text("Lat/Long:").font(.caption)
Text("\(String(mappin.latitude ?? 0)) \(String(mappin.longitude ?? 0))")
.foregroundColor(.gray)
.font(.caption)
Text("Altitude:")
.font(.caption)
Text("\(String(mappin.altitude))m")
.foregroundColor(.gray)
.font(.caption)
}
HStack {
Image(systemName: "clock.badge.checkmark.fill")
.font(.subheadline)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("Time:")
.font(.caption)
Text("\(mappin.time!, style: .date) \(mappin.time!, style: .time)")
.foregroundColor(.gray)
.font(.caption)
Divider()
Text("Battery").font(.caption).fixedSize()
Text(String(mappin.batteryLevel) + "%")
.font(.caption)
.foregroundColor(.gray)
.symbolRenderingMode(.hierarchical)
}
}
.padding([.top, .bottom])
Divider()
}
}
}
}.navigationTitle(node.user!.longName ?? "Unknown")
.navigationBarTitleDisplayMode(.inline)
@ -174,16 +223,19 @@ struct NodeDetail: View {
self.bleManager.context = context
})
}.ignoresSafeArea(.all, edges: [.leading, .trailing])
}
.ignoresSafeArea(.all, edges: [.leading, .trailing])
}
}
struct NodeInfoEntityDetail_Previews: PreviewProvider {
static let bleManager = BLEManager()
static var previews: some View {
Group {
//NodeInfoEntityDetail(node: node)
//NodeDetail(node: node)
}
}
}

View file

@ -19,7 +19,12 @@ struct NodeList: View {
sortDescriptors: [NSSortDescriptor(key: "lastHeard", ascending: false)],
animation: .default)
private var nodes: FetchedResults<NodeInfoEntity>
private var nodes: FetchedResults<NodeInfoEntity>
//@FetchRequest(
// sortDescriptors: [NSSortDescriptor(key: "lastHeard", ascending: false)],
// animation: .default) var nodes: FetchedResults<NodeInfoEntity>
@State private var selection: String?
@ -113,7 +118,7 @@ struct NodeList: View {
}
.navigationTitle("All Nodes")
.onAppear{
//self.nodes.returnsObjectsAsFaults = false
self.bleManager.context = context
if UIDevice.current.userInterfaceIdiom == .pad {