feat: implement two-location speed calculation when native speed unavailable

This commit is contained in:
fiatcode 2026-05-02 16:22:02 +07:00
parent eca39e542c
commit c9e49c6cbd
No known key found for this signature in database

View file

@ -13,7 +13,9 @@ import android.net.ConnectivityManager
import android.location.Location
import android.os.Binder
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.os.PowerManager
import androidx.core.app.NotificationCompat
import dev.fiatcode.tracpulse.BridgeModule
@ -57,6 +59,9 @@ class LocationTrackingService : Service() {
private var bypassFilterOnce = false
private var currentConfig: TrackingConfig? = null
private var pendingSpeedLocation: Location? = null
private var speedRequestPending = false
private val SPEED_CALC_DELAY_MS = 2500L
inner class LocalBinder : Binder() {
fun getService(): LocationTrackingService = this@LocationTrackingService
@ -143,6 +148,8 @@ class LocationTrackingService : Service() {
isTracking = true
distanceFilterProcessor.reset()
pendingSpeedLocation = null
speedRequestPending = false
prefs.edit().putBoolean("tracking_active", true).apply()
Log.d(TAG, "startTracking: set tracking_active=true")
@ -226,15 +233,22 @@ class LocationTrackingService : Service() {
}
bypassFilterOnce = false
val nativeSpeed = if (location.hasSpeed()) location.speed else null
if (nativeSpeed == null || nativeSpeed <= 0) {
pendingSpeedLocation = location
requestLocationForSpeedCalculation()
}
val traccarLocation = TraccarLocation(
timestamp = location.time,
latitude = location.latitude,
longitude = location.longitude,
accuracy = if (location.hasAccuracy()) location.accuracy else null,
speed = if (location.hasSpeed()) location.speed else null,
speed = nativeSpeed,
heading = if (location.hasBearing()) location.bearing else null,
altitude = if (location.hasAltitude()) location.altitude else null,
isMoving = location.speed > 1.0f // Consider moving if speed > 1 m/s
isMoving = (nativeSpeed ?: 0f) > 1.0f
)
logEvent("LOCATION", "Lat: ${location.latitude}, Lon: ${location.longitude}, Speed: ${location.speed}")
@ -262,10 +276,12 @@ class LocationTrackingService : Service() {
apply()
}
if (isNetworkAvailable) {
sendLocationToServer(traccarLocation)
} else {
bufferLocation(traccarLocation)
if (nativeSpeed != null && nativeSpeed > 0) {
if (isNetworkAvailable) {
sendLocationToServer(traccarLocation)
} else {
bufferLocation(traccarLocation)
}
}
}
@ -276,6 +292,58 @@ class LocationTrackingService : Service() {
}
}
private fun requestLocationForSpeedCalculation() {
if (speedRequestPending) return
speedRequestPending = true
Handler(Looper.getMainLooper()).postDelayed({
fusedLocationProvider.getLastLocation { location ->
location?.let {
val calculatedSpeed = distanceFilterProcessor.getCalculatedSpeed(it)
onSpeedLocationReceived(it, calculatedSpeed)
}
speedRequestPending = false
pendingSpeedLocation = null
}
}, SPEED_CALC_DELAY_MS)
}
private fun onSpeedLocationReceived(location: Location, calculatedSpeed: Float?) {
val config = currentConfig ?: return
val finalSpeed = if (location.hasSpeed() && location.speed > 0) {
location.speed
} else {
calculatedSpeed
}
if (finalSpeed == null || finalSpeed <= 0) {
logEvent("SPEED_CALC", "Speed calculation failed - insufficient data")
return
}
val traccarLocation = TraccarLocation(
timestamp = location.time,
latitude = location.latitude,
longitude = location.longitude,
accuracy = if (location.hasAccuracy()) location.accuracy else null,
speed = finalSpeed,
heading = if (location.hasBearing()) location.bearing else null,
altitude = if (location.hasAltitude()) location.altitude else null,
isMoving = finalSpeed > 1.0f
)
logEvent("LOCATION", "Lat: ${location.latitude}, Lon: ${location.longitude}, Calc Speed: ${finalSpeed}")
updateNotificationSpeed(location, finalSpeed)
if (isNetworkAvailable) {
sendLocationToServer(traccarLocation)
} else {
bufferLocation(traccarLocation)
}
}
private fun sendLocationToServer(location: TraccarLocation) {
val config = currentConfig ?: return
val traccarConfig = TraccarConfig(
@ -407,6 +475,20 @@ class LocationTrackingService : Service() {
notificationManager.notify(NOTIFICATION_ID, notification)
}
private fun updateNotificationSpeed(location: Location, speed: Float) {
val content = buildString {
append("Lat: %.4f Lon: %.4f".format(location.latitude, location.longitude))
append("\nSpeed: %.0f km/h (calc)".format(speed * 3.6))
val time = java.text.SimpleDateFormat("HH:mm:ss", java.util.Locale.getDefault())
.format(java.util.Date(location.time))
append("\nLast: $time")
}
val notification = createNotification(content)
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager.notify(NOTIFICATION_ID, notification)
}
private fun acquireWakeLock() {
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(