diff --git a/android/src/main/java/com/dumon/plugin/geolocation/DumonGeolocation.kt b/android/src/main/java/com/dumon/plugin/geolocation/DumonGeolocation.kt index f63d597..3db143e 100644 --- a/android/src/main/java/com/dumon/plugin/geolocation/DumonGeolocation.kt +++ b/android/src/main/java/com/dumon/plugin/geolocation/DumonGeolocation.kt @@ -72,6 +72,8 @@ class DumonGeolocation : Plugin() { private val emitIntervalMs: Long = 1000L // hard debounce // private val emitIntervalMs: Long = 500L + private var motionState: String = "idle" // 'idle', 'driving', 'mocked' + override fun load() { gpsManager = GpsStatusManager( context, @@ -245,38 +247,95 @@ class DumonGeolocation : Plugin() { call.resolve(result) } +// private fun emitPositionUpdate() { +// /*val now = System.currentTimeMillis() +// if (now - lastEmitTimestamp < emitIntervalMs) return +// lastEmitTimestamp = now +// notifyListeners("onPositionUpdate", buildPositionData())*/ +// +// val now = System.currentTimeMillis() +// if (now - lastEmitTimestamp < emitIntervalMs) return +// +// val distance = calculateDistance(latestLatitude, latestLongitude, prevLatitude, prevLongitude) +// val isSignificantChange = distance >= significantChangeThreshold +// val speedChanged = abs((latestImu?.speed ?: 0f) - prevSpeed) > speedChangeThreshold +// val directionChanged = abs((latestImu?.directionRad ?: 0f) - prevDirection) > directionChangeThreshold +// +// if (isSignificantChange || speedChanged || directionChanged) { +// prevLatitude = latestLatitude +// prevLongitude = latestLongitude +// prevSpeed = latestImu?.speed ?: 0f +// prevDirection = latestImu?.directionRad ?: 0f +// lastEmitTimestamp = now +// +// notifyListeners("onPositionUpdate", buildPositionData()) +// } +// +// // Fallback prediksi jika tidak ada GNSS update > 1.5 detik +// if (System.currentTimeMillis() - latestTimestamp > 1500 && latestImu != null) { +// val (predLat, predLon) = fusionManager?.predictForwardPosition(1.0) ?: return +// latestLatitude = predLat +// latestLongitude = predLon +// latestAccuracy = 10.0 +// latestSource = "PREDICTED" +// latestTimestamp = System.currentTimeMillis() +// +// Log.d("DUMON_PREDICTION", "Predicted position: $predLat, $predLon") +// notifyListeners("onPositionUpdate", buildPositionData()) +// } +// } private fun emitPositionUpdate() { - /*val now = System.currentTimeMillis() - if (now - lastEmitTimestamp < emitIntervalMs) return - lastEmitTimestamp = now - notifyListeners("onPositionUpdate", buildPositionData())*/ - val now = System.currentTimeMillis() if (now - lastEmitTimestamp < emitIntervalMs) return val distance = calculateDistance(latestLatitude, latestLongitude, prevLatitude, prevLongitude) - val isSignificantChange = distance >= significantChangeThreshold - val speedChanged = abs((latestImu?.speed ?: 0f) - prevSpeed) > speedChangeThreshold - val directionChanged = abs((latestImu?.directionRad ?: 0f) - prevDirection) > directionChangeThreshold + val speedNow = latestImu?.speed ?: 0f + val directionNow = latestImu?.directionRad ?: 0f - if (isSignificantChange || speedChanged || directionChanged) { + val isSignificantChange = distance >= significantChangeThreshold + val speedChanged = abs(speedNow - prevSpeed) > speedChangeThreshold + val directionChanged = abs(directionNow - prevDirection) > directionChangeThreshold + + // Tentukan motion state + motionState = when { + isMockedLocation -> "mocked" + speedNow > 1.0f -> "driving" + else -> "idle" + } + + val shouldEmit = isSignificantChange || speedChanged || directionChanged + + if (shouldEmit) { prevLatitude = latestLatitude prevLongitude = latestLongitude - prevSpeed = latestImu?.speed ?: 0f - prevDirection = latestImu?.directionRad ?: 0f + prevSpeed = speedNow + prevDirection = directionNow lastEmitTimestamp = now notifyListeners("onPositionUpdate", buildPositionData()) + return } - // Fallback prediksi jika tidak ada GNSS update > 1.5 detik - if (System.currentTimeMillis() - latestTimestamp > 1500 && latestImu != null) { - val (predLat, predLon) = fusionManager?.predictForwardPosition(1.0) ?: return + maybeEmitPredictedPosition(now, speedNow) + } + + private fun maybeEmitPredictedPosition(now: Long, speedNow: Float) { + val timeSinceFix = now - latestTimestamp + + val shouldPredict = (motionState == "driving") && timeSinceFix > 3000 + + if (!shouldPredict) return + + val (predLat, predLon) = fusionManager?.predictForwardPosition(1.5) ?: return + val predictedDistance = calculateDistance(latestLatitude, latestLongitude, predLat, predLon) + + if (predictedDistance > significantChangeThreshold) { latestLatitude = predLat latestLongitude = predLon latestAccuracy = 10.0 latestSource = "PREDICTED" - latestTimestamp = System.currentTimeMillis() + latestTimestamp = now + lastEmitTimestamp = now Log.d("DUMON_PREDICTION", "Predicted position: $predLat, $predLon") notifyListeners("onPositionUpdate", buildPositionData())