# 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) } 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. ### 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`