mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Make BLEManager handle Position packets that arrive under the PositionApp port number
This commit is contained in:
parent
38977db1bf
commit
21f2e0fbf4
5 changed files with 117 additions and 26 deletions
Binary file not shown.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue