Make current location nilable, remove log spam

This commit is contained in:
Garth Vander Houwen 2025-09-26 19:17:52 -07:00
parent fe17333ac8
commit 90dd5b2141
7 changed files with 91 additions and 129 deletions

View file

@ -15976,22 +15976,6 @@
}
}
},
"Generated from your private key and sent to other nodes on the mesh so they can compute a shared secret key." : {
"localizations" : {
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "秘密キーから生成され、メッシュ上の他のノードに送信されて、共有秘密キーの計算を可能にします。"
}
},
"sr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Генерисано из твог приватног кључа и послато другим чворовима на мрежи како би им омогућило да израчунају заједнички тајни кључ.\n"
}
}
}
},
"Get custom waterproof solar and detection sensor router nodes, aluminium desktop nodes and rugged handsets." : {
"localizations" : {
"it" : {
@ -42335,6 +42319,9 @@
}
}
}
},
"Your public key is generated from your private key and sent to other nodes on the mesh so they can compute a shared secret key with you." : {
},
"Your region has a %lld%% duty cycle. MQTT is not advised when you are duty cycle restricted, the extra traffic will quickly overwhelm your LoRa mesh." : {
"localizations" : {
@ -42428,4 +42415,4 @@
}
},
"version" : "1.1"
}
}

View file

