updated 151025-01
This commit is contained in:
parent
438fb644cd
commit
c306b59b9e
13
README.md
13
README.md
@ -169,6 +169,11 @@ interface PositioningData {
|
|||||||
isMocked: boolean;
|
isMocked: boolean;
|
||||||
mode: 'normal' | 'driving';
|
mode: 'normal' | 'driving';
|
||||||
predicted?: boolean;
|
predicted?: boolean;
|
||||||
|
// opsional: detail asal speed
|
||||||
|
speedSource?: 'GNSS' | 'IMU' | 'DELTA' | 'NONE';
|
||||||
|
speedGnss?: number; // m/s dari Location.getSpeed bila tersedia & segar
|
||||||
|
speedImu?: number; // m/s dari IMU (heuristik internal)
|
||||||
|
speedDerived?: number; // m/s hasil Δpos/Δt (kasar)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -189,6 +194,14 @@ interface PermissionStatus {
|
|||||||
- Prediksi maju (dead‑reckoning) bersifat opsional dan nonaktif secara default. Aktifkan dengan `setOptions({ enableForwardPrediction: true, maxPredictionSeconds?: number })`.
|
- Prediksi maju (dead‑reckoning) bersifat opsional dan nonaktif secara default. Aktifkan dengan `setOptions({ enableForwardPrediction: true, maxPredictionSeconds?: number })`.
|
||||||
- Saat prediksi aktif, posisi dapat diproyeksikan pendek (<= `maxPredictionSeconds`) berdasarkan `speed` dan `directionRad` dari IMU, serta ditandai `predicted: true`. Nilai `source` tidak berubah.
|
- Saat prediksi aktif, posisi dapat diproyeksikan pendek (<= `maxPredictionSeconds`) berdasarkan `speed` dan `directionRad` dari IMU, serta ditandai `predicted: true`. Nilai `source` tidak berubah.
|
||||||
|
|
||||||
|
### Kebijakan `speed`
|
||||||
|
|
||||||
|
- Field `speed` kini dipilih dengan prioritas: GNSS > IMU > Δpos/Δt > 0.
|
||||||
|
- GNSS: dipakai jika `Location.hasSpeed()` dan usia fix ≤ ~3000 ms.
|
||||||
|
- IMU: fallback dari integrasi percepatan IMU (dibatasi ke 0..30 m/s, dengan smoothing & idle handling).
|
||||||
|
- Δpos/Δt: fallback terakhir, hanya bila selang waktu antar fix ≥ 3 s.
|
||||||
|
- Field tambahan opsional: `speedSource`, `speedGnss`, `speedImu`, `speedDerived` untuk transparansi asal nilai.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Detail Sensor (untuk pengembangan lanjutan)
|
## Detail Sensor (untuk pengembangan lanjutan)
|
||||||
|
|||||||
@ -60,6 +60,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
private var latestAccuracy = 999.0
|
private var latestAccuracy = 999.0
|
||||||
private var latestSource = "GNSS"
|
private var latestSource = "GNSS"
|
||||||
private var latestTimestamp: Long = 0L
|
private var latestTimestamp: Long = 0L
|
||||||
|
private var latestGnssSpeed: Float? = null
|
||||||
|
|
||||||
private var latestImu: ImuData? = null
|
private var latestImu: ImuData? = null
|
||||||
private var satelliteStatus: SatelliteStatus? = null
|
private var satelliteStatus: SatelliteStatus? = null
|
||||||
@ -72,6 +73,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
private var prevLongitude = 0.0
|
private var prevLongitude = 0.0
|
||||||
private var prevSpeed = 0f
|
private var prevSpeed = 0f
|
||||||
private var prevDirection = 0f
|
private var prevDirection = 0f
|
||||||
|
private var prevTimestamp: Long = 0L
|
||||||
// private val significantChangeThreshold = 0.00007 // ~7 meters
|
// private val significantChangeThreshold = 0.00007 // ~7 meters
|
||||||
private var significantChangeThreshold = 7.0 // ~7 meters
|
private var significantChangeThreshold = 7.0 // ~7 meters
|
||||||
private var speedChangeThreshold = 0.5f // m/s
|
private var speedChangeThreshold = 0.5f // m/s
|
||||||
@ -121,6 +123,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
latestSource = if (isMocked) "MOCK" else "GNSS"
|
latestSource = if (isMocked) "MOCK" else "GNSS"
|
||||||
isMockedLocation = isMocked
|
isMockedLocation = isMocked
|
||||||
latestTimestamp = location.time
|
latestTimestamp = location.time
|
||||||
|
latestGnssSpeed = if (location.hasSpeed()) location.speed else null
|
||||||
|
|
||||||
if (currentTrackingMode == GpsTrackingMode.DRIVING) {
|
if (currentTrackingMode == GpsTrackingMode.DRIVING) {
|
||||||
bufferedDrivingLocation = location
|
bufferedDrivingLocation = location
|
||||||
@ -160,6 +163,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
latestAccuracy = location.accuracy.toDouble()
|
latestAccuracy = location.accuracy.toDouble()
|
||||||
latestTimestamp = location.time
|
latestTimestamp = location.time
|
||||||
latestSource = if (isMockedLocation) "MOCK" else "GNSS"
|
latestSource = if (isMockedLocation) "MOCK" else "GNSS"
|
||||||
|
latestGnssSpeed = if (location.hasSpeed()) location.speed else null
|
||||||
emitPositionUpdate(forceEmit = true) // force emit in driving
|
emitPositionUpdate(forceEmit = true) // force emit in driving
|
||||||
}
|
}
|
||||||
drivingEmitHandler?.postDelayed(this, drivingEmitIntervalMs)
|
drivingEmitHandler?.postDelayed(this, drivingEmitIntervalMs)
|
||||||
@ -229,6 +233,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
latestSource = if (isMocked) "MOCK" else "GNSS"
|
latestSource = if (isMocked) "MOCK" else "GNSS"
|
||||||
isMockedLocation = isMocked
|
isMockedLocation = isMocked
|
||||||
latestTimestamp = location.time
|
latestTimestamp = location.time
|
||||||
|
latestGnssSpeed = if (location.hasSpeed()) location.speed else null
|
||||||
call.resolve(buildPositionData())
|
call.resolve(buildPositionData())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -653,6 +658,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
prevLongitude = latestLongitude
|
prevLongitude = latestLongitude
|
||||||
prevSpeed = speedNow
|
prevSpeed = speedNow
|
||||||
prevDirection = directionNow
|
prevDirection = directionNow
|
||||||
|
prevTimestamp = if (latestTimestamp > 0) latestTimestamp else now
|
||||||
lastEmitTimestamp = now
|
lastEmitTimestamp = now
|
||||||
|
|
||||||
// Ensure listener notifications run on the main thread for consistency
|
// Ensure listener notifications run on the main thread for consistency
|
||||||
@ -740,13 +746,42 @@ class DumonGeolocation : Plugin() {
|
|||||||
obj.put("isMocked", isMockedLocation)
|
obj.put("isMocked", isMockedLocation)
|
||||||
obj.put("mode", if (currentTrackingMode == GpsTrackingMode.DRIVING) "driving" else "normal")
|
obj.put("mode", if (currentTrackingMode == GpsTrackingMode.DRIVING) "driving" else "normal")
|
||||||
|
|
||||||
// Always provide IMU-related fields to match TS definitions
|
// Gather speed candidates
|
||||||
val speedVal = latestImu?.speed ?: 0f
|
val imuSpeed: Float? = latestImu?.speed
|
||||||
val accelVal = latestImu?.acceleration ?: 0f
|
val imuAccel: Float = latestImu?.acceleration ?: 0f
|
||||||
val dirVal = latestImu?.directionRad ?: 0f
|
val imuDir: Float = latestImu?.directionRad ?: 0f
|
||||||
obj.put("speed", speedVal)
|
|
||||||
obj.put("acceleration", accelVal)
|
// GNSS speed candidate is valid only if recent enough
|
||||||
obj.put("directionRad", dirVal)
|
val fixAgeMs = if (latestTimestamp > 0) (now - latestTimestamp) else Long.MAX_VALUE
|
||||||
|
val gnssSpeed: Float? = latestGnssSpeed?.takeIf { fixAgeMs <= 3000L }
|
||||||
|
|
||||||
|
// Derived speed from delta position and timestamps (use only on sufficient dt)
|
||||||
|
val derivedSpeed: Float? = run {
|
||||||
|
val dtMs = if (prevTimestamp > 0 && latestTimestamp > 0) (latestTimestamp - prevTimestamp) else 0L
|
||||||
|
val dtSec = dtMs.toDouble() / 1000.0
|
||||||
|
if (dtSec >= 3.0 && dtSec <= 30.0) {
|
||||||
|
val dMeters = calculateDistance(latestLatitude, latestLongitude, prevLatitude, prevLongitude)
|
||||||
|
(dMeters / dtSec).toFloat()
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose final speed: GNSS > IMU > Derived > 0
|
||||||
|
val (finalSpeed, speedSource) = when {
|
||||||
|
gnssSpeed != null -> Pair(gnssSpeed, "GNSS")
|
||||||
|
imuSpeed != null -> Pair(imuSpeed, "IMU")
|
||||||
|
derivedSpeed != null -> Pair(derivedSpeed, "DELTA")
|
||||||
|
else -> Pair(0f, "NONE")
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.put("speed", finalSpeed)
|
||||||
|
obj.put("acceleration", imuAccel)
|
||||||
|
obj.put("directionRad", imuDir)
|
||||||
|
obj.put("speedSource", speedSource)
|
||||||
|
|
||||||
|
// Optional additional fields when available
|
||||||
|
gnssSpeed?.let { obj.put("speedGnss", it.toDouble()) }
|
||||||
|
imuSpeed?.let { obj.put("speedImu", it.toDouble()) }
|
||||||
|
derivedSpeed?.let { obj.put("speedDerived", it.toDouble()) }
|
||||||
|
|
||||||
obj.put("predicted", predicted)
|
obj.put("predicted", predicted)
|
||||||
|
|
||||||
|
|||||||
28
dist/docs.json
vendored
28
dist/docs.json
vendored
@ -386,6 +386,34 @@
|
|||||||
"docs": "",
|
"docs": "",
|
||||||
"complexTypes": [],
|
"complexTypes": [],
|
||||||
"type": "boolean | undefined"
|
"type": "boolean | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "speedSource",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "'GNSS' | 'IMU' | 'DELTA' | 'NONE' | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "speedGnss",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "speedImu",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "speedDerived",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
4
dist/esm/definitions.d.ts
vendored
4
dist/esm/definitions.d.ts
vendored
@ -11,6 +11,10 @@ export interface PositioningData {
|
|||||||
isMocked: boolean;
|
isMocked: boolean;
|
||||||
mode: 'normal' | 'driving';
|
mode: 'normal' | 'driving';
|
||||||
predicted?: boolean;
|
predicted?: boolean;
|
||||||
|
speedSource?: 'GNSS' | 'IMU' | 'DELTA' | 'NONE';
|
||||||
|
speedGnss?: number;
|
||||||
|
speedImu?: number;
|
||||||
|
speedDerived?: number;
|
||||||
}
|
}
|
||||||
export interface SatelliteStatus {
|
export interface SatelliteStatus {
|
||||||
satellitesInView: number;
|
satellitesInView: number;
|
||||||
|
|||||||
2
dist/esm/definitions.js.map
vendored
2
dist/esm/definitions.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n// export interface SatelliteStatus {\n// satellitesInView: number;\n// usedInFix: number;\n// constellationCounts: { [key: string]: number };\n// }\n\n// export interface WifiAp {\n// ssid: string;\n// bssid: string;\n// rssi: number;\n// distance?: number;\n// }\n\n// export interface WifiScanResult {\n// apCount: number;\n// aps: WifiAp[];\n// }\n\n// export interface ImuData {\n// accelX: number;\n// accelY: number;\n// accelZ: number;\n// gyroX: number;\n// gyroY: number;\n// gyroZ: number;\n// speed?: number;\n// acceleration?: number;\n// directionRad?: number;\n// }\n\n// export interface GpsData {\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n// satellitesInView?: number;\n// usedInFix?: number;\n// constellationCounts?: { [key: string]: number };\n// }\n\n// export interface PositioningData {\n// source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n// timestamp: number;\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n\n// gnssData?: SatelliteStatus;\n// wifiData?: WifiAp[];\n// imuData?: ImuData;\n// }\n\nexport interface PositioningData {\n source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n timestamp: number;\n latitude: number;\n longitude: number;\n accuracy: number;\n speed: number;\n acceleration: number;\n directionRad: number;\n isMocked: boolean;\n mode: 'normal' | 'driving';\n predicted?: boolean;\n}\n\nexport interface SatelliteStatus {\n satellitesInView: number;\n usedInFix: number;\n constellationCounts: { [key: string]: number };\n}\n\nexport interface DumonGeoOptions {\n distanceThresholdMeters?: number;\n speedChangeThreshold?: number;\n directionChangeThreshold?: number;\n emitDebounceMs?: number;\n drivingEmitIntervalMs?: number;\n wifiScanIntervalMs?: number;\n enableWifiRtt?: boolean;\n enableLogging?: boolean;\n enableForwardPrediction?: boolean;\n maxPredictionSeconds?: number;\n emitGnssStatus?: boolean;\n suppressMockedUpdates?: boolean;\n keepScreenOn?: boolean;\n backgroundPollingIntervalMs?: number; // Android background polling interval\n backgroundPostMinDistanceMeters?: number; // Android background min distance to post\n backgroundPostMinAccuracyMeters?: number; // Android background min acceptable accuracy for POST (meters)\n backgroundMinPostIntervalMs?: number; // Android background minimum interval between POST attempts\n}\n\nexport interface PermissionStatus {\n location: 'granted' | 'denied';\n wifi: 'granted' | 'denied';\n}\n\nexport interface DumonGeolocationPlugin {\n startPositioning(): Promise<void>;\n stopPositioning(): Promise<void>;\n getLatestPosition(): Promise<PositioningData>;\n checkAndRequestPermissions(): Promise<PermissionStatus>;\n setOptions(options: DumonGeoOptions): Promise<void>;\n getGnssStatus(): Promise<SatelliteStatus | null>;\n getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>;\n // Background tracking (Android)\n startBackgroundTracking(options?: {\n title?: string;\n text?: string;\n channelId?: string;\n channelName?: string;\n postUrl?: string; // optional: service will POST latest fixes here as JSON\n }): Promise<void>;\n stopBackgroundTracking(): Promise<void>;\n isBackgroundTrackingActive(): Promise<{ active: boolean }>;\n getBackgroundLatestPosition(): Promise<PositioningData | null>;\n openBackgroundPermissionSettings(): Promise<void>;\n openNotificationPermissionSettings(): Promise<void>;\n // Auth token management for background posting\n setAuthTokens(tokens: { accessToken: string; refreshToken: string }): Promise<void>;\n clearAuthTokens(): Promise<void>;\n getAuthState(): Promise<{ present: boolean }>;\n setBackgroundPostUrl(options: { url?: string }): Promise<void>;\n getBackgroundPostUrl(): Promise<{ url: string | null }>;\n\n configureEdgeToEdge(options: {\n bgColor: string;\n style: 'DARK' | 'LIGHT';\n overlay?: boolean;\n }): Promise<void>;\n\n setGpsMode(options: { mode: 'normal' | 'driving' }): Promise<void>;\n\n addListener(\n eventName: 'onPositionUpdate',\n listenerFunc: (data: PositioningData) => void\n ): PluginListenerHandle;\n\n addListener(\n eventName: 'onGnssStatus',\n listenerFunc: (data: SatelliteStatus) => void\n ): PluginListenerHandle;\n}\n"]}
|
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n// export interface SatelliteStatus {\n// satellitesInView: number;\n// usedInFix: number;\n// constellationCounts: { [key: string]: number };\n// }\n\n// export interface WifiAp {\n// ssid: string;\n// bssid: string;\n// rssi: number;\n// distance?: number;\n// }\n\n// export interface WifiScanResult {\n// apCount: number;\n// aps: WifiAp[];\n// }\n\n// export interface ImuData {\n// accelX: number;\n// accelY: number;\n// accelZ: number;\n// gyroX: number;\n// gyroY: number;\n// gyroZ: number;\n// speed?: number;\n// acceleration?: number;\n// directionRad?: number;\n// }\n\n// export interface GpsData {\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n// satellitesInView?: number;\n// usedInFix?: number;\n// constellationCounts?: { [key: string]: number };\n// }\n\n// export interface PositioningData {\n// source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n// timestamp: number;\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n\n// gnssData?: SatelliteStatus;\n// wifiData?: WifiAp[];\n// imuData?: ImuData;\n// }\n\nexport interface PositioningData {\n source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n timestamp: number;\n latitude: number;\n longitude: number;\n accuracy: number;\n speed: number;\n acceleration: number;\n directionRad: number;\n isMocked: boolean;\n mode: 'normal' | 'driving';\n predicted?: boolean;\n // Optional detailed speed fields and provenance\n speedSource?: 'GNSS' | 'IMU' | 'DELTA' | 'NONE';\n speedGnss?: number; // m/s from Location.getSpeed when available and fresh\n speedImu?: number; // m/s from IMU fusion (internal heuristic)\n speedDerived?: number; // m/s from delta-position / delta-time (coarse)\n}\n\nexport interface SatelliteStatus {\n satellitesInView: number;\n usedInFix: number;\n constellationCounts: { [key: string]: number };\n}\n\nexport interface DumonGeoOptions {\n distanceThresholdMeters?: number;\n speedChangeThreshold?: number;\n directionChangeThreshold?: number;\n emitDebounceMs?: number;\n drivingEmitIntervalMs?: number;\n wifiScanIntervalMs?: number;\n enableWifiRtt?: boolean;\n enableLogging?: boolean;\n enableForwardPrediction?: boolean;\n maxPredictionSeconds?: number;\n emitGnssStatus?: boolean;\n suppressMockedUpdates?: boolean;\n keepScreenOn?: boolean;\n backgroundPollingIntervalMs?: number; // Android background polling interval\n backgroundPostMinDistanceMeters?: number; // Android background min distance to post\n backgroundPostMinAccuracyMeters?: number; // Android background min acceptable accuracy for POST (meters)\n backgroundMinPostIntervalMs?: number; // Android background minimum interval between POST attempts\n}\n\nexport interface PermissionStatus {\n location: 'granted' | 'denied';\n wifi: 'granted' | 'denied';\n}\n\nexport interface DumonGeolocationPlugin {\n startPositioning(): Promise<void>;\n stopPositioning(): Promise<void>;\n getLatestPosition(): Promise<PositioningData>;\n checkAndRequestPermissions(): Promise<PermissionStatus>;\n setOptions(options: DumonGeoOptions): Promise<void>;\n getGnssStatus(): Promise<SatelliteStatus | null>;\n getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>;\n // Background tracking (Android)\n startBackgroundTracking(options?: {\n title?: string;\n text?: string;\n channelId?: string;\n channelName?: string;\n postUrl?: string; // optional: service will POST latest fixes here as JSON\n }): Promise<void>;\n stopBackgroundTracking(): Promise<void>;\n isBackgroundTrackingActive(): Promise<{ active: boolean }>;\n getBackgroundLatestPosition(): Promise<PositioningData | null>;\n openBackgroundPermissionSettings(): Promise<void>;\n openNotificationPermissionSettings(): Promise<void>;\n // Auth token management for background posting\n setAuthTokens(tokens: { accessToken: string; refreshToken: string }): Promise<void>;\n clearAuthTokens(): Promise<void>;\n getAuthState(): Promise<{ present: boolean }>;\n setBackgroundPostUrl(options: { url?: string }): Promise<void>;\n getBackgroundPostUrl(): Promise<{ url: string | null }>;\n\n configureEdgeToEdge(options: {\n bgColor: string;\n style: 'DARK' | 'LIGHT';\n overlay?: boolean;\n }): Promise<void>;\n\n setGpsMode(options: { mode: 'normal' | 'driving' }): Promise<void>;\n\n addListener(\n eventName: 'onPositionUpdate',\n listenerFunc: (data: PositioningData) => void\n ): PluginListenerHandle;\n\n addListener(\n eventName: 'onGnssStatus',\n listenerFunc: (data: SatelliteStatus) => void\n ): PluginListenerHandle;\n}\n"]}
|
||||||
4
dist/esm/web.js
vendored
4
dist/esm/web.js
vendored
@ -23,6 +23,10 @@ export class DumonGeolocationWeb extends WebPlugin {
|
|||||||
directionRad: 0,
|
directionRad: 0,
|
||||||
isMocked: false,
|
isMocked: false,
|
||||||
mode: this._mode,
|
mode: this._mode,
|
||||||
|
speedSource: 'NONE',
|
||||||
|
speedImu: 0,
|
||||||
|
speedGnss: 0,
|
||||||
|
speedDerived: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async checkAndRequestPermissions() {
|
async checkAndRequestPermissions() {
|
||||||
|
|||||||
2
dist/esm/web.js.map
vendored
2
dist/esm/web.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/plugin.cjs.js
vendored
4
dist/plugin.cjs.js
vendored
@ -30,6 +30,10 @@ class DumonGeolocationWeb extends core.WebPlugin {
|
|||||||
directionRad: 0,
|
directionRad: 0,
|
||||||
isMocked: false,
|
isMocked: false,
|
||||||
mode: this._mode,
|
mode: this._mode,
|
||||||
|
speedSource: 'NONE',
|
||||||
|
speedImu: 0,
|
||||||
|
speedGnss: 0,
|
||||||
|
speedDerived: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async checkAndRequestPermissions() {
|
async checkAndRequestPermissions() {
|
||||||
|
|||||||
2
dist/plugin.cjs.js.map
vendored
2
dist/plugin.cjs.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/plugin.js
vendored
4
dist/plugin.js
vendored
@ -29,6 +29,10 @@ var capacitorDumonGeolocation = (function (exports, core) {
|
|||||||
directionRad: 0,
|
directionRad: 0,
|
||||||
isMocked: false,
|
isMocked: false,
|
||||||
mode: this._mode,
|
mode: this._mode,
|
||||||
|
speedSource: 'NONE',
|
||||||
|
speedImu: 0,
|
||||||
|
speedGnss: 0,
|
||||||
|
speedDerived: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async checkAndRequestPermissions() {
|
async checkAndRequestPermissions() {
|
||||||
|
|||||||
2
dist/plugin.js.map
vendored
2
dist/plugin.js.map
vendored
File diff suppressed because one or more lines are too long
@ -25,12 +25,17 @@ export interface PositioningData {
|
|||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
accuracy: number; // meter
|
accuracy: number; // meter
|
||||||
speed: number; // m/s (dari IMU heuristik)
|
speed: number; // m/s (lihat kebijakan pemilihan di bawah)
|
||||||
acceleration: number; // m/s^2 (magnitude IMU)
|
acceleration: number; // m/s^2 (magnitude IMU)
|
||||||
directionRad: number; // radian, relatif utara
|
directionRad: number; // radian, relatif utara
|
||||||
isMocked: boolean; // lokasi terdeteksi palsu
|
isMocked: boolean; // lokasi terdeteksi palsu
|
||||||
mode: 'normal' | 'driving'; // mode tracking aktif saat emisi
|
mode: 'normal' | 'driving'; // mode tracking aktif saat emisi
|
||||||
predicted?: boolean; // true jika posisi diproyeksikan ke depan
|
predicted?: boolean; // true jika posisi diproyeksikan ke depan
|
||||||
|
// opsional: detail asal speed
|
||||||
|
speedSource?: 'GNSS' | 'IMU' | 'DELTA' | 'NONE';
|
||||||
|
speedGnss?: number; // m/s dari Location.getSpeed bila tersedia & segar
|
||||||
|
speedImu?: number; // m/s dari IMU (heuristik internal)
|
||||||
|
speedDerived?: number; // m/s hasil Δpos/Δt (kasar)
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SatelliteStatus {
|
export interface SatelliteStatus {
|
||||||
@ -184,6 +189,14 @@ Implementasi utama: `android/src/main/java/com/dumon/plugin/geolocation/DumonGeo
|
|||||||
- Jika `enableForwardPrediction` aktif dan ada IMU, posisi dapat diproyeksikan pendek (<= `maxPredictionSeconds`) memakai `speed` dan `directionRad` → flag `predicted: true`.
|
- Jika `enableForwardPrediction` aktif dan ada IMU, posisi dapat diproyeksikan pendek (<= `maxPredictionSeconds`) memakai `speed` dan `directionRad` → flag `predicted: true`.
|
||||||
- `source` tetap diisi nilai asli (mis. `GNSS`), bukan `FUSED`.
|
- `source` tetap diisi nilai asli (mis. `GNSS`), bukan `FUSED`.
|
||||||
|
|
||||||
|
### Kebijakan pemilihan `speed`
|
||||||
|
|
||||||
|
- Urutan prioritas: GNSS > IMU > Δpos/Δt > 0.
|
||||||
|
- GNSS: dipakai bila `Location.hasSpeed()` dan usia fix ≤ ~3000 ms.
|
||||||
|
- IMU: fallback dari integrasi percepatan IMU (0..30 m/s; smoothing dan idle handling diterapkan).
|
||||||
|
- Δpos/Δt: dipakai hanya bila selang waktu antar fix memadai (≥ 3 s). Cocok sebagai estimasi kasar.
|
||||||
|
- Untuk transparansi, payload dapat menyertakan `speedSource`, `speedGnss`, `speedImu`, `speedDerived` (opsional).
|
||||||
|
|
||||||
### getLatestPosition (perilaku terbaru)
|
### getLatestPosition (perilaku terbaru)
|
||||||
|
|
||||||
- Memicu `GpsStatusManager.requestSingleFix()` (GPS + opsional Network) dengan timeout default ~3000 ms.
|
- Memicu `GpsStatusManager.requestSingleFix()` (GPS + opsional Network) dengan timeout default ~3000 ms.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dumon-geolocation",
|
"name": "dumon-geolocation",
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"description": "Implement manager GNSS, Wi‑Fi RTT, IMU, Kalman fusion, event emitter",
|
"description": "Implement manager GNSS, Wi‑Fi RTT, IMU, Kalman fusion, event emitter",
|
||||||
"main": "dist/plugin.cjs.js",
|
"main": "dist/plugin.cjs.js",
|
||||||
"module": "dist/esm/index.js",
|
"module": "dist/esm/index.js",
|
||||||
|
|||||||
@ -63,6 +63,11 @@ export interface PositioningData {
|
|||||||
isMocked: boolean;
|
isMocked: boolean;
|
||||||
mode: 'normal' | 'driving';
|
mode: 'normal' | 'driving';
|
||||||
predicted?: boolean;
|
predicted?: boolean;
|
||||||
|
// Optional detailed speed fields and provenance
|
||||||
|
speedSource?: 'GNSS' | 'IMU' | 'DELTA' | 'NONE';
|
||||||
|
speedGnss?: number; // m/s from Location.getSpeed when available and fresh
|
||||||
|
speedImu?: number; // m/s from IMU fusion (internal heuristic)
|
||||||
|
speedDerived?: number; // m/s from delta-position / delta-time (coarse)
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SatelliteStatus {
|
export interface SatelliteStatus {
|
||||||
|
|||||||
@ -24,6 +24,10 @@ export class DumonGeolocationWeb extends WebPlugin {
|
|||||||
directionRad: 0,
|
directionRad: 0,
|
||||||
isMocked: false,
|
isMocked: false,
|
||||||
mode: this._mode,
|
mode: this._mode,
|
||||||
|
speedSource: 'NONE',
|
||||||
|
speedImu: 0,
|
||||||
|
speedGnss: 0,
|
||||||
|
speedDerived: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user