401 lines
16 KiB
Markdown
401 lines
16 KiB
Markdown
# 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<void>
|
||
```
|
||
- Mulai GNSS, IMU, dan Wi‑Fi scanning periodik (RTT opsional). Mengaktifkan loop emisi posisi.
|
||
|
||
```ts
|
||
stopPositioning(): Promise<void>
|
||
```
|
||
- Hentikan semua sensor dan emisi update.
|
||
|
||
```ts
|
||
getLatestPosition(): Promise<PositioningData>
|
||
```
|
||
- 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<PermissionStatus>
|
||
```
|
||
- Memeriksa dan (bila perlu) meminta semua izin lokasi/Wi‑Fi yang diperlukan.
|
||
|
||
```ts
|
||
setOptions(options: DumonGeoOptions): Promise<void>
|
||
```
|
||
- 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<void>
|
||
```
|
||
- `normal`: polling adaptif (hemat baterai). `driving`: continuous GPS + loop emisi paksa berkala.
|
||
|
||
```ts
|
||
configureEdgeToEdge(options: { bgColor: string; style: 'DARK' | 'LIGHT'; overlay?: boolean }): Promise<void>
|
||
```
|
||
- Mengatur status bar/navigation bar agar sesuai tema UI.
|
||
|
||
```ts
|
||
getGnssStatus(): Promise<SatelliteStatus | null>
|
||
```
|
||
- 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<void>
|
||
stopBackgroundTracking(): Promise<void>
|
||
isBackgroundTrackingActive(): Promise<{ active: boolean }>
|
||
getBackgroundLatestPosition(): Promise<PositioningData | null>
|
||
setAuthTokens(tokens: { accessToken: string; refreshToken: string }): Promise<void>
|
||
clearAuthTokens(): Promise<void>
|
||
getAuthState(): Promise<{ present: boolean }>
|
||
setBackgroundPostUrl(options: { url?: string }): Promise<void>
|
||
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 <token>` dan `refresh-token: <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: '<ACCESS>', refreshToken: '<REFRESH>' });
|
||
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`
|