@ -21,27 +21,27 @@ extension PositionEntity {
request.returnsDistinctResults = true
request.sortDescriptors = [NSSortDescriptor(key: "time", ascending: false)]
let positionPredicate = NSPredicate(format: "nodePosition != nil && (nodePosition.user.shortName != nil || nodePosition.user.shortName != '') && latest == true")
let pointOfInterest = LocationsHandler.currentLocation
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
let d: Double = UserDefaults.meshMapDistance * 1.1
let r: Double = 6371009
let meanLatitidue = pointOfInterest.latitude * .pi / 180
let deltaLatitude = d / r * 180 / .pi
let deltaLongitude = d / (r * cos(meanLatitidue)) * 180 / .pi
let minLatitude: Double = pointOfInterest.latitude - deltaLatitude
let maxLatitude: Double = pointOfInterest.latitude + deltaLatitude
let minLongitude: Double = pointOfInterest.longitude - deltaLongitude
let maxLongitude: Double = pointOfInterest.longitude + deltaLongitude
let distancePredicate = NSPredicate(format: "(%lf <= (longitudeI / 1e7)) AND ((longitudeI / 1e7) <= %lf) AND (%lf <= (latitudeI / 1e7)) AND ((latitudeI / 1e7) <= %lf)", minLongitude, maxLongitude, minLatitude, maxLatitude)
request.predicate = NSCompoundPredicate(type: .and, subpredicates: [positionPredicate, distancePredicate])
} else {
request.predicate = positionPredicate
if let pointOfInterest = LocationsHandler.currentLocation {
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
let d: Double = UserDefaults.meshMapDistance * 1.1
let r: Double = 6371009
let meanLatitidue = pointOfInterest.latitude * .pi / 180
let deltaLatitude = d / r * 180 / .pi
let deltaLongitude = d / (r * cos(meanLatitidue)) * 180 / .pi
let minLatitude: Double = pointOfInterest.latitude - deltaLatitude
let maxLatitude: Double = pointOfInterest.latitude + deltaLatitude
let minLongitude: Double = pointOfInterest.longitude - deltaLongitude
let maxLongitude: Double = pointOfInterest.longitude + deltaLongitude
let distancePredicate = NSPredicate(format: "(%lf <= (longitudeI / 1e7)) AND ((longitudeI / 1e7) <= %lf) AND (%lf <= (latitudeI / 1e7)) AND ((latitudeI / 1e7) <= %lf)", minLongitude, maxLongitude, minLatitude, maxLatitude)
request.predicate = NSCompoundPredicate(type: .and, subpredicates: [positionPredicate, distancePredicate])
} else {
request.predicate = positionPredicate
}
}
return request
}
var latitude: Double? {
let d = Double(latitudeI)

View file

@ -220,50 +220,18 @@ import OSLog
// If not recording, only keep the latest location.
locationsArray = [location]
}
// Store the last known location in UserDefaults for persistence.
UserDefaults.standard.set(location.coordinate.latitude, forKey: "lastKnownLatitude")
UserDefaults.standard.set(location.coordinate.longitude, forKey: "lastKnownLongitude")
UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: "lastKnownLocationTimestamp")
return true
}
// Default location (Apple Park) used as a fallback.
// nonisolated because it is never mutated
nonisolated static let DefaultLocation = CLLocationCoordinate2D(latitude: 37.3346, longitude: -122.0090)
/// Provides the current location, falling back to last known or a default if necessary.
static var currentLocation: CLLocationCoordinate2D {
static var currentLocation: CLLocationCoordinate2D? {
// Attempt to get the most recent location from the manager.
if let location = shared.manager.location {
return location.coordinate
} else {
// If manager.location is nil, check authorization status and potentially request.
let status = shared.manager.authorizationStatus
switch status {
case .notDetermined:
Logger.services.info("📍 [App] Location permission not determined, requesting authorization (WhenInUse)")
// Requesting WhenInUse authorization here. For "Always" authorization,
// `requestLocationAlwaysPermissions()` should be called explicitly,
// typically from a user action or app setup.
shared.manager.requestWhenInUseAuthorization()
case .denied, .restricted:
Logger.services.warning("📍 [App] Location access denied or restricted. Please enable location services in Settings to get accurate positioning!")
// Requesting WhenInUse authorization again, though user interaction is needed for denied/restricted.
shared.manager.requestWhenInUseAuthorization()
default:
break // For .authorizedAlways, .authorizedWhenInUse, .limited
}
// Fallback 1: Last known location from UserDefaults if it's recent (within 4 hours).
if let lat = UserDefaults.standard.object(forKey: "lastKnownLatitude") as? Double,
let lon = UserDefaults.standard.object(forKey: "lastKnownLongitude") as? Double,
let timestamp = UserDefaults.standard.object(forKey: "lastKnownLocationTimestamp") as? Double,
lat >= -90 && lat <= 90, // Validate latitude
lon >= -180 && lon <= 180, // Validate longitude
Date().timeIntervalSince1970 - timestamp <= 14_400 { // 4 hours in seconds
Logger.services.info("📍 [App] Falling back to last known location (age: \(Int(Date().timeIntervalSince1970 - timestamp)) seconds)")
return CLLocationCoordinate2D(latitude: lat, longitude: lon)
}
// Fallback 2: Default location if no other location is available.
Logger.services.warning("📍 [App] No Location and no last known location, check your location settings. Falling back to default location.")
return DefaultLocation
return nil
}
}
/// Estimates the number of satellites in view based on horizontal and vertical accuracy.

View file

@ -211,9 +211,12 @@ struct NodeWeatherForecast {
struct NodeWeatherForecastView_Previews: PreviewProvider {
static var previews: some View {
NodeWeatherForecastView(location: CLLocation(latitude: LocationsHandler.currentLocation.latitude, longitude: LocationsHandler.currentLocation.longitude) )
.aspectRatio(2, contentMode: .fit)
.padding()
.previewLayout(.sizeThatFits)
if let cl = LocationsHandler.currentLocation {
NodeWeatherForecastView(location: CLLocation(latitude: cl.latitude, longitude: cl.longitude) )
.aspectRatio(2, contentMode: .fit)
.padding()
.previewLayout(.sizeThatFits)
}
}
}

View file

@ -290,19 +290,20 @@ fileprivate extension NodeFilterParameters {
}
// Distance
if distanceFilter {
let pointOfInterest = LocationsHandler.currentLocation
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
let d: Double = maxDistance * 1.1
let r: Double = 6371009
let meanLatitidue = pointOfInterest.latitude * .pi / 180
let deltaLatitude = d / r * 180 / .pi
let deltaLongitude = d / (r * cos(meanLatitidue)) * 180 / .pi
let minLatitude: Double = pointOfInterest.latitude - deltaLatitude
let maxLatitude: Double = pointOfInterest.latitude + deltaLatitude
let minLongitude: Double = pointOfInterest.longitude - deltaLongitude
let maxLongitude: Double = pointOfInterest.longitude + deltaLongitude
let distancePredicate = NSPredicate(format: "(SUBQUERY(userNode.positions, $position, $position.latest == TRUE && (%lf <= ($position.longitudeI / 1e7)) AND (($position.longitudeI / 1e7) <= %lf) AND (%lf <= ($position.latitudeI / 1e7)) AND (($position.latitudeI / 1e7) <= %lf))).@count > 0", minLongitude, maxLongitude, minLatitude, maxLatitude)
predicates.append(distancePredicate)
if let pointOfInterest = LocationsHandler.currentLocation {
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
let d: Double = maxDistance * 1.1
let r: Double = 6371009
let meanLatitidue = pointOfInterest.latitude * .pi / 180
let deltaLatitude = d / r * 180 / .pi
let deltaLongitude = d / (r * cos(meanLatitidue)) * 180 / .pi
let minLatitude: Double = pointOfInterest.latitude - deltaLatitude
let maxLatitude: Double = pointOfInterest.latitude + deltaLatitude
let minLongitude: Double = pointOfInterest.longitude - deltaLongitude
let maxLongitude: Double = pointOfInterest.longitude + deltaLongitude
let distancePredicate = NSPredicate(format: "(SUBQUERY(userNode.positions, $position, $position.latest == TRUE && (%lf <= ($position.longitudeI / 1e7)) AND (($position.longitudeI / 1e7) <= %lf) AND (%lf <= ($position.latitudeI / 1e7)) AND (($position.latitudeI / 1e7) <= %lf))).@count > 0", minLongitude, maxLongitude, minLatitude, maxLatitude)
predicates.append(distancePredicate)
}
}
}
// Always apply unmessagable and connected node filters

View file

@ -40,21 +40,21 @@ struct WaypointForm: View {
.font(.largeTitle)
Divider()
Form {
let distance = CLLocation(latitude: LocationsHandler.currentLocation.latitude, longitude: LocationsHandler.currentLocation.longitude).distance(from: CLLocation(latitude: waypoint.coordinate.latitude, longitude: waypoint.coordinate.longitude ))
Section(header: Text("Coordinate") ) {
HStack {
Text("Location:")
.foregroundColor(.secondary)
Text("\(String(format: "%.5f", waypoint.coordinate.latitude) + "," + String(format: "%.5f", waypoint.coordinate.longitude))")
.textSelection(.enabled)
.foregroundColor(.secondary)
.font(.caption)
}
if let cl = LocationsHandler.currentLocation {
let distance = CLLocation(latitude: cl.latitude, longitude: cl.longitude).distance(from: CLLocation(latitude: waypoint.coordinate.latitude, longitude: waypoint.coordinate.longitude ))
Section(header: Text("Coordinate") ) {
HStack {
Text("Location:")
.foregroundColor(.secondary)
Text("\(String(format: "%.5f", waypoint.coordinate.latitude) + "," + String(format: "%.5f", waypoint.coordinate.longitude))")
.textSelection(.enabled)
.foregroundColor(.secondary)
.font(.caption)
}
Button {
let currentLoc = LocationsHandler.currentLocation
waypoint.coordinate.longitude = currentLoc.longitude
waypoint.coordinate.latitude = currentLoc.latitude
waypoint.coordinate.longitude = cl.longitude
waypoint.coordinate.latitude = cl.latitude
} label: {
HStack {
Text("Use my Location")
@ -62,10 +62,11 @@ struct WaypointForm: View {
}
}
.accessibilityLabel("Set to current location")
HStack {
if waypoint.coordinate.latitude != 0 && waypoint.coordinate.longitude != 0 {
DistanceText(meters: distance)
.foregroundColor(Color.gray)
HStack {
if waypoint.coordinate.latitude != 0 && waypoint.coordinate.longitude != 0 {
DistanceText(meters: distance)
.foregroundColor(Color.gray)
}
}
}
}
@ -374,17 +375,19 @@ struct WaypointForm: View {
.padding(.bottom, 5)
}
/// Distance
if LocationsHandler.currentLocation.distance(from: LocationsHandler.DefaultLocation) > 0.0 {
let metersAway = waypoint.coordinate.distance(from: LocationsHandler.currentLocation)
Label {
Text("Distance".localized + ": \(distanceFormatter.string(fromDistance: Double(metersAway)))")
.foregroundColor(.primary)
} icon: {
Image(systemName: "lines.measurement.horizontal")
.symbolRenderingMode(.hierarchical)
.frame(width: 35)
if let cl = LocationsHandler.currentLocation {
if cl.distance(from: cl) > 0.0 {
let metersAway = waypoint.coordinate.distance(from: cl)
Label {
Text("Distance".localized + ": \(distanceFormatter.string(fromDistance: Double(metersAway)))")
.foregroundColor(.primary)
} icon: {
Image(systemName: "lines.measurement.horizontal")
.symbolRenderingMode(.hierarchical)
.frame(width: 35)
}
.padding(.bottom, 5)
}
.padding(.bottom, 5)
}
}
.padding(.top)

View file

@ -341,23 +341,23 @@ fileprivate extension NodeFilterParameters {
// Distance filter
if distanceFilter {
let pointOfInterest = LocationsHandler.currentLocation
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
let d: Double = maxDistance * 1.1
let r: Double = 6371009
let meanLatitidue = pointOfInterest.latitude * .pi / 180
let deltaLatitude = d / r * 180 / .pi
let deltaLongitude = d / (r * cos(meanLatitidue)) * 180 / .pi
let minLatitude: Double = pointOfInterest.latitude - deltaLatitude
let maxLatitude: Double = pointOfInterest.latitude + deltaLatitude
let minLongitude: Double = pointOfInterest.longitude - deltaLongitude
let maxLongitude: Double = pointOfInterest.longitude + deltaLongitude
let distancePredicate = NSPredicate(format: "(SUBQUERY(positions, $position, $position.latest == TRUE && (%lf <= ($position.longitudeI / 1e7)) AND (($position.longitudeI / 1e7) <= %lf) AND (%lf <= ($position.latitudeI / 1e7)) AND (($position.latitudeI / 1e7) <= %lf))).@count > 0", minLongitude, maxLongitude, minLatitude, maxLatitude)
predicates.append(distancePredicate)
if let pointOfInterest = LocationsHandler.currentLocation {
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
let d: Double = maxDistance * 1.1
let r: Double = 6371009
let meanLatitidue = pointOfInterest.latitude * .pi / 180
let deltaLatitude = d / r * 180 / .pi
let deltaLongitude = d / (r * cos(meanLatitidue)) * 180 / .pi
let minLatitude: Double = pointOfInterest.latitude - deltaLatitude
let maxLatitude: Double = pointOfInterest.latitude + deltaLatitude
let minLongitude: Double = pointOfInterest.longitude - deltaLongitude
let maxLongitude: Double = pointOfInterest.longitude + deltaLongitude
let distancePredicate = NSPredicate(format: "(SUBQUERY(positions, $position, $position.latest == TRUE && (%lf <= ($position.longitudeI / 1e7)) AND (($position.longitudeI / 1e7) <= %lf) AND (%lf <= ($position.latitudeI / 1e7)) AND (($position.latitudeI / 1e7) <= %lf))).@count > 0", minLongitude, maxLongitude, minLatitude, maxLatitude)
predicates.append(distancePredicate)
}
}
}
return predicates.isEmpty ? nil : NSCompoundPredicate(type: .and, subpredicates: predicates)
}
}