# Dumon Geolocation Plugin — Reference & Internals Dokumen ini merangkum API publik, perilaku runtime, state internal, serta contoh penggunaan plugin dumon‑geolocation (Android). Disusun agar mudah dipahami developer aplikasi. ## Ringkasan - Platform: Android (web memiliki stub; iOS saat ini bukan target utama). - Sumber data: GNSS (GPS/GLONASS/BeiDou/Galileo), IMU (accelerometer/gyro/rotation), Wi‑Fi (RTT/RSSI untuk diagnostik), deteksi lokasi palsu (mock). - Update real‑time melalui event `onPositionUpdate` dengan debounce dan threshold perubahan posisi/kecepatan/arah. - getLatestPosition: mencoba satu kali pembacaan “fresh” (one‑shot) lalu fallback ke snapshot terakhir bila gagal/timeout. - Opsi prediksi maju (dead‑reckoning) opsional untuk memproyeksikan posisi pendek ke depan. --- ## API Publik (TypeScript) Tipe didefinisikan di `dumon-geolocation/src/definitions.ts`. ### Interfaces ```ts export interface PositioningData { source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK'; timestamp: number; // epoch ms latitude: number; longitude: number; accuracy: number; // meter speed: number; // m/s (lihat kebijakan pemilihan di bawah) acceleration: number; // m/s^2 (magnitude IMU) directionRad: number; // radian, relatif utara isMocked: boolean; // lokasi terdeteksi palsu mode: 'normal' | 'driving'; // mode tracking aktif saat emisi 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 { satellitesInView: number; usedInFix: number; constellationCounts: { [key: string]: number }; } export interface DumonGeoOptions { distanceThresholdMeters?: number; // default ~7.0 speedChangeThreshold?: number; // default ~0.5 m/s directionChangeThreshold?: number; // default ~0.17 rad (~10°) emitDebounceMs?: number; // default adaptif; awal 1000 ms drivingEmitIntervalMs?: number; // default ~1600 ms wifiScanIntervalMs?: number; // default ~3000 ms enableWifiRtt?: boolean; // default true enableLogging?: boolean; // default off → bisa on lewat options enableForwardPrediction?: boolean; // default false maxPredictionSeconds?: number; // default 1.0, clamp 0..5 emitGnssStatus?: boolean; // default false suppressMockedUpdates?: boolean; // default false keepScreenOn?: boolean; // default false backgroundPollingIntervalMs?: number; // Android: interval polling service (default 5000) backgroundPostMinDistanceMeters?: number; // Android: minimum perpindahan untuk POST (default 10m) backgroundPostMinAccuracyMeters?: number; // Android: minimum akurasi fix untuk POST (meter); kosong = tidak dibatasi backgroundMinPostIntervalMs?: number; // Android: interval minimum antar upaya POST (default ~10000 ms) backgroundUseImuFallback?: boolean; // Android: aktif/nonaktifkan fallback speed via IMU saat background (default false) } export interface PermissionStatus { location: 'granted' | 'denied'; wifi: 'granted' | 'denied'; } ``` ### Methods ```ts startPositioning(): Promise ``` - Mulai GNSS, IMU, dan Wi‑Fi scanning periodik (RTT opsional). Mengaktifkan loop emisi posisi. ```ts stopPositioning(): Promise ``` - Hentikan semua sensor dan emisi update. ```ts getLatestPosition(): Promise ``` - Mencoba mengambil 1x lokasi “fresh” (one‑shot) dari provider (GPS + opsional Network) dengan timeout singkat (~3000 ms). Jika gagal/timeout atau disupress (mock), fallback ke snapshot terakhir yang tersimpan. ```ts checkAndRequestPermissions(): Promise ``` - Memeriksa dan (bila perlu) meminta semua izin lokasi/Wi‑Fi yang diperlukan. ```ts setOptions(options: DumonGeoOptions): Promise ``` - Mengubah opsi runtime (threshold, interval, logging, prediksi, GNSS status, Wi‑Fi RTT, dll). Sebagian opsi langsung mempengaruhi perilaku GPS polling dan loop emisi. ```ts setGpsMode(options: { mode: 'normal' | 'driving' }): Promise ``` - `normal`: polling adaptif (hemat baterai). `driving`: continuous GPS + loop emisi paksa berkala. ```ts configureEdgeToEdge(options: { bgColor: string; style: 'DARK' | 'LIGHT'; overlay?: boolean }): Promise ``` - Mengatur status bar/navigation bar agar sesuai tema UI. ```ts getGnssStatus(): Promise ``` - Mengambil status satelit terakhir (untuk diagnostik). Listener real‑time tersedia jika `emitGnssStatus` diaktifkan. ```ts getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }> ``` - Memeriksa apakah provider GNSS dan Network aktif di perangkat. ```ts // Android only — background tracking via Foreground Service startBackgroundTracking(options?: { title?: string; text?: string; channelId?: string; channelName?: string; postUrl?: string }): Promise stopBackgroundTracking(): Promise isBackgroundTrackingActive(): Promise<{ active: boolean }> getBackgroundLatestPosition(): Promise setAuthTokens(tokens: { accessToken: string; refreshToken: string }): Promise clearAuthTokens(): Promise getAuthState(): Promise<{ present: boolean }> setBackgroundPostUrl(options: { url?: string }): Promise getBackgroundPostUrl(): Promise<{ url: string | null }> ``` - Menjalankan tracking lokasi saat app di‑pause menggunakan Foreground Service. Menyimpan latest fix ke penyimpanan lokal agar bisa diambil saat kembali ke foreground. Opsi `postUrl` (opsional) akan mengirim setiap pembaruan lokasi via HTTP POST (JSON) ke endpoint tersebut. Untuk autentikasi header, panggil `setAuthTokens` (menyimpan token secara native) agar setiap POST menyertakan header `Authorization: Bearer ` dan `refresh-token: `. Di web: no‑op. Catatan baterai (Android, background): - Secara default fallback IMU dimatikan. Aktifkan `backgroundUseImuFallback: true` bila Anda butuh estimasi speed yang lebih halus saat sinyal GNSS kurang baik, dengan konsekuensi konsumsi baterai meningkat. Saat dimatikan, speed di background hanya berasal dari GNSS (jika tersedia) atau turunan Δpos/Δt; `acceleration` dan `directionRad` akan terset ke 0. Format payload POST (background): - `source`: string (`GNSS` | `MOCK`) - `timestamp`: number (epoch ms) - `latitude`: number - `longitude`: number - `accuracy`: number (meter) - `speed`: number (m/s) - `isMocked`: boolean ### Events ```ts addListener('onPositionUpdate', (data: PositioningData) => void) ``` - Menerima update posisi real‑time dengan debounce dan threshold perubahan. Di mode `driving`, emisi dipaksa periodik (default ~1600 ms) agar UI responsif saat bergerak cepat. ```ts addListener('onGnssStatus', (data: SatelliteStatus) => void) ``` - Mengalirkan status GNSS jika `emitGnssStatus: true` diaktifkan. --- ## Perilaku & State Internal (Android) Implementasi utama: `android/src/main/java/com/dumon/plugin/geolocation/DumonGeolocation.kt`. ### State penting (ringkas) - `latestLatitude/Longitude/Accuracy/Source/Timestamp`: snapshot posisi terakhir dari GNSS. - `latestImu: ImuData?`: speed, acceleration, directionRad dari IMU (heuristik, dismoothing). - `isMockedLocation`: flag hasil deteksi mock dari OS. - `prevLatitude/Longitude`, `prevSpeed`, `prevDirection`: baseline untuk menentukan perubahan signifikan. - Threshold dan interval: - `significantChangeThreshold` (meter), `speedChangeThreshold` (m/s), `directionChangeThreshold` (rad). - `emitIntervalMs`: base debounce; diatur adaptif via kecepatan IMU. - `drivingEmitIntervalMs`: interval emisi paksa di mode `driving`. - Opsi runtime: - `enableWifiRtt`, `enableForwardPrediction`, `maxPredictionSeconds`, `emitGnssStatus`, `suppressMockedUpdates`, `keepScreenOn`. - Mode GPS: `NORMAL` (polling) vs `DRIVING` (continuous + emit paksa). ### Sumber data - GNSS: `GpsStatusManager` - Mode polling adaptif (memicu request single update secara berkala) atau continuous (mode `driving`). - `requestSingleFix(timeoutMs, useNetworkProvider)` untuk one‑shot lokasi dengan timeout. - Meneruskan status satelit via callback. - IMU: `ImuSensorManager` - Menggabungkan accelerometer, gyroscope, rotation vector untuk estimasi `speed`, `acceleration`, `directionRad`. - Menyetel delay sensor dan interval emisi adaptif berdasarkan kecepatan. - Wi‑Fi: `WifiPositioningManager` - Scan periodik; jika RTT didukung dan diaktifkan, akan mencoba pengukuran jarak AP (diagnostik). Data Wi‑Fi saat ini belum dipakai untuk menghitung posisi final; menjadi sinyal tambahan di update. ### Emisi update posisi - `emitPositionUpdate()` dipicu oleh perubahan GNSS/IMU/Wi‑Fi dengan aturan: - Hanya emit jika lewat debounce dan terjadi perubahan signifikan: jarak, selisih speed, atau selisih arah. - Di mode `driving`, ada loop yang memaksa emisi periodik supaya UI tetap responsif. - Jika `suppressMockedUpdates` aktif dan lokasi terdeteksi mock, emisi dibatalkan. ### Prediksi maju (opsional) - 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`. ### 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) - Memicu `GpsStatusManager.requestSingleFix()` (GPS + opsional Network) dengan timeout default ~3000 ms. - Jika berhasil dan tidak disupress (mock), update state lalu kembalikan hasil `buildPositionData()`. - Jika timeout atau disupress, fallback ke snapshot terakhir. --- ## Driving Mode vs Normal Mode (Android) Perbedaan inti antara kedua mode ini ada pada cara GPS diakses dan bagaimana event dikirim ke JS. - Pola akses GPS - Driving: continuous updates (GPS selalu aktif dengan requestLocationUpdates 0 ms/0 m). Cocok untuk navigasi real‑time dan pergerakan cepat. - Normal: polling periodik (one‑shot tiap interval) dengan handler internal. Lebih hemat baterai. - Emisi ke JS - Driving: ada loop emisi paksa (force emit) menggunakan lokasi yang di‑buffer, pada interval `drivingEmitIntervalMs` (default ~1600 ms) agar UI tetap responsif. - Normal: emisi hanya terjadi bila melewati debounce (`emitIntervalMs`) dan ada perubahan signifikan (jarak/speed/arah) dari baseline sebelumnya. - Interval & adaptasi - Driving: diatur oleh `drivingEmitIntervalMs` (ubah via `setOptions`). - Normal: `emitIntervalMs` diatur adaptif berdasarkan estimasi kecepatan IMU, kira‑kira: - > 5 m/s → 3000 ms - > 1.5 m/s → 8000 ms - > 0.3 m/s → 20000 ms - idle → 30000 ms - Trade‑off - Driving: latency rendah, konsumsi baterai lebih tinggi. - Normal: hemat baterai, cukup untuk use‑case non‑navigasi. - Cara ganti mode - `setGpsMode({ mode: 'driving' })` atau `setGpsMode({ mode: 'normal' })`. ## Permissions (Android) - Wajib: `ACCESS_FINE_LOCATION` (GNSS), `ACCESS_COARSE_LOCATION` (Network provider/Wi‑Fi scan), `ACCESS_WIFI_STATE`, `CHANGE_WIFI_STATE`. - Android 13+: `NEARBY_WIFI_DEVICES` untuk RTT. - Disarankan: aktifkan Location Services (GPS dan Network) agar one‑shot lebih cepat. Gunakan `checkAndRequestPermissions()` sebelum memulai. --- ## Contoh Penggunaan ### Persiapan dasar ```ts import { DumonGeolocation } from 'dumon-geolocation'; // 1) Minta izin await DumonGeolocation.checkAndRequestPermissions(); // 2) Opsi (opsional) await DumonGeolocation.setOptions({ enableLogging: true, emitDebounceMs: 1000, enableForwardPrediction: false, }); // 3) Listener real-time const handle = DumonGeolocation.addListener('onPositionUpdate', data => { console.log('pos:', data); }); // 4) Mulai await DumonGeolocation.startPositioning(); // ... // 5) Stop bila perlu await DumonGeolocation.stopPositioning(); await handle.remove(); ``` ### Satu kali pembacaan (fresh + fallback) ```ts const data = await DumonGeolocation.getLatestPosition(); console.log('latest:', data); // Catatan: bisa menunggu ~3s untuk one-shot fix, // lalu jatuh ke snapshot kalau timeout. ``` ### Mode GPS ```ts await DumonGeolocation.setGpsMode({ mode: 'driving' }); // continuous + emit paksa // ... await DumonGeolocation.setGpsMode({ mode: 'normal' }); // polling adaptif ``` ### GNSS status dan layanan lokasi ```ts await DumonGeolocation.setOptions({ emitGnssStatus: true }); const gnssHandle = DumonGeolocation.addListener('onGnssStatus', s => console.log('gnss:', s)); const services = await DumonGeolocation.getLocationServicesStatus(); console.log('services:', services); ``` ### UI Edge‑to‑Edge ```ts await DumonGeolocation.configureEdgeToEdge({ bgColor: '#ffffff', style: 'DARK', overlay: false, }); ``` ### Background tracking (Android) ```ts // Minta izin lokasi dan notifikasi (Android 13+) lebih dulu await DumonGeolocation.checkAndRequestPermissions(); // Mulai Foreground Service untuk tracking di background await DumonGeolocation.startBackgroundTracking({ title: 'Dumon tracking active', text: 'Collecting location in background', // opsional: posting otomatis setiap update lokasi (JSON) postUrl: 'https://dumonapp.com/dev-test-cap', }); // Cek status dan tarik latest fix yang disimpan oleh service const { active } = await DumonGeolocation.isBackgroundTrackingActive(); const latestBg = await DumonGeolocation.getBackgroundLatestPosition(); // Berhenti await DumonGeolocation.stopBackgroundTracking(); // Opsi: set token autentikasi dan URL endpoint secara terpisah (dapat diubah kapan saja) await DumonGeolocation.setAuthTokens({ accessToken: '', refreshToken: '' }); await DumonGeolocation.setBackgroundPostUrl({ url: 'https://dumonapp.com/dev-test-cap' }); // Kirim otomatis hanya jika perpindahan >= 10 meter (default 10 m); atur interval polling 5 detik await DumonGeolocation.setOptions({ backgroundPostMinDistanceMeters: 10, backgroundPollingIntervalMs: 5000 }); // (Opsional) Tambah pembatasan akurasi & interval minimum antar POST await DumonGeolocation.setOptions({ backgroundPostMinAccuracyMeters: 50, backgroundMinPostIntervalMs: 10000 }); // Catatan perilaku background: // - Service melakukan polling one‑shot fix periodik dan menyimpan latest fix. // - Posting ke REST API hanya terjadi jika bergerak minimal 'backgroundPostMinDistanceMeters' dari lokasi terakhir yang sukses diposting. // - Jika GPS lemah (mis. indoor), service juga mencoba NETWORK provider saat polling agar tetap ada pembaruan. // - Token Authorization/refresh‑token diambil dari penyimpanan native yang diisi via setAuthTokens(). ``` --- ## Catatan & Batasan - Event JS tidak berjalan saat app di‑pause/background. Untuk update background yang andal, gunakan Foreground Service native (rencana peningkatan berikutnya). - Prediksi maju bersifat heuristik (berbasis IMU); aktifkan hanya bila sesuai kebutuhan. - Wi‑Fi RTT dibatasi oleh hardware/OS; di background, kemampuan scan bisa dibatasi OS. - Web: stub (mengembalikan data dummy) sehingga hanya bermanfaat untuk pengembangan UI. --- ## Rencana Peningkatan (arah) - Background tracking via Foreground Service (lokasi dan penyimpanan/telemetri saat app di‑pause). - Opsi konfigurasi timeouts/strategi one‑shot getLatestPosition via `setOptions`. - Integrasi Fused Location Provider untuk TTFF/efisiensi lebih baik. --- ## Build & Run (Example App) Plugin build ``` cd dumon-geolocation npm install npm run build ``` Example app ``` cd dumon-geolocation/example-app npm install npm run build // <-- untuk update pack ke dist npx cap sync android npx cap run android ``` Alternatif: `npx cap open android` lalu Run dari Android Studio. --- ## Referensi File Penting - Plugin Android: `dumon-geolocation/android/src/main/java/com/dumon/plugin/geolocation/DumonGeolocation.kt` - GNSS Manager: `dumon-geolocation/android/src/main/java/com/dumon/plugin/geolocation/gps/GpsStatusManager.kt` - IMU Manager: `dumon-geolocation/android/src/main/java/com/dumon/plugin/geolocation/imu/ImuSensorManager.kt` - Wi‑Fi Manager: `dumon-geolocation/android/src/main/java/com/dumon/plugin/geolocation/wifi/WifiPositioningManager.kt` - Definisi TS: `dumon-geolocation/src/definitions.ts` - Contoh App: `dumon-geolocation/example-app`