Make BLEManager handle Position packets that arrive under the PositionApp port number

This commit is contained in:
Joshua Pirihi 2022-01-18 17:09:23 +13:00
parent 38977db1bf
commit 21f2e0fbf4
5 changed files with 117 additions and 26 deletions

View file

@ -811,6 +811,31 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
}
fetchedNode[0].snr = decodedInfo.packet.rxSnr
if let positionMessage = try? Position(serializedData: decodedInfo.packet.decoded.payload) {
let position = PositionEntity(context: context!)
position.latitudeI = positionMessage.latitudeI
position.longitudeI = positionMessage.longitudeI
position.altitude = positionMessage.altitude
position.batteryLevel = positionMessage.batteryLevel
position.time = Date(timeIntervalSince1970: TimeInterval(Int64(positionMessage.time)))
let mutablePositions = fetchedNode[0].positions!.mutableCopy() as! NSMutableOrderedSet
mutablePositions.add(position)
print("💾 Recieved a Position Packet")
if position.coordinate == nil {
var newPostions = [PositionEntity]()
newPostions.append(position)
fetchedNode[0].positions? = NSOrderedSet(array: newPostions)
} else {
fetchedNode[0].positions = mutablePositions.copy() as? NSOrderedSet
}
}
} else {
return

View file

@ -9,12 +9,43 @@ import UIKit
import MapKit
import SQLite
extension MKMapRect {
init(coordinates: [CLLocationCoordinate2D]) {
self = MKMapRect()
var coordinates = coordinates
if !coordinates.isEmpty {
let first = coordinates.removeFirst()
var top = first.latitude
var bottom = first.latitude
var left = first.longitude
var right = first.longitude
coordinates.forEach { coordinate in
top = max(top, coordinate.latitude)
bottom = min(bottom, coordinate.latitude)
left = min(left, coordinate.longitude)
right = max(right, coordinate.longitude)
}
let topLeft = MKMapPoint(CLLocationCoordinate2D(latitude:top, longitude:left))
let bottomRight = MKMapPoint(CLLocationCoordinate2D(latitude:bottom, longitude:right))
self = MKMapRect(x:topLeft.x, y:topLeft.y,
width:bottomRight.x - topLeft.x, height:bottomRight.y - topLeft.y)
}
}
}
class LocalMBTileOverlay: MKTileOverlay {
var path: String!
var mb: Connection!
private var _boundingMapRect: MKMapRect!
override var boundingMapRect: MKMapRect {
get {
return _boundingMapRect
}
}
init(mbTilePath path: String) {
super.init(urlTemplate: nil)
@ -35,19 +66,29 @@ class LocalMBTileOverlay: MKTileOverlay {
self.isGeometryFlipped = true
//let boundingBoxString = try mb.pluck(metadata.select(value).filter(name == "bounds"))
//let boundCoords = boundingBoxString![value].split(separator: ",")
//self.boundingMapRect = MKMapRect(coordinates: [CLLocationCoordinate2D(latitude: Double(boundCoords[0]) ?? 0, longitude: Double(boundCoords[1]) ?? 0), CLLocationCoordinate2D(latitude: Double(boundCoords[2]) ?? 0, longitude: Double(boundCoords[3]) ?? 0)])
let boundingBoxString = try mb.pluck(metadata.select(value).filter(name == "bounds"))
let boundCoords = boundingBoxString![value].split(separator: ",")
let coords = [
CLLocationCoordinate2D(latitude: Double(boundCoords[1]) ?? 0,
longitude: Double(boundCoords[0]) ?? 0),
CLLocationCoordinate2D(latitude: Double(boundCoords[3]) ?? 0,
longitude: Double(boundCoords[2]) ?? 0)
]
self._boundingMapRect = MKMapRect(coordinates: coords)
} catch {
//print("MAP ERROR \(error)")
}
}
override func loadTile(at path: MKTileOverlayPath) async throws -> Data {
override func loadTile(at path: MKTileOverlayPath, result: @escaping (Data?, Error?) -> Void) {
//}
//override func loadTile(at path: MKTileOverlayPath) async throws -> Data {
let tileX = Int64(path.x)
let tileY = Int64(path.y)
@ -58,14 +99,18 @@ class LocalMBTileOverlay: MKTileOverlay {
let tileColumn = Expression<Int64>("tile_column")
let tileRow = Expression<Int64>("tile_row")
if let dataQuery = try self.mb.pluck(Table("tiles").select(tileData).filter(zoomLevel == tileZ).filter(tileColumn == tileX).filter(tileRow == tileY)) {
if let dataQuery = try? self.mb.pluck(Table("tiles").select(tileData).filter(zoomLevel == tileZ).filter(tileColumn == tileX).filter(tileRow == tileY)) {
let data = Data(bytes: dataQuery[tileData].bytes, count: dataQuery[tileData].bytes.count)//dataQuery![tileData].bytes
return data
//return data
result(data, nil)
} else {
return Data()
print("💥 No tile here: x:\(tileX) y:\(tileY) z:\(tileZ)")
//return Data()
let error = NSError(domain: "LocalMBTileOverlay", code: 1, userInfo: ["reason": "no_tile"])
result(nil, error)
}
}

View file

@ -11,9 +11,9 @@ import CoreData
#if canImport(MapKit) && canImport(UIKit)
public struct MapView: UIViewRepresentable {
//@Environment(\.managedObjectContext) var context
@Environment(\.managedObjectContext) var context
var context: NSManagedObjectContext?
//var context: NSManagedObjectContext?
//@Binding private var region: MKCoordinateRegion
@ -40,8 +40,11 @@ public struct MapView: UIViewRepresentable {
private var overlays: [Overlay]
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "lastHeard", ascending: false)], animation: .default)
private var locationNodes: FetchedResults<NodeInfoEntity>
//@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "lastHeard", ascending: false)], animation: .default)
// private var locationNodes: FetchedResults<NodeInfoEntity>
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "time", ascending: false)], animation: .default)
private var positions: FetchedResults<PositionEntity>
//@State private var locationNodes: [NodeInfoEntity]
@ -62,8 +65,8 @@ public struct MapView: UIViewRepresentable {
userLocation: Binding<CLLocationCoordinate2D?> = .constant(nil),
//annotations: [MKPointAnnotation] = [],
//locationNodes: [NodeInfoEntity] = [],
overlays: [Overlay] = [],
context: NSManagedObjectContext? = nil
overlays: [Overlay] = []
//context: NSManagedObjectContext? = nil
) {
//self._region = region
@ -111,7 +114,7 @@ public struct MapView: UIViewRepresentable {
mapView.delegate = context.coordinator
mapView.register(PositionAnnotationView.self, forAnnotationViewWithReuseIdentifier: NSStringFromClass(PositionAnnotationView.self))
Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in
/*Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in
for node in self.locationNodes {
// try and get the last position
if (node.positions?.count ?? 0) > 0 && (node.positions!.lastObject as! PositionEntity).coordinate != nil {
@ -123,7 +126,7 @@ public struct MapView: UIViewRepresentable {
mapView.addAnnotation(annotation)
}
}
}
}*/
return mapView
}
@ -139,18 +142,20 @@ public struct MapView: UIViewRepresentable {
mapView.removeOverlays(mapView.overlays)
if let customMapOverlay = self.customMapOverlay {
let overlay = LocalMBTileOverlay(mbTilePath: Bundle.main.path(forResource: "offline_map", ofType: "mbtiles")!)
overlay.canReplaceMapContent = false//customMapOverlay.canReplaceMapContent
mapView.addOverlay(overlay)
if let tilePath = Bundle.main.path(forResource: "offline_map", ofType: "mbtiles") {
let overlay = LocalMBTileOverlay(mbTilePath: tilePath)
overlay.canReplaceMapContent = false//customMapOverlay.canReplaceMapContent
mapView.addOverlay(overlay)
}
}
DispatchQueue.main.async {
self.presentCustomMapOverlayHash = self.customMapOverlay
}
}
if mapView.overlays.count != (self.overlays.count + (self.customMapOverlay == nil ? 0 : 1)) {
/*if mapView.overlays.count != (self.overlays.count + (self.customMapOverlay == nil ? 0 : 1)) {
context.coordinator.overlays = self.overlays
mapView.overlays.forEach { overlay in
if !(overlay is MKTileOverlay) {
@ -158,7 +163,7 @@ public struct MapView: UIViewRepresentable {
}
}
mapView.addOverlays(self.overlays.map { overlay in overlay.shape })
}
}*/
if mapView.mapType != self.mapType {
mapView.mapType = self.mapType
@ -210,7 +215,7 @@ public struct MapView: UIViewRepresentable {
shouldMoveRegion = true
}
for node in self.locationNodes {
/*for node in self.locationNodes {
// try and get the last position
if (node.positions?.count ?? 0) > 0 && (node.positions!.lastObject as! PositionEntity).coordinate != nil {
let annotation = PositionAnnotation()
@ -220,6 +225,22 @@ public struct MapView: UIViewRepresentable {
mapView.addAnnotation(annotation)
}
}*/
var displayedNodes: [Int64] = []
for position in self.positions {
if position.nodePosition == nil || displayedNodes.contains(position.nodePosition!.num) || position.coordinate == nil {
continue
}
let annotation = PositionAnnotation()
annotation.coordinate = position.coordinate!
annotation.title = position.nodePosition!.user?.longName ?? "Unknown"
annotation.shortName = position.nodePosition!.user?.shortName?.uppercased() ?? "???"
mapView.addAnnotation(annotation)
displayedNodes.append(position.nodePosition!.num)
}
if shouldMoveRegion {

View file

@ -108,8 +108,8 @@ struct NodeMap: View {
userLocation: self.$userLocation,
//annotations: self.annotations,
//locationNodes: self.locationNodes.map({ nodeinfo in return nodeinfo }),
overlays: self.overlays,
context: self.context
overlays: self.overlays
//context: self.context
)
.frame(maxHeight: .infinity)