Add setting for user tracking mode

This commit is contained in:
Garth Vander Houwen 2023-02-24 21:14:08 -08:00
parent 57268576c4
commit b214b34d64
8 changed files with 117 additions and 47 deletions

View file

@ -39,7 +39,7 @@ enum CenteringMode: Int, CaseIterable, Identifiable {
case allAnnotations = 0
case allPositions = 1
case clientGps = 2
case phoneGps = 2
var id: Int { self.rawValue }
var description: String {
@ -49,8 +49,8 @@ enum CenteringMode: Int, CaseIterable, Identifiable {
return "All Annotations"// NSLocalizedString("default", comment: "Default Keyboard")
case .allPositions:
return "All Node Postions"// NSLocalizedString("ascii.capable", comment: "ASCII Capable Keyboard")
case .clientGps:
return "Client GPS"//NSLocalizedString("email.address", comment: "Email Address Keyboard")
case .phoneGps:
return "Phone GPS"//NSLocalizedString("email.address", comment: "Email Address Keyboard")
}
}
}
@ -105,6 +105,39 @@ enum MeshMapType: String, CaseIterable, Identifiable {
}
}
enum UserTrackingModes: Int, CaseIterable, Identifiable {
case none = 0
case follow = 1
case followWithHeading = 2
var id: Int { self.rawValue }
var description: String {
get {
switch self {
case .none:
return NSLocalizedString("map.usertrackingmode.none", comment: "None")
case .follow:
return NSLocalizedString("map.usertrackingmode.follow", comment: "Follow")
case .followWithHeading:
return NSLocalizedString("map.usertrackingmode.followwithheading", comment: "Follow with Heading")
}
}
}
func MKUserTrackingModeValue() -> MKUserTrackingMode {
switch self {
case .none:
return MKUserTrackingMode.none
case .follow:
return MKUserTrackingMode.follow
case .followWithHeading:
return MKUserTrackingMode.followWithHeading
}
}
}
enum LocationUpdateInterval: Int, CaseIterable, Identifiable {
case fiveSeconds = 5

View file

@ -16,6 +16,7 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
case routerClient = 3
case repeater = 4
case tracker = 5
case sensor = 6
var id: Int { self.rawValue }
var name: String {
@ -34,6 +35,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return "Repeater"
case .tracker:
return "Tracker"
case .sensor:
return "Sensor"
}
}
}
@ -53,6 +56,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return NSLocalizedString("device.role.repeater", comment: "Repeater - Mesh packets will prefer to be routed over this node. This role eliminates unnecessary overhead such as NodeInfo, DeviceTelemetry, and any other mesh packet, resulting in the device not appearing as part of the network. Please see Rebroadcast Mode for additional settings specific to this role.")
case .tracker:
return NSLocalizedString("device.role.tracker", comment: "Tracker - For use with devices intended as a GPS tracker. Position packets sent from this device will be higher priority, with position broadcasting every two minutes. Smart Position Broadcast will default to off.")
case .sensor:
return NSLocalizedString("device.role.sensor", comment: "Sensor - For use with remote telemetry sensors. Setting this role will turn on environment telemetry. Telemetry packets sent from this device will be higher priority, with telemetry broadcasting every 7 minutes")
}
}
}
@ -72,6 +77,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
return Config.DeviceConfig.Role.repeater
case .tracker:
return Config.DeviceConfig.Role.tracker
case .sensor:
return Config.DeviceConfig.Role.sensor
}
}
}

View file

@ -62,8 +62,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
self.lastConnectionError = ""
self.connectedVersion = "0.0.0"
super.init()
//centralManager = CBCentralManager(delegate: self, queue: nil)
centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionRestoreIdentifierKey: restoreKey])
centralManager = CBCentralManager(delegate: self, queue: nil)
//centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionRestoreIdentifierKey: restoreKey])
}
// MARK: Scanning for BLE Devices

View file

@ -62,7 +62,13 @@ class UserSettings: ObservableObject {
UserDefaults.standard.set(meshMapCustomTileServer, forKey: "meshMapCustomTileServer")
}
}
@Published var meshMapUserTrackingMode: Int {
didSet {
UserDefaults.standard.set(meshMapUserTrackingMode, forKey: "meshMapUserTrackingMode")
UserDefaults.standard.synchronize()
}
}
init() {
self.meshtasticUsername = UserDefaults.standard.object(forKey: "meshtasticusername") as? String ?? ""
@ -75,5 +81,6 @@ class UserSettings: ObservableObject {
self.meshMapCenteringMode = UserDefaults.standard.object(forKey: "meshMapCenteringMode") as? Int ?? 0
self.meshMapRecentering = UserDefaults.standard.object(forKey: "meshMapRecentering") as? Bool ?? true
self.meshMapCustomTileServer = UserDefaults.standard.string(forKey: "meshMapCustomTileServer") ?? ""
self.meshMapUserTrackingMode = UserDefaults.standard.object(forKey: "meshMapUserTrackingMode") as? Int ?? 0
}
}

View file

@ -23,6 +23,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
let centerOnPositionsOnly: Bool
@AppStorage("meshMapRecentering") private var recenter = false
@AppStorage("meshMapUserTrackingMode") private var userTrackingModeId = 0
// Offline Maps
//make this view dependent on the UserDefault that is updated when importing a new map file
@ -39,18 +40,18 @@ struct MapViewSwiftUI: UIViewRepresentable {
mapView.addAnnotations(waypoints)
// Logic to manage the map centering options
switch centeringMode {
case .allAnnotations:
mapView.addAnnotations(positions)
mapView.fitAllAnnotations()
case .allPositions:
mapView.fit(annotations: positions, andShow: true)
case .clientGps:
let span = MKCoordinateSpan(latitudeDelta: 0.003, longitudeDelta: 0.003)
let center = CLLocationCoordinate2D(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude)
let region = MKCoordinateRegion(center: center, span: span)
mapView.setRegion(region, animated: true)
mapView.addAnnotations(positions)
case .allAnnotations:
mapView.addAnnotations(positions)
mapView.fitAllAnnotations()
case .allPositions:
mapView.fit(annotations: positions, andShow: true)
case .phoneGps:
let span = MKCoordinateSpan(latitudeDelta: 0.003, longitudeDelta: 0.003)
let center = CLLocationCoordinate2D(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude)
let region = MKCoordinateRegion(center: center, span: span)
mapView.setRegion(region, animated: true)
mapView.addAnnotations(positions)
}
// Other MKMapView Settings
@ -116,34 +117,36 @@ struct MapViewSwiftUI: UIViewRepresentable {
DispatchQueue.main.async {
mapView.removeAnnotations(mapView.annotations)
mapView.addAnnotations(waypoints)
switch centeringMode {
case .allAnnotations:
mapView.addAnnotations(positions)
if recenter {
mapView.fitAllAnnotations()
}
case .allPositions:
if recenter {
mapView.fit(annotations: positions, andShow: true)
} else {
mapView.addAnnotations(positions)
}
case .clientGps:
mapView.addAnnotations(positions)
mapView.showsUserLocation = true
mapView.setUserTrackingMode(.followWithHeading, animated: true)
if recenter {
// create a 3D Camera
let mapCamera = MKMapCamera()
mapCamera.centerCoordinate = LocationHelper.currentLocation
mapCamera.pitch = 45
mapCamera.altitude = 500 // example altitude
mapCamera.heading = 45
mapView.setUserTrackingMode(UserTrackingModes(rawValue: userTrackingModeId )?.MKUserTrackingModeValue() ?? MKUserTrackingMode.none, animated: true)
// set the camera property
mapView.camera = mapCamera
mapView.centerCoordinate = LocationHelper.currentLocation
}
switch centeringMode {
case .allAnnotations:
mapView.addAnnotations(positions)
if recenter {
mapView.fitAllAnnotations()
}
case .allPositions:
if recenter {
mapView.fit(annotations: positions, andShow: true)
} else {
mapView.addAnnotations(positions)
}
case .phoneGps:
mapView.addAnnotations(positions)
mapView.showsUserLocation = true
if recenter {
// create a 3D Camera
// let mapCamera = MKMapCamera()
// mapCamera.centerCoordinate = LocationHelper.currentLocation
// mapCamera.pitch = 45
// mapCamera.altitude = 500 // example altitude
// mapCamera.heading = 45
// // set the camera property
// mapView.camera = mapCamera
mapView.centerCoordinate = LocationHelper.currentLocation
}
}
}
}
@ -176,7 +179,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
case _ as MKClusterAnnotation:
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "nodeGroup") as? MKMarkerAnnotationView ?? MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "WaypointGroup")
annotationView.markerTintColor = .brown//.systemRed
annotationView.markerTintColor = .brown
annotationView.displayPriority = .defaultLow
annotationView.tag = -1
return annotationView
@ -220,6 +223,9 @@ struct MapViewSwiftUI: UIViewRepresentable {
annotationView.glyphImage = UIImage(systemName: "wifi.router.fill")
} else if DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.tracker {
annotationView.glyphImage = UIImage(systemName: "location.viewfinder")
} else if DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.sensor {
annotationView.glyphImage = UIImage(systemName: "sensor")
}
let pf = PositionFlags(rawValue: Int(positionAnnotation.nodePosition?.metadata?.positionFlags ?? 3))

View file

@ -58,6 +58,15 @@ struct AppSettings: View {
.font(.caption)
.listRowSeparator(.visible)
}
Picker("map.usertrackingmode", selection: $userSettings.meshMapUserTrackingMode) {
ForEach(UserTrackingModes.allCases) { utm in
Text(utm.description)
}
}
.pickerStyle(DefaultPickerStyle())
Text("map.usertrackingmode.description")
.font(.caption)
.listRowSeparator(.visible)
}
Section(header: Text("map options")) {

View file

@ -140,6 +140,10 @@
"map.centering"="Centering";
"map.recentering"="Automatic Re-centering";
"map.type"="kartentyp";
"map.usertrackingmode"="User tracking mode";
"map.usertrackingmode.none"="None";
"map.usertrackingmode.follow"="Follow";
"map.usertrackingmode.followwithheading"="Follow with heading";
"mesh.log"="Mesh Log";
"mesh.log.bluetooth.config %@"="Bluetooth Konfiguration empfangen: %@";
"mesh.log.cannedmessage.config %@"="Canned Message module config received: %@";

View file

@ -130,7 +130,7 @@
"interval.eighteen.hours"="Eighteen Hours";
"interval.twentyfour.hours"="Twenty Four Hours";
"interval.thirtysix.hours"="Thirty Six Hours";
"interval.fortyeight.hours"="Forty Eight Hours Hours";
"interval.fortyeight.hours"="Forty Eight Hours";
"interval.seventytwo.hours"="Seventy Two Hours";
"keyboard.type"="Keyboard Type";
"logging"="Logging";
@ -140,6 +140,10 @@
"map.type"="Default Type";
"map.centering"="Centering Mode";
"map.recentering"="Automatic Re-centering";
"map.usertrackingmode"="User tracking mode";
"map.usertrackingmode.none"="None";
"map.usertrackingmode.follow"="Follow";
"map.usertrackingmode.followwithheading"="Follow with heading";
"mesh.log"="Mesh Log";
"mesh.log.bluetooth.config %@"="Bluetooth config received: %@";
"mesh.log.cannedmessage.config %@"="Canned Message module config received: %@";