dumon-geolocation/documentation/PLUGIN_REFERENCE.md
2025-10-15 09:49:07 +08:00

16 KiB
Raw Blame History

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

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

startPositioning(): Promise<void>
  • Mulai GNSS, IMU, dan WiFi scanning periodik (RTT opsional). Mengaktifkan loop emisi posisi.
stopPositioning(): Promise<void>
  • Hentikan semua sensor dan emisi update.
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.
checkAndRequestPermissions(): Promise<PermissionStatus>
  • Memeriksa dan (bila perlu) meminta semua izin lokasi/WiFi yang diperlukan.
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.
setGpsMode(options: { mode: 'normal' | 'driving' }): Promise<void>
  • normal: polling adaptif (hemat baterai). driving: continuous GPS + loop emisi paksa berkala.
configureEdgeToEdge(options: { bgColor: string; style: 'DARK' | 'LIGHT'; overlay?: boolean }): Promise<void>
  • Mengatur status bar/navigation bar agar sesuai tema UI.
getGnssStatus(): Promise<SatelliteStatus | null>
  • Mengambil status satelit terakhir (untuk diagnostik). Listener realtime tersedia jika emitGnssStatus diaktifkan.
getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>
  • Memeriksa apakah provider GNSS dan Network aktif di perangkat.
// 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.

Events

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.
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

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)

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

await DumonGeolocation.setGpsMode({ mode: 'driving' });  // continuous + emit paksa
// ...
await DumonGeolocation.setGpsMode({ mode: 'normal' });   // polling adaptif

GNSS status dan layanan lokasi

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

await DumonGeolocation.configureEdgeToEdge({
  bgColor: '#ffffff',
  style: 'DARK',
  overlay: false,
});

Background tracking (Android)

// 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