dumon-geolocation/documentation/PLUGIN_REFERENCE.md
2025-10-16 01:20:23 +08:00

415 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Dumon Geolocation Plugin — Reference & Internals
Dokumen ini merangkum API publik, perilaku runtime, state internal, serta contoh penggunaan plugin dumongeolocation (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), WiFi (RTT/RSSI untuk diagnostik), deteksi lokasi palsu (mock).
- Update realtime melalui event `onPositionUpdate` dengan debounce dan threshold perubahan posisi/kecepatan/arah.
- getLatestPosition: mencoba satu kali pembacaan “fresh” (oneshot) lalu fallback ke snapshot terakhir bila gagal/timeout.
- Opsi prediksi maju (deadreckoning) 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<void>
```
- Mulai GNSS, IMU, dan WiFi 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” (oneshot) 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/WiFi yang diperlukan.
```ts
setOptions(options: DumonGeoOptions): Promise<void>
```
- Mengubah opsi runtime (threshold, interval, logging, prediksi, GNSS status, WiFi 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 realtime 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 dipause 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: noop.
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 realtime 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 oneshot 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.
- WiFi: `WifiPositioningManager`
- Scan periodik; jika RTT didukung dan diaktifkan, akan mencoba pengukuran jarak AP (diagnostik). Data WiFi saat ini belum dipakai untuk menghitung posisi final; menjadi sinyal tambahan di update.
### Emisi update posisi
- `emitPositionUpdate()` dipicu oleh perubahan GNSS/IMU/WiFi 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 realtime dan pergerakan cepat.
- Normal: polling periodik (oneshot tiap interval) dengan handler internal. Lebih hemat baterai.
- Emisi ke JS
- Driving: ada loop emisi paksa (force emit) menggunakan lokasi yang dibuffer, 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, kirakira:
- > 5 m/s → 3000 ms
- > 1.5 m/s → 8000 ms
- > 0.3 m/s → 20000 ms
- idle → 30000 ms
- Tradeoff
- Driving: latency rendah, konsumsi baterai lebih tinggi.
- Normal: hemat baterai, cukup untuk usecase nonnavigasi.
- Cara ganti mode
- `setGpsMode({ mode: 'driving' })` atau `setGpsMode({ mode: 'normal' })`.
## Permissions (Android)
- Wajib: `ACCESS_FINE_LOCATION` (GNSS), `ACCESS_COARSE_LOCATION` (Network provider/WiFi scan), `ACCESS_WIFI_STATE`, `CHANGE_WIFI_STATE`.
- Android 13+: `NEARBY_WIFI_DEVICES` untuk RTT.
- Disarankan: aktifkan Location Services (GPS dan Network) agar oneshot 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 EdgetoEdge
```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 oneshot 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/refreshtoken diambil dari penyimpanan native yang diisi via setAuthTokens().
```
---
## Catatan & Batasan
- Event JS tidak berjalan saat app dipause/background. Untuk update background yang andal, gunakan Foreground Service native (rencana peningkatan berikutnya).
- Prediksi maju bersifat heuristik (berbasis IMU); aktifkan hanya bila sesuai kebutuhan.
- WiFi 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 dipause).
- Opsi konfigurasi timeouts/strategi oneshot 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`
- WiFi 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`