updated 280925-01
This commit is contained in:
parent
448824a187
commit
f5be8180f2
50
README.md
50
README.md
@ -94,6 +94,52 @@ configureEdgeToEdge(options: {
|
|||||||
|
|
||||||
Mengatur status bar dan navigasi bar agar transparan, dengan warna dan icon style sesuai UI.
|
Mengatur status bar dan navigasi bar agar transparan, dengan warna dan icon style sesuai UI.
|
||||||
|
|
||||||
|
### setOptions()
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
setOptions(options: {
|
||||||
|
distanceThresholdMeters?: number;
|
||||||
|
speedChangeThreshold?: number;
|
||||||
|
directionChangeThreshold?: number;
|
||||||
|
emitDebounceMs?: number;
|
||||||
|
drivingEmitIntervalMs?: number;
|
||||||
|
wifiScanIntervalMs?: number;
|
||||||
|
enableWifiRtt?: boolean;
|
||||||
|
enableLogging?: boolean;
|
||||||
|
enableForwardPrediction?: boolean;
|
||||||
|
maxPredictionSeconds?: number;
|
||||||
|
emitGnssStatus?: boolean;
|
||||||
|
suppressMockedUpdates?: boolean;
|
||||||
|
keepScreenOn?: boolean;
|
||||||
|
}): Promise<void>
|
||||||
|
```
|
||||||
|
|
||||||
|
Mengubah parameter runtime tanpa rebuild. Semua default menjaga perilaku saat ini.
|
||||||
|
|
||||||
|
### getGnssStatus()
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
getGnssStatus(): Promise<SatelliteStatus | null>
|
||||||
|
```
|
||||||
|
|
||||||
|
Mengambil status GNSS terakhir untuk debugging.
|
||||||
|
|
||||||
|
### getLocationServicesStatus()
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>
|
||||||
|
```
|
||||||
|
|
||||||
|
Memeriksa apakah provider lokasi aktif.
|
||||||
|
|
||||||
|
### addListener('onGnssStatus', …)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
addListener('onGnssStatus', (data: SatelliteStatus) => void): PluginListenerHandle
|
||||||
|
```
|
||||||
|
|
||||||
|
Menerima update status GNSS jika `emitGnssStatus: true` di setOptions.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Interfaces
|
## Interfaces
|
||||||
@ -102,7 +148,7 @@ PositioningData
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface PositioningData {
|
interface PositioningData {
|
||||||
source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK' | 'PREDICTED';
|
source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
@ -189,4 +235,4 @@ Contoh implementasi tersedia di folder /example-app dengan tombol:
|
|||||||
---
|
---
|
||||||
|
|
||||||
- Lisensi: MIT
|
- Lisensi: MIT
|
||||||
- Dibuat oleh: Tim Dumon 🇮🇩
|
- Dibuat oleh: Tim Dumon 🇮🇩
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import com.dumon.plugin.geolocation.wifi.WifiPositioningManager
|
|||||||
import com.dumon.plugin.geolocation.wifi.WifiScanResult
|
import com.dumon.plugin.geolocation.wifi.WifiScanResult
|
||||||
//import com.dumon.plugin.geolocation.fusion.SensorFusionManager
|
//import com.dumon.plugin.geolocation.fusion.SensorFusionManager
|
||||||
import com.dumon.plugin.geolocation.utils.PermissionUtils
|
import com.dumon.plugin.geolocation.utils.PermissionUtils
|
||||||
|
import com.dumon.plugin.geolocation.utils.LogUtils
|
||||||
import com.getcapacitor.annotation.PermissionCallback
|
import com.getcapacitor.annotation.PermissionCallback
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@ -67,9 +68,9 @@ class DumonGeolocation : Plugin() {
|
|||||||
private var prevSpeed = 0f
|
private var prevSpeed = 0f
|
||||||
private var prevDirection = 0f
|
private var prevDirection = 0f
|
||||||
// private val significantChangeThreshold = 0.00007 // ~7 meters
|
// private val significantChangeThreshold = 0.00007 // ~7 meters
|
||||||
private val significantChangeThreshold = 7 // ~7 meters
|
private var significantChangeThreshold = 7.0 // ~7 meters
|
||||||
private val speedChangeThreshold = 0.5f // m/s
|
private var speedChangeThreshold = 0.5f // m/s
|
||||||
private val directionChangeThreshold = 0.17f // ~10 deg
|
private var directionChangeThreshold = 0.17f // ~10 deg
|
||||||
|
|
||||||
// private val emitIntervalMs: Long = 500L
|
// private val emitIntervalMs: Long = 500L
|
||||||
private var emitIntervalMs: Long = 1000L // hard debounce
|
private var emitIntervalMs: Long = 1000L // hard debounce
|
||||||
@ -80,17 +81,32 @@ class DumonGeolocation : Plugin() {
|
|||||||
private var bufferedDrivingLocation: Location? = null
|
private var bufferedDrivingLocation: Location? = null
|
||||||
private var drivingEmitHandler: Handler? = null
|
private var drivingEmitHandler: Handler? = null
|
||||||
private var drivingEmitRunnable: Runnable? = null
|
private var drivingEmitRunnable: Runnable? = null
|
||||||
private val drivingEmitIntervalMs = 1600L
|
private var drivingEmitIntervalMs = 1600L
|
||||||
|
|
||||||
|
private var wifiScanIntervalMs = 3000L
|
||||||
|
private var enableWifiRtt = true
|
||||||
|
private var enableForwardPrediction = false
|
||||||
|
private var maxPredictionSeconds = 1.0
|
||||||
|
private var emitGnssStatus = false
|
||||||
|
private var suppressMockedUpdates = false
|
||||||
|
private var keepScreenOn = false
|
||||||
|
|
||||||
private var currentTrackingMode = GpsTrackingMode.NORMAL
|
private var currentTrackingMode = GpsTrackingMode.NORMAL
|
||||||
|
|
||||||
override fun load() {
|
override fun load() {
|
||||||
gpsManager = GpsStatusManager(
|
gpsManager = GpsStatusManager(
|
||||||
context,
|
context,
|
||||||
onSatelliteStatusUpdate = { satelliteStatus = it },
|
onSatelliteStatusUpdate = { status ->
|
||||||
|
satelliteStatus = status
|
||||||
|
if (emitGnssStatus) {
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
notifyListeners("onGnssStatus", buildGnssStatusData(status))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
onLocationUpdate = onLocationUpdate@{ location, isMocked ->
|
onLocationUpdate = onLocationUpdate@{ location, isMocked ->
|
||||||
if (location.latitude == 0.0 && location.longitude == 0.0) {
|
if (location.latitude == 0.0 && location.longitude == 0.0) {
|
||||||
Log.w("GPS_LOCATION", "Ignored location update: (0.0, 0.0)")
|
LogUtils.w("GPS_LOCATION", "Ignored location update: (0.0, 0.0)")
|
||||||
return@onLocationUpdate
|
return@onLocationUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +164,9 @@ class DumonGeolocation : Plugin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun stopDrivingEmitLoop() {
|
private fun stopDrivingEmitLoop() {
|
||||||
drivingEmitHandler?.removeCallbacks(drivingEmitRunnable!!)
|
drivingEmitRunnable?.let { runnable ->
|
||||||
|
drivingEmitHandler?.removeCallbacks(runnable)
|
||||||
|
}
|
||||||
drivingEmitHandler = null
|
drivingEmitHandler = null
|
||||||
drivingEmitRunnable = null
|
drivingEmitRunnable = null
|
||||||
bufferedDrivingLocation = null
|
bufferedDrivingLocation = null
|
||||||
@ -163,7 +181,9 @@ class DumonGeolocation : Plugin() {
|
|||||||
|
|
||||||
gpsManager?.start()
|
gpsManager?.start()
|
||||||
imuManager?.start()
|
imuManager?.start()
|
||||||
wifiManager?.startPeriodicScan(3000L)
|
wifiManager?.setEnableRtt(enableWifiRtt)
|
||||||
|
wifiManager?.startPeriodicScan(wifiScanIntervalMs)
|
||||||
|
applyKeepScreenOn(keepScreenOn)
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +193,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
imuManager?.stop()
|
imuManager?.stop()
|
||||||
wifiManager?.stopPeriodicScan()
|
wifiManager?.stopPeriodicScan()
|
||||||
stopDrivingEmitLoop()
|
stopDrivingEmitLoop()
|
||||||
|
applyKeepScreenOn(false)
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +205,18 @@ class DumonGeolocation : Plugin() {
|
|||||||
@PluginMethod
|
@PluginMethod
|
||||||
fun checkAndRequestPermissions(call: PluginCall) {
|
fun checkAndRequestPermissions(call: PluginCall) {
|
||||||
// requestAllPermissions(call, "checkAndRequestPermissions")
|
// requestAllPermissions(call, "checkAndRequestPermissions")
|
||||||
requestAllPermissions(call, "onPermissionResult")
|
val isLocationGranted =
|
||||||
|
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
|
val isWifiGranted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
ActivityCompat.checkSelfPermission(context, Manifest.permission.NEARBY_WIFI_DEVICES) == PackageManager.PERMISSION_GRANTED
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLocationGranted || !isWifiGranted) {
|
||||||
|
requestAllPermissions(call, "onPermissionResult")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val locationStatus = PermissionUtils.getPermissionStatus(
|
val locationStatus = PermissionUtils.getPermissionStatus(
|
||||||
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
|
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
@ -272,12 +304,12 @@ class DumonGeolocation : Plugin() {
|
|||||||
gpsManager?.startContinuousMode()
|
gpsManager?.startContinuousMode()
|
||||||
currentTrackingMode = GpsTrackingMode.DRIVING
|
currentTrackingMode = GpsTrackingMode.DRIVING
|
||||||
startDrivingEmitLoop()
|
startDrivingEmitLoop()
|
||||||
Log.d("DUMON_GEOLOCATION", "Switched to driving mode (continuous GPS)")
|
LogUtils.d("DUMON_GEOLOCATION", "Switched to driving mode (continuous GPS)")
|
||||||
} else {
|
} else {
|
||||||
gpsManager?.startPollingMode()
|
gpsManager?.startPollingMode()
|
||||||
currentTrackingMode = GpsTrackingMode.NORMAL
|
currentTrackingMode = GpsTrackingMode.NORMAL
|
||||||
stopDrivingEmitLoop()
|
stopDrivingEmitLoop()
|
||||||
Log.d("DUMON_GEOLOCATION", "Switched to normal mode (polling GPS)")
|
LogUtils.d("DUMON_GEOLOCATION", "Switched to normal mode (polling GPS)")
|
||||||
}
|
}
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
@ -302,9 +334,89 @@ class DumonGeolocation : Plugin() {
|
|||||||
call.resolve(result)
|
call.resolve(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PluginMethod
|
||||||
|
fun setOptions(call: PluginCall) {
|
||||||
|
call.getDouble("distanceThresholdMeters")?.let { significantChangeThreshold = it }
|
||||||
|
call.getDouble("speedChangeThreshold")?.let { speedChangeThreshold = it.toFloat() }
|
||||||
|
call.getDouble("directionChangeThreshold")?.let { directionChangeThreshold = it.toFloat() }
|
||||||
|
call.getInt("emitDebounceMs")?.let {
|
||||||
|
emitIntervalMs = it.toLong().coerceAtLeast(0L)
|
||||||
|
gpsManager?.setPollingInterval(emitIntervalMs)
|
||||||
|
}
|
||||||
|
call.getInt("drivingEmitIntervalMs")?.let {
|
||||||
|
drivingEmitIntervalMs = it.toLong().coerceAtLeast(200L)
|
||||||
|
if (currentTrackingMode == GpsTrackingMode.DRIVING) {
|
||||||
|
stopDrivingEmitLoop()
|
||||||
|
startDrivingEmitLoop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call.getInt("wifiScanIntervalMs")?.let {
|
||||||
|
wifiScanIntervalMs = it.toLong().coerceAtLeast(1000L)
|
||||||
|
}
|
||||||
|
call.getBoolean("enableWifiRtt")?.let {
|
||||||
|
enableWifiRtt = it
|
||||||
|
wifiManager?.setEnableRtt(it)
|
||||||
|
}
|
||||||
|
call.getBoolean("enableLogging")?.let { LogUtils.enabled = it }
|
||||||
|
call.getBoolean("enableForwardPrediction")?.let { enableForwardPrediction = it }
|
||||||
|
call.getDouble("maxPredictionSeconds")?.let { maxPredictionSeconds = it.coerceIn(0.0, 5.0) }
|
||||||
|
call.getBoolean("emitGnssStatus")?.let { emitGnssStatus = it }
|
||||||
|
call.getBoolean("suppressMockedUpdates")?.let { suppressMockedUpdates = it }
|
||||||
|
call.getBoolean("keepScreenOn")?.let {
|
||||||
|
keepScreenOn = it
|
||||||
|
applyKeepScreenOn(keepScreenOn)
|
||||||
|
}
|
||||||
|
call.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun applyKeepScreenOn(enabled: Boolean) {
|
||||||
|
val webView = bridge?.webView
|
||||||
|
val activity = bridge?.activity
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
webView?.keepScreenOn = enabled
|
||||||
|
val window = activity?.window
|
||||||
|
if (window != null) {
|
||||||
|
if (enabled) {
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
} else {
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PluginMethod
|
||||||
|
fun getGnssStatus(call: PluginCall) {
|
||||||
|
val status = satelliteStatus
|
||||||
|
if (status == null) {
|
||||||
|
call.resolve(JSObject())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val obj = JSObject()
|
||||||
|
obj.put("satellitesInView", status.satellitesInView)
|
||||||
|
obj.put("usedInFix", status.usedInFix)
|
||||||
|
val counts = JSObject()
|
||||||
|
status.constellationCounts.forEach { (k, v) -> counts.put(k, v) }
|
||||||
|
obj.put("constellationCounts", counts)
|
||||||
|
call.resolve(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
@PluginMethod
|
||||||
|
fun getLocationServicesStatus(call: PluginCall) {
|
||||||
|
val lm = context.getSystemService(android.content.Context.LOCATION_SERVICE) as android.location.LocationManager
|
||||||
|
val gpsEnabled = try { lm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER) } catch (_: Exception) { false }
|
||||||
|
val netEnabled = try { lm.isProviderEnabled(android.location.LocationManager.NETWORK_PROVIDER) } catch (_: Exception) { false }
|
||||||
|
val obj = JSObject().apply {
|
||||||
|
put("gpsEnabled", gpsEnabled)
|
||||||
|
put("networkEnabled", netEnabled)
|
||||||
|
}
|
||||||
|
call.resolve(obj)
|
||||||
|
}
|
||||||
|
|
||||||
private fun emitPositionUpdate(forceEmit: Boolean = false) {
|
private fun emitPositionUpdate(forceEmit: Boolean = false) {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (!forceEmit && now - lastEmitTimestamp < emitIntervalMs) return
|
if (!forceEmit && now - lastEmitTimestamp < emitIntervalMs) return
|
||||||
|
if (suppressMockedUpdates && isMockedLocation) return
|
||||||
|
|
||||||
val distance = calculateDistance(latestLatitude, latestLongitude, prevLatitude, prevLongitude)
|
val distance = calculateDistance(latestLatitude, latestLongitude, prevLatitude, prevLongitude)
|
||||||
val speedNow = latestImu?.speed ?: 0f
|
val speedNow = latestImu?.speed ?: 0f
|
||||||
@ -330,7 +442,10 @@ class DumonGeolocation : Plugin() {
|
|||||||
prevDirection = directionNow
|
prevDirection = directionNow
|
||||||
lastEmitTimestamp = now
|
lastEmitTimestamp = now
|
||||||
|
|
||||||
notifyListeners("onPositionUpdate", buildPositionData())
|
// Ensure listener notifications run on the main thread for consistency
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
notifyListeners("onPositionUpdate", buildPositionData())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,7 +460,7 @@ class DumonGeolocation : Plugin() {
|
|||||||
if (emitIntervalMs != targetInterval) {
|
if (emitIntervalMs != targetInterval) {
|
||||||
emitIntervalMs = targetInterval
|
emitIntervalMs = targetInterval
|
||||||
gpsManager?.setPollingInterval(targetInterval)
|
gpsManager?.setPollingInterval(targetInterval)
|
||||||
Log.d("DUMON_GEOLOCATION", "Auto-set emitIntervalMs = $emitIntervalMs ms")
|
LogUtils.d("DUMON_GEOLOCATION", "Auto-set emitIntervalMs = $emitIntervalMs ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
imuManager?.setSensorDelayBySpeed(speed)
|
imuManager?.setSensorDelayBySpeed(speed)
|
||||||
@ -369,23 +484,67 @@ class DumonGeolocation : Plugin() {
|
|||||||
return R * c
|
return R * c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildGnssStatusData(status: SatelliteStatus): JSObject {
|
||||||
|
val obj = JSObject()
|
||||||
|
obj.put("satellitesInView", status.satellitesInView)
|
||||||
|
obj.put("usedInFix", status.usedInFix)
|
||||||
|
val counts = JSObject()
|
||||||
|
status.constellationCounts.forEach { (k, v) -> counts.put(k, v) }
|
||||||
|
obj.put("constellationCounts", counts)
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildPositionData(): JSObject {
|
private fun buildPositionData(): JSObject {
|
||||||
val obj = JSObject()
|
val obj = JSObject()
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
|
||||||
|
var outLat = latestLatitude
|
||||||
|
var outLon = latestLongitude
|
||||||
|
var predicted = false
|
||||||
|
|
||||||
|
val imu = latestImu
|
||||||
|
val dtSec = ((now - (if (latestTimestamp > 0) latestTimestamp else now)).toDouble() / 1000.0)
|
||||||
|
if (enableForwardPrediction && imu != null && !isMockedLocation && dtSec > 0) {
|
||||||
|
val clampedDt = dtSec.coerceAtMost(maxPredictionSeconds)
|
||||||
|
val speed = imu.speed
|
||||||
|
val dir = imu.directionRad
|
||||||
|
val dNorth = speed * clampedDt * kotlin.math.cos(dir)
|
||||||
|
val dEast = speed * clampedDt * kotlin.math.sin(dir)
|
||||||
|
val R = 6371000.0
|
||||||
|
val latRad = degToRad(latestLatitude)
|
||||||
|
val dLat = (dNorth / R) * (180.0 / PI)
|
||||||
|
val dLon = (dEast / (R * kotlin.math.cos(latRad))) * (180.0 / PI)
|
||||||
|
outLat = latestLatitude + dLat
|
||||||
|
outLon = latestLongitude + dLon
|
||||||
|
predicted = true
|
||||||
|
}
|
||||||
|
|
||||||
obj.put("source", latestSource)
|
obj.put("source", latestSource)
|
||||||
obj.put("timestamp", if (latestTimestamp > 0) latestTimestamp else System.currentTimeMillis())
|
obj.put("timestamp", if (latestTimestamp > 0) latestTimestamp else now)
|
||||||
obj.put("latitude", latestLatitude)
|
obj.put("latitude", outLat)
|
||||||
obj.put("longitude", latestLongitude)
|
obj.put("longitude", outLon)
|
||||||
obj.put("accuracy", latestAccuracy)
|
obj.put("accuracy", latestAccuracy)
|
||||||
obj.put("isMocked", isMockedLocation)
|
obj.put("isMocked", isMockedLocation)
|
||||||
|
|
||||||
latestImu?.let {
|
// Always provide IMU-related fields to match TS definitions
|
||||||
obj.put("speed", it.speed)
|
val speedVal = latestImu?.speed ?: 0f
|
||||||
obj.put("acceleration", it.acceleration)
|
val accelVal = latestImu?.acceleration ?: 0f
|
||||||
obj.put("directionRad", it.directionRad)
|
val dirVal = latestImu?.directionRad ?: 0f
|
||||||
}
|
obj.put("speed", speedVal)
|
||||||
|
obj.put("acceleration", accelVal)
|
||||||
|
obj.put("directionRad", dirVal)
|
||||||
|
|
||||||
obj.put("predicted", latestSource == "PREDICTED")
|
obj.put("predicted", predicted)
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
override fun handleOnDestroy() {
|
||||||
|
gpsManager?.stop()
|
||||||
|
imuManager?.stop()
|
||||||
|
wifiManager?.stopPeriodicScan()
|
||||||
|
stopDrivingEmitLoop()
|
||||||
|
applyKeepScreenOn(false)
|
||||||
|
super.handleOnDestroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -13,7 +13,9 @@ import android.os.Handler
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.dumon.plugin.geolocation.utils.LogUtils
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
|
||||||
enum class GpsTrackingMode {
|
enum class GpsTrackingMode {
|
||||||
NORMAL,
|
NORMAL,
|
||||||
@ -73,7 +75,7 @@ class GpsStatusManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val info = "$providerTag Lat: ${location.latitude}, Lon: ${location.longitude}, Acc: ${location.accuracy} m @ $timestamp | Mock=$isMocked"
|
val info = "$providerTag Lat: ${location.latitude}, Lon: ${location.longitude}, Acc: ${location.accuracy} m @ $timestamp | Mock=$isMocked"
|
||||||
Log.d("GPS_LOCATION", info)
|
LogUtils.d("GPS_LOCATION", info)
|
||||||
|
|
||||||
onLocationUpdate(location, isMocked)
|
onLocationUpdate(location, isMocked)
|
||||||
locationManager.removeUpdates(this)
|
locationManager.removeUpdates(this)
|
||||||
@ -92,7 +94,7 @@ class GpsStatusManager(
|
|||||||
oneShotListener
|
oneShotListener
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Log.e("GPS_STATUS", "Missing location permission")
|
LogUtils.e("GPS_STATUS", "Missing location permission")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +108,10 @@ class GpsStatusManager(
|
|||||||
|
|
||||||
fun setPollingInterval(intervalMs: Long) {
|
fun setPollingInterval(intervalMs: Long) {
|
||||||
this.pollingIntervalMs = intervalMs
|
this.pollingIntervalMs = intervalMs
|
||||||
|
if (isPolling) {
|
||||||
|
handler.removeCallbacks(pollingRunnable)
|
||||||
|
handler.postDelayed(pollingRunnable, pollingIntervalMs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@ -114,11 +120,18 @@ class GpsStatusManager(
|
|||||||
currentMode = mode
|
currentMode = mode
|
||||||
|
|
||||||
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.e("GPS_STATUS", "Missing location permissions")
|
LogUtils.e("GPS_STATUS", "Missing location permissions")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
locationManager.registerGnssStatusCallback(gnssStatusCallback, null)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
locationManager.registerGnssStatusCallback(
|
||||||
|
ContextCompat.getMainExecutor(context),
|
||||||
|
gnssStatusCallback
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
locationManager.registerGnssStatusCallback(gnssStatusCallback, handler)
|
||||||
|
}
|
||||||
|
|
||||||
if (mode == GpsTrackingMode.DRIVING) {
|
if (mode == GpsTrackingMode.DRIVING) {
|
||||||
startContinuousUpdates()
|
startContinuousUpdates()
|
||||||
@ -139,12 +152,12 @@ class GpsStatusManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d("GPS_STATUS", "GPS started with mode: $mode")
|
LogUtils.d("GPS_STATUS", "GPS started with mode: $mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startContinuousUpdates() {
|
private fun startContinuousUpdates() {
|
||||||
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.e("GPS_STATUS", "Missing ACCESS_FINE_LOCATION permission")
|
LogUtils.e("GPS_STATUS", "Missing ACCESS_FINE_LOCATION permission")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +179,7 @@ class GpsStatusManager(
|
|||||||
continuousListener!!
|
continuousListener!!
|
||||||
)
|
)
|
||||||
|
|
||||||
Log.d("GPS_STATUS", "Started continuous location updates")
|
LogUtils.d("GPS_STATUS", "Started continuous location updates")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startContinuousMode() {
|
fun startContinuousMode() {
|
||||||
@ -188,7 +201,7 @@ class GpsStatusManager(
|
|||||||
locationManager.removeUpdates(it)
|
locationManager.removeUpdates(it)
|
||||||
continuousListener = null
|
continuousListener = null
|
||||||
}
|
}
|
||||||
Log.d("GPS_STATUS", "GPS stopped for mode: $currentMode")
|
LogUtils.d("GPS_STATUS", "GPS stopped for mode: $currentMode")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getConstellationName(type: Int): String {
|
private fun getConstellationName(type: Int): String {
|
||||||
@ -209,4 +222,4 @@ data class SatelliteStatus(
|
|||||||
val satellitesInView: Int,
|
val satellitesInView: Int,
|
||||||
val usedInFix: Int,
|
val usedInFix: Int,
|
||||||
val constellationCounts: Map<String, Int>
|
val constellationCounts: Map<String, Int>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package com.dumon.plugin.geolocation.imu
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.hardware.*
|
import android.hardware.*
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.dumon.plugin.geolocation.utils.LogUtils
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
class ImuSensorManager(
|
class ImuSensorManager(
|
||||||
@ -35,12 +36,12 @@ class ImuSensorManager(
|
|||||||
accelerometer?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) }
|
accelerometer?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) }
|
||||||
gyroscope?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) }
|
gyroscope?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) }
|
||||||
rotationVector?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) }
|
rotationVector?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) }
|
||||||
Log.d("IMU_SENSOR", "IMU sensor tracking started")
|
LogUtils.d("IMU_SENSOR", "IMU sensor tracking started")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun stop() {
|
||||||
sensorManager.unregisterListener(this)
|
sensorManager.unregisterListener(this)
|
||||||
Log.d("IMU_SENSOR", "IMU sensor tracking stopped")
|
LogUtils.d("IMU_SENSOR", "IMU sensor tracking stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSensorDelayBySpeed(speed: Float) {
|
fun setSensorDelayBySpeed(speed: Float) {
|
||||||
@ -54,7 +55,7 @@ class ImuSensorManager(
|
|||||||
if (desiredDelay != currentDelay) {
|
if (desiredDelay != currentDelay) {
|
||||||
currentDelay = desiredDelay
|
currentDelay = desiredDelay
|
||||||
restartSensorsWithDelay(currentDelay)
|
restartSensorsWithDelay(currentDelay)
|
||||||
Log.d("IMU_SENSOR", "Sensor delay changed to $currentDelay")
|
LogUtils.d("IMU_SENSOR", "Sensor delay changed to $currentDelay")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ class ImuSensorManager(
|
|||||||
|
|
||||||
emitCombinedImuData(speed, acceleration, latestDirectionRad)
|
emitCombinedImuData(speed, acceleration, latestDirectionRad)
|
||||||
|
|
||||||
Log.d("IMU_SENSOR", "Accel x: %.3f y: %.3f z: %.3f | Speed: %.3f | AccelMag: %.3f | Dir: %.2f rad".format(
|
LogUtils.d("IMU_SENSOR", "Accel x: %.3f y: %.3f z: %.3f | Speed: %.3f | AccelMag: %.3f | Dir: %.2f rad".format(
|
||||||
lastAccel[0], lastAccel[1], lastAccel[2], speed, acceleration, latestDirectionRad
|
lastAccel[0], lastAccel[1], lastAccel[2], speed, acceleration, latestDirectionRad
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -165,4 +166,4 @@ data class ImuData(
|
|||||||
val speed: Float,
|
val speed: Float,
|
||||||
val acceleration: Float,
|
val acceleration: Float,
|
||||||
val directionRad: Float
|
val directionRad: Float
|
||||||
)
|
)
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.dumon.plugin.geolocation.utils
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
object LogUtils {
|
||||||
|
@Volatile
|
||||||
|
var enabled: Boolean = true
|
||||||
|
|
||||||
|
fun d(tag: String, msg: String) {
|
||||||
|
if (enabled) Log.d(tag, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun w(tag: String, msg: String) {
|
||||||
|
if (enabled) Log.w(tag, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun e(tag: String, msg: String, tr: Throwable? = null) {
|
||||||
|
if (!enabled) return
|
||||||
|
if (tr != null) Log.e(tag, msg, tr) else Log.e(tag, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -2,6 +2,9 @@ package com.dumon.plugin.geolocation.wifi
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.wifi.ScanResult
|
import android.net.wifi.ScanResult
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
@ -10,8 +13,9 @@ import android.net.wifi.rtt.RangingResultCallback
|
|||||||
import android.net.wifi.rtt.WifiRttManager
|
import android.net.wifi.rtt.WifiRttManager
|
||||||
import android.os.*
|
import android.os.*
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.dumon.plugin.geolocation.utils.LogUtils
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import java.util.concurrent.Executors
|
import androidx.core.content.ContextCompat
|
||||||
|
|
||||||
class WifiPositioningManager(
|
class WifiPositioningManager(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
@ -30,6 +34,9 @@ class WifiPositioningManager(
|
|||||||
private var isScanning = false
|
private var isScanning = false
|
||||||
|
|
||||||
private var lastWifiScanAps: MutableList<WifiAp> = mutableListOf()
|
private var lastWifiScanAps: MutableList<WifiAp> = mutableListOf()
|
||||||
|
private var scanResultsReceiver: BroadcastReceiver? = null
|
||||||
|
private var scanReceiverRegistered: Boolean = false
|
||||||
|
private var enableRtt: Boolean = true
|
||||||
|
|
||||||
fun isRttSupported(): Boolean {
|
fun isRttSupported(): Boolean {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && wifiRttManager != null && wifiManager.isWifiEnabled
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && wifiRttManager != null && wifiManager.isWifiEnabled
|
||||||
@ -37,6 +44,7 @@ class WifiPositioningManager(
|
|||||||
|
|
||||||
fun startPeriodicScan(intervalMs: Long = 3000L) {
|
fun startPeriodicScan(intervalMs: Long = 3000L) {
|
||||||
isScanning = true
|
isScanning = true
|
||||||
|
registerScanResultsReceiverIfNeeded()
|
||||||
handler.post(object : Runnable {
|
handler.post(object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (isScanning) {
|
if (isScanning) {
|
||||||
@ -50,6 +58,7 @@ class WifiPositioningManager(
|
|||||||
fun stopPeriodicScan() {
|
fun stopPeriodicScan() {
|
||||||
isScanning = false
|
isScanning = false
|
||||||
handler.removeCallbacksAndMessages(null)
|
handler.removeCallbacksAndMessages(null)
|
||||||
|
unregisterScanResultsReceiverIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startWifiScan() {
|
fun startWifiScan() {
|
||||||
@ -59,22 +68,50 @@ class WifiPositioningManager(
|
|||||||
) == PackageManager.PERMISSION_GRANTED
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
) {
|
) {
|
||||||
val success = wifiManager.startScan()
|
val success = wifiManager.startScan()
|
||||||
if (success) {
|
if (!success) {
|
||||||
val results = wifiManager.scanResults
|
LogUtils.e("WIFI_POSITION", "Wi-Fi scan failed")
|
||||||
processScanResults(results)
|
|
||||||
if (isRttSupported()) {
|
|
||||||
startRttRanging(results)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e("WIFI_POSITION", "Wi-Fi scan failed")
|
|
||||||
onWifiPositioningUpdate(WifiScanResult(0, emptyList()))
|
onWifiPositioningUpdate(WifiScanResult(0, emptyList()))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e("WIFI_POSITION", "Missing ACCESS_FINE_LOCATION permission")
|
LogUtils.e("WIFI_POSITION", "Missing ACCESS_FINE_LOCATION permission")
|
||||||
onWifiPositioningUpdate(WifiScanResult(0, emptyList()))
|
onWifiPositioningUpdate(WifiScanResult(0, emptyList()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun registerScanResultsReceiverIfNeeded() {
|
||||||
|
if (scanReceiverRegistered) return
|
||||||
|
scanResultsReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
if (intent?.action == WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) {
|
||||||
|
val results = wifiManager.scanResults
|
||||||
|
processScanResults(results)
|
||||||
|
if (enableRtt && isRttSupported()) {
|
||||||
|
startRttRanging(results)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val filter = IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
|
||||||
|
try {
|
||||||
|
context.registerReceiver(scanResultsReceiver, filter)
|
||||||
|
scanReceiverRegistered = true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LogUtils.e("WIFI_POSITION", "Failed to register scan receiver", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unregisterScanResultsReceiverIfNeeded() {
|
||||||
|
if (!scanReceiverRegistered) return
|
||||||
|
try {
|
||||||
|
context.unregisterReceiver(scanResultsReceiver)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
// Receiver already unregistered
|
||||||
|
} finally {
|
||||||
|
scanReceiverRegistered = false
|
||||||
|
scanResultsReceiver = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun processScanResults(results: List<ScanResult>) {
|
private fun processScanResults(results: List<ScanResult>) {
|
||||||
lastWifiScanAps = results.map { result ->
|
lastWifiScanAps = results.map { result ->
|
||||||
WifiAp(
|
WifiAp(
|
||||||
@ -84,9 +121,9 @@ class WifiPositioningManager(
|
|||||||
)
|
)
|
||||||
}.toMutableList()
|
}.toMutableList()
|
||||||
|
|
||||||
Log.d("WIFI_POSITION", "Wi-Fi scan → AP count: ${lastWifiScanAps.size}")
|
LogUtils.d("WIFI_POSITION", "Wi-Fi scan → AP count: ${lastWifiScanAps.size}")
|
||||||
lastWifiScanAps.forEach {
|
lastWifiScanAps.forEach {
|
||||||
Log.d("WIFI_POSITION", "SSID: ${it.ssid}, BSSID: ${it.bssid}, RSSI: ${it.rssi} dBm")
|
LogUtils.d("WIFI_POSITION", "SSID: ${it.ssid}, BSSID: ${it.bssid}, RSSI: ${it.rssi} dBm")
|
||||||
}
|
}
|
||||||
|
|
||||||
onWifiPositioningUpdate(WifiScanResult(lastWifiScanAps.size, lastWifiScanAps))
|
onWifiPositioningUpdate(WifiScanResult(lastWifiScanAps.size, lastWifiScanAps))
|
||||||
@ -94,13 +131,13 @@ class WifiPositioningManager(
|
|||||||
|
|
||||||
private fun startRttRanging(results: List<ScanResult>) {
|
private fun startRttRanging(results: List<ScanResult>) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P || wifiRttManager == null) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P || wifiRttManager == null) {
|
||||||
Log.d("WIFI_POSITION", "RTT not supported or WifiRttManager is null.")
|
LogUtils.d("WIFI_POSITION", "RTT not supported or WifiRttManager is null.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val rttCapableAps = results.filter { it.is80211mcResponder }
|
val rttCapableAps = results.filter { it.is80211mcResponder }
|
||||||
if (rttCapableAps.isEmpty()) {
|
if (rttCapableAps.isEmpty()) {
|
||||||
Log.d("WIFI_POSITION", "No RTT-capable AP found.")
|
LogUtils.d("WIFI_POSITION", "No RTT-capable AP found.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,10 +148,10 @@ class WifiPositioningManager(
|
|||||||
try {
|
try {
|
||||||
wifiRttManager.startRanging(
|
wifiRttManager.startRanging(
|
||||||
rangingRequest,
|
rangingRequest,
|
||||||
Executors.newSingleThreadExecutor(),
|
ContextCompat.getMainExecutor(context),
|
||||||
object : RangingResultCallback() {
|
object : RangingResultCallback() {
|
||||||
override fun onRangingFailure(code: Int) {
|
override fun onRangingFailure(code: Int) {
|
||||||
Log.e("WIFI_POSITION", "RTT Ranging failed: $code")
|
LogUtils.e("WIFI_POSITION", "RTT Ranging failed: $code")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRangingResults(results: List<android.net.wifi.rtt.RangingResult>) {
|
override fun onRangingResults(results: List<android.net.wifi.rtt.RangingResult>) {
|
||||||
@ -123,7 +160,7 @@ class WifiPositioningManager(
|
|||||||
val distance = if (result.status == android.net.wifi.rtt.RangingResult.STATUS_SUCCESS) {
|
val distance = if (result.status == android.net.wifi.rtt.RangingResult.STATUS_SUCCESS) {
|
||||||
result.distanceMm / 1000.0
|
result.distanceMm / 1000.0
|
||||||
} else {
|
} else {
|
||||||
Log.w("WIFI_POSITION", "RTT distance unavailable for ${result.macAddress}")
|
LogUtils.w("WIFI_POSITION", "RTT distance unavailable for ${result.macAddress}")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +168,7 @@ class WifiPositioningManager(
|
|||||||
lastWifiScanAps[idx] = lastWifiScanAps[idx].copy(distance = distance)
|
lastWifiScanAps[idx] = lastWifiScanAps[idx].copy(distance = distance)
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(
|
LogUtils.d(
|
||||||
"WIFI_POSITION",
|
"WIFI_POSITION",
|
||||||
if (distance != null)
|
if (distance != null)
|
||||||
"RTT → ${mac}, Distance: ${distance} m"
|
"RTT → ${mac}, Distance: ${distance} m"
|
||||||
@ -145,9 +182,13 @@ class WifiPositioningManager(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} catch (e: SecurityException) {
|
} catch (e: SecurityException) {
|
||||||
Log.e("WIFI_POSITION", "SecurityException: Missing NEARBY_WIFI_DEVICES permission", e)
|
LogUtils.e("WIFI_POSITION", "SecurityException: Missing NEARBY_WIFI_DEVICES permission", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setEnableRtt(enable: Boolean) {
|
||||||
|
enableRtt = enable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class WifiAp(
|
data class WifiAp(
|
||||||
@ -160,4 +201,4 @@ data class WifiAp(
|
|||||||
data class WifiScanResult(
|
data class WifiScanResult(
|
||||||
val apCount: Int,
|
val apCount: Int,
|
||||||
val aps: List<WifiAp>
|
val aps: List<WifiAp>
|
||||||
)
|
)
|
||||||
|
|||||||
194
dist/docs.json
vendored
194
dist/docs.json
vendored
@ -49,6 +49,46 @@
|
|||||||
],
|
],
|
||||||
"slug": "checkandrequestpermissions"
|
"slug": "checkandrequestpermissions"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "setOptions",
|
||||||
|
"signature": "(options: DumonGeoOptions) => Promise<void>",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "options",
|
||||||
|
"docs": "",
|
||||||
|
"type": "DumonGeoOptions"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": "Promise<void>",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [
|
||||||
|
"DumonGeoOptions"
|
||||||
|
],
|
||||||
|
"slug": "setoptions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "getGnssStatus",
|
||||||
|
"signature": "() => Promise<SatelliteStatus | null>",
|
||||||
|
"parameters": [],
|
||||||
|
"returns": "Promise<SatelliteStatus | null>",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [
|
||||||
|
"SatelliteStatus"
|
||||||
|
],
|
||||||
|
"slug": "getgnssstatus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "getLocationServicesStatus",
|
||||||
|
"signature": "() => Promise<{ gpsEnabled: boolean; networkEnabled: boolean; }>",
|
||||||
|
"parameters": [],
|
||||||
|
"returns": "Promise<{ gpsEnabled: boolean; networkEnabled: boolean; }>",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"slug": "getlocationservicesstatus"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "configureEdgeToEdge",
|
"name": "configureEdgeToEdge",
|
||||||
"signature": "(options: { bgColor: string; style: 'DARK' | 'LIGHT'; overlay?: boolean; }) => Promise<void>",
|
"signature": "(options: { bgColor: string; style: 'DARK' | 'LIGHT'; overlay?: boolean; }) => Promise<void>",
|
||||||
@ -104,6 +144,30 @@
|
|||||||
"PositioningData"
|
"PositioningData"
|
||||||
],
|
],
|
||||||
"slug": "addlisteneronpositionupdate-"
|
"slug": "addlisteneronpositionupdate-"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "addListener",
|
||||||
|
"signature": "(eventName: 'onGnssStatus', listenerFunc: (data: SatelliteStatus) => void) => PluginListenerHandle",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "eventName",
|
||||||
|
"docs": "",
|
||||||
|
"type": "'onGnssStatus'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "listenerFunc",
|
||||||
|
"docs": "",
|
||||||
|
"type": "(data: SatelliteStatus) => void"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": "PluginListenerHandle",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [
|
||||||
|
"PluginListenerHandle",
|
||||||
|
"SatelliteStatus"
|
||||||
|
],
|
||||||
|
"slug": "addlistenerongnssstatus-"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"properties": []
|
"properties": []
|
||||||
@ -211,6 +275,136 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "DumonGeoOptions",
|
||||||
|
"slug": "dumongeooptions",
|
||||||
|
"docs": "",
|
||||||
|
"tags": [],
|
||||||
|
"methods": [],
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "distanceThresholdMeters",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "speedChangeThreshold",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "directionChangeThreshold",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "emitDebounceMs",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "drivingEmitIntervalMs",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wifiScanIntervalMs",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enableWifiRtt",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "boolean | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enableLogging",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "boolean | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enableForwardPrediction",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "boolean | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maxPredictionSeconds",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "emitGnssStatus",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "boolean | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "suppressMockedUpdates",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "boolean | undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keepScreenOn",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "boolean | undefined"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SatelliteStatus",
|
||||||
|
"slug": "satellitestatus",
|
||||||
|
"docs": "",
|
||||||
|
"tags": [],
|
||||||
|
"methods": [],
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "satellitesInView",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "usedInFix",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "constellationCounts",
|
||||||
|
"tags": [],
|
||||||
|
"docs": "",
|
||||||
|
"complexTypes": [],
|
||||||
|
"type": "{ [key: string]: number; }"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "PluginListenerHandle",
|
"name": "PluginListenerHandle",
|
||||||
"slug": "pluginlistenerhandle",
|
"slug": "pluginlistenerhandle",
|
||||||
|
|||||||
29
dist/esm/definitions.d.ts
vendored
29
dist/esm/definitions.d.ts
vendored
@ -11,6 +11,28 @@ export interface PositioningData {
|
|||||||
isMocked: boolean;
|
isMocked: boolean;
|
||||||
predicted?: boolean;
|
predicted?: boolean;
|
||||||
}
|
}
|
||||||
|
export interface SatelliteStatus {
|
||||||
|
satellitesInView: number;
|
||||||
|
usedInFix: number;
|
||||||
|
constellationCounts: {
|
||||||
|
[key: string]: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface DumonGeoOptions {
|
||||||
|
distanceThresholdMeters?: number;
|
||||||
|
speedChangeThreshold?: number;
|
||||||
|
directionChangeThreshold?: number;
|
||||||
|
emitDebounceMs?: number;
|
||||||
|
drivingEmitIntervalMs?: number;
|
||||||
|
wifiScanIntervalMs?: number;
|
||||||
|
enableWifiRtt?: boolean;
|
||||||
|
enableLogging?: boolean;
|
||||||
|
enableForwardPrediction?: boolean;
|
||||||
|
maxPredictionSeconds?: number;
|
||||||
|
emitGnssStatus?: boolean;
|
||||||
|
suppressMockedUpdates?: boolean;
|
||||||
|
keepScreenOn?: boolean;
|
||||||
|
}
|
||||||
export interface PermissionStatus {
|
export interface PermissionStatus {
|
||||||
location: 'granted' | 'denied';
|
location: 'granted' | 'denied';
|
||||||
wifi: 'granted' | 'denied';
|
wifi: 'granted' | 'denied';
|
||||||
@ -20,6 +42,12 @@ export interface DumonGeolocationPlugin {
|
|||||||
stopPositioning(): Promise<void>;
|
stopPositioning(): Promise<void>;
|
||||||
getLatestPosition(): Promise<PositioningData>;
|
getLatestPosition(): Promise<PositioningData>;
|
||||||
checkAndRequestPermissions(): Promise<PermissionStatus>;
|
checkAndRequestPermissions(): Promise<PermissionStatus>;
|
||||||
|
setOptions(options: DumonGeoOptions): Promise<void>;
|
||||||
|
getGnssStatus(): Promise<SatelliteStatus | null>;
|
||||||
|
getLocationServicesStatus(): Promise<{
|
||||||
|
gpsEnabled: boolean;
|
||||||
|
networkEnabled: boolean;
|
||||||
|
}>;
|
||||||
configureEdgeToEdge(options: {
|
configureEdgeToEdge(options: {
|
||||||
bgColor: string;
|
bgColor: string;
|
||||||
style: 'DARK' | 'LIGHT';
|
style: 'DARK' | 'LIGHT';
|
||||||
@ -29,4 +57,5 @@ export interface DumonGeolocationPlugin {
|
|||||||
mode: 'normal' | 'driving';
|
mode: 'normal' | 'driving';
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
addListener(eventName: 'onPositionUpdate', listenerFunc: (data: PositioningData) => void): PluginListenerHandle;
|
addListener(eventName: 'onPositionUpdate', listenerFunc: (data: PositioningData) => void): PluginListenerHandle;
|
||||||
|
addListener(eventName: 'onGnssStatus', listenerFunc: (data: SatelliteStatus) => void): PluginListenerHandle;
|
||||||
}
|
}
|
||||||
|
|||||||
2
dist/esm/definitions.js.map
vendored
2
dist/esm/definitions.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n// export interface SatelliteStatus {\n// satellitesInView: number;\n// usedInFix: number;\n// constellationCounts: { [key: string]: number };\n// }\n\n// export interface WifiAp {\n// ssid: string;\n// bssid: string;\n// rssi: number;\n// distance?: number;\n// }\n\n// export interface WifiScanResult {\n// apCount: number;\n// aps: WifiAp[];\n// }\n\n// export interface ImuData {\n// accelX: number;\n// accelY: number;\n// accelZ: number;\n// gyroX: number;\n// gyroY: number;\n// gyroZ: number;\n// speed?: number;\n// acceleration?: number;\n// directionRad?: number;\n// }\n\n// export interface GpsData {\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n// satellitesInView?: number;\n// usedInFix?: number;\n// constellationCounts?: { [key: string]: number };\n// }\n\n// export interface PositioningData {\n// source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n// timestamp: number;\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n\n// gnssData?: SatelliteStatus;\n// wifiData?: WifiAp[];\n// imuData?: ImuData;\n// }\n\nexport interface PositioningData {\n source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n timestamp: number;\n latitude: number;\n longitude: number;\n accuracy: number;\n speed: number;\n acceleration: number;\n directionRad: number;\n isMocked: boolean;\n predicted?: boolean;\n}\n\nexport interface PermissionStatus {\n location: 'granted' | 'denied';\n wifi: 'granted' | 'denied';\n}\n\nexport interface DumonGeolocationPlugin {\n startPositioning(): Promise<void>;\n stopPositioning(): Promise<void>;\n getLatestPosition(): Promise<PositioningData>;\n checkAndRequestPermissions(): Promise<PermissionStatus>;\n\n configureEdgeToEdge(options: {\n bgColor: string;\n style: 'DARK' | 'LIGHT';\n overlay?: boolean;\n }): Promise<void>;\n\n setGpsMode(options: { mode: 'normal' | 'driving' }): Promise<void>;\n\n addListener(\n eventName: 'onPositionUpdate',\n listenerFunc: (data: PositioningData) => void\n ): PluginListenerHandle;\n}"]}
|
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n// export interface SatelliteStatus {\n// satellitesInView: number;\n// usedInFix: number;\n// constellationCounts: { [key: string]: number };\n// }\n\n// export interface WifiAp {\n// ssid: string;\n// bssid: string;\n// rssi: number;\n// distance?: number;\n// }\n\n// export interface WifiScanResult {\n// apCount: number;\n// aps: WifiAp[];\n// }\n\n// export interface ImuData {\n// accelX: number;\n// accelY: number;\n// accelZ: number;\n// gyroX: number;\n// gyroY: number;\n// gyroZ: number;\n// speed?: number;\n// acceleration?: number;\n// directionRad?: number;\n// }\n\n// export interface GpsData {\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n// satellitesInView?: number;\n// usedInFix?: number;\n// constellationCounts?: { [key: string]: number };\n// }\n\n// export interface PositioningData {\n// source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n// timestamp: number;\n// latitude: number;\n// longitude: number;\n// accuracy: number;\n\n// gnssData?: SatelliteStatus;\n// wifiData?: WifiAp[];\n// imuData?: ImuData;\n// }\n\nexport interface PositioningData {\n source: 'GNSS' | 'WIFI' | 'FUSED' | 'MOCK';\n timestamp: number;\n latitude: number;\n longitude: number;\n accuracy: number;\n speed: number;\n acceleration: number;\n directionRad: number;\n isMocked: boolean;\n predicted?: boolean;\n}\n\nexport interface SatelliteStatus {\n satellitesInView: number;\n usedInFix: number;\n constellationCounts: { [key: string]: number };\n}\n\nexport interface DumonGeoOptions {\n distanceThresholdMeters?: number;\n speedChangeThreshold?: number;\n directionChangeThreshold?: number;\n emitDebounceMs?: number;\n drivingEmitIntervalMs?: number;\n wifiScanIntervalMs?: number;\n enableWifiRtt?: boolean;\n enableLogging?: boolean;\n enableForwardPrediction?: boolean;\n maxPredictionSeconds?: number;\n emitGnssStatus?: boolean;\n suppressMockedUpdates?: boolean;\n keepScreenOn?: boolean;\n}\n\nexport interface PermissionStatus {\n location: 'granted' | 'denied';\n wifi: 'granted' | 'denied';\n}\n\nexport interface DumonGeolocationPlugin {\n startPositioning(): Promise<void>;\n stopPositioning(): Promise<void>;\n getLatestPosition(): Promise<PositioningData>;\n checkAndRequestPermissions(): Promise<PermissionStatus>;\n setOptions(options: DumonGeoOptions): Promise<void>;\n getGnssStatus(): Promise<SatelliteStatus | null>;\n getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>;\n\n configureEdgeToEdge(options: {\n bgColor: string;\n style: 'DARK' | 'LIGHT';\n overlay?: boolean;\n }): Promise<void>;\n\n setGpsMode(options: { mode: 'normal' | 'driving' }): Promise<void>;\n\n addListener(\n eventName: 'onPositionUpdate',\n listenerFunc: (data: PositioningData) => void\n ): PluginListenerHandle;\n\n addListener(\n eventName: 'onGnssStatus',\n listenerFunc: (data: SatelliteStatus) => void\n ): PluginListenerHandle;\n}\n"]}
|
||||||
8
dist/esm/web.d.ts
vendored
8
dist/esm/web.d.ts
vendored
@ -1,5 +1,5 @@
|
|||||||
import { WebPlugin } from '@capacitor/core';
|
import { WebPlugin } from '@capacitor/core';
|
||||||
import type { PositioningData } from './definitions';
|
import type { PositioningData, DumonGeoOptions, SatelliteStatus } from './definitions';
|
||||||
export declare class DumonGeolocationWeb extends WebPlugin {
|
export declare class DumonGeolocationWeb extends WebPlugin {
|
||||||
startPositioning(): Promise<void>;
|
startPositioning(): Promise<void>;
|
||||||
stopPositioning(): Promise<void>;
|
stopPositioning(): Promise<void>;
|
||||||
@ -13,4 +13,10 @@ export declare class DumonGeolocationWeb extends WebPlugin {
|
|||||||
style: 'DARK' | 'LIGHT';
|
style: 'DARK' | 'LIGHT';
|
||||||
overlay?: boolean;
|
overlay?: boolean;
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
|
setOptions(_options: DumonGeoOptions): Promise<void>;
|
||||||
|
getGnssStatus(): Promise<SatelliteStatus | null>;
|
||||||
|
getLocationServicesStatus(): Promise<{
|
||||||
|
gpsEnabled: boolean;
|
||||||
|
networkEnabled: boolean;
|
||||||
|
}>;
|
||||||
}
|
}
|
||||||
|
|||||||
10
dist/esm/web.js
vendored
10
dist/esm/web.js
vendored
@ -31,5 +31,15 @@ export class DumonGeolocationWeb extends WebPlugin {
|
|||||||
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
async setOptions(_options) {
|
||||||
|
// No-op on web
|
||||||
|
}
|
||||||
|
async getGnssStatus() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
async getLocationServicesStatus() {
|
||||||
|
// Web stub; assume enabled
|
||||||
|
return { gpsEnabled: true, networkEnabled: true };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=web.js.map
|
//# sourceMappingURL=web.js.map
|
||||||
2
dist/esm/web.js.map
vendored
2
dist/esm/web.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChD,KAAK,CAAC,gBAAgB;QACpB,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;QACtF,OAAO;YACL,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,CAAC;YACZ,QAAQ,EAAE,GAAG;YACb,KAAK,EAAE,CAAC;YACR,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,0BAA0B;QAI9B,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC/E,OAAO;YACL,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,OAIzB;QACC,OAAO,CAAC,IAAI,CAAC,6DAA6D,EAAE,OAAO,CAAC,CAAC;QACrF,QAAQ;IACV,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\nimport type { PositioningData } from './definitions';\n\nexport class DumonGeolocationWeb extends WebPlugin {\n async startPositioning(): Promise<void> {\n console.log('DumonGeolocationWeb: startPositioning() called (no-op)');\n }\n\n async stopPositioning(): Promise<void> {\n console.log('DumonGeolocationWeb: stopPositioning() called (no-op)');\n }\n\n async getLatestPosition(): Promise<PositioningData> {\n console.log('DumonGeolocationWeb: getLatestPosition() called (returning dummy data)');\n return {\n source: 'GNSS',\n timestamp: Date.now(),\n latitude: 0,\n longitude: 0,\n accuracy: 999,\n speed: 0,\n acceleration: 0,\n directionRad: 0,\n isMocked: false,\n };\n }\n\n async checkAndRequestPermissions(): Promise<{\n location: 'granted' | 'denied';\n wifi: 'granted' | 'denied';\n }> {\n console.info('[dumon-geolocation] checkAndRequestPermissions mocked for web.');\n return {\n location: 'granted',\n wifi: 'granted',\n };\n }\n\n async configureEdgeToEdge(options: {\n bgColor: string;\n style: 'DARK' | 'LIGHT';\n overlay?: boolean;\n }): Promise<void> {\n console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);\n // No-op\n }\n}"]}
|
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChD,KAAK,CAAC,gBAAgB;QACpB,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;QACtF,OAAO;YACL,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,CAAC;YACZ,QAAQ,EAAE,GAAG;YACb,KAAK,EAAE,CAAC;YACR,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,0BAA0B;QAI9B,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC/E,OAAO;YACL,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,OAIzB;QACC,OAAO,CAAC,IAAI,CAAC,6DAA6D,EAAE,OAAO,CAAC,CAAC;QACrF,QAAQ;IACV,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAyB;QACxC,eAAe;IACjB,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,yBAAyB;QAC7B,2BAA2B;QAC3B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IACpD,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\nimport type { PositioningData, DumonGeoOptions, SatelliteStatus } from './definitions';\n\nexport class DumonGeolocationWeb extends WebPlugin {\n async startPositioning(): Promise<void> {\n console.log('DumonGeolocationWeb: startPositioning() called (no-op)');\n }\n\n async stopPositioning(): Promise<void> {\n console.log('DumonGeolocationWeb: stopPositioning() called (no-op)');\n }\n\n async getLatestPosition(): Promise<PositioningData> {\n console.log('DumonGeolocationWeb: getLatestPosition() called (returning dummy data)');\n return {\n source: 'GNSS',\n timestamp: Date.now(),\n latitude: 0,\n longitude: 0,\n accuracy: 999,\n speed: 0,\n acceleration: 0,\n directionRad: 0,\n isMocked: false,\n };\n }\n\n async checkAndRequestPermissions(): Promise<{\n location: 'granted' | 'denied';\n wifi: 'granted' | 'denied';\n }> {\n console.info('[dumon-geolocation] checkAndRequestPermissions mocked for web.');\n return {\n location: 'granted',\n wifi: 'granted',\n };\n }\n\n async configureEdgeToEdge(options: {\n bgColor: string;\n style: 'DARK' | 'LIGHT';\n overlay?: boolean;\n }): Promise<void> {\n console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);\n // No-op\n }\n\n async setOptions(_options: DumonGeoOptions): Promise<void> {\n // No-op on web\n }\n\n async getGnssStatus(): Promise<SatelliteStatus | null> {\n return null;\n }\n\n async getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }> {\n // Web stub; assume enabled\n return { gpsEnabled: true, networkEnabled: true };\n }\n}\n"]}
|
||||||
10
dist/plugin.cjs.js
vendored
10
dist/plugin.cjs.js
vendored
@ -38,6 +38,16 @@ class DumonGeolocationWeb extends core.WebPlugin {
|
|||||||
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
async setOptions(_options) {
|
||||||
|
// No-op on web
|
||||||
|
}
|
||||||
|
async getGnssStatus() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
async getLocationServicesStatus() {
|
||||||
|
// Web stub; assume enabled
|
||||||
|
return { gpsEnabled: true, networkEnabled: true };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var web = /*#__PURE__*/Object.freeze({
|
var web = /*#__PURE__*/Object.freeze({
|
||||||
|
|||||||
2
dist/plugin.cjs.js.map
vendored
2
dist/plugin.cjs.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst DumonGeolocation = registerPlugin('DumonGeolocation', {\n web: () => import('./web').then((m) => new m.DumonGeolocationWeb()),\n});\nexport * from './definitions';\nexport { DumonGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class DumonGeolocationWeb extends WebPlugin {\n async startPositioning() {\n console.log('DumonGeolocationWeb: startPositioning() called (no-op)');\n }\n async stopPositioning() {\n console.log('DumonGeolocationWeb: stopPositioning() called (no-op)');\n }\n async getLatestPosition() {\n console.log('DumonGeolocationWeb: getLatestPosition() called (returning dummy data)');\n return {\n source: 'GNSS',\n timestamp: Date.now(),\n latitude: 0,\n longitude: 0,\n accuracy: 999,\n speed: 0,\n acceleration: 0,\n directionRad: 0,\n isMocked: false,\n };\n }\n async checkAndRequestPermissions() {\n console.info('[dumon-geolocation] checkAndRequestPermissions mocked for web.');\n return {\n location: 'granted',\n wifi: 'granted',\n };\n }\n async configureEdgeToEdge(options) {\n console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);\n // No-op\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,gBAAgB,GAAGA,mBAAc,CAAC,kBAAkB,EAAE;AAC5D,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;AACvE,CAAC;;ACFM,MAAM,mBAAmB,SAASC,cAAS,CAAC;AACnD,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC;AAC7E;AACA,IAAI,MAAM,eAAe,GAAG;AAC5B,QAAQ,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC;AAC5E;AACA,IAAI,MAAM,iBAAiB,GAAG;AAC9B,QAAQ,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC;AAC7F,QAAQ,OAAO;AACf,YAAY,MAAM,EAAE,MAAM;AAC1B,YAAY,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;AACjC,YAAY,QAAQ,EAAE,CAAC;AACvB,YAAY,SAAS,EAAE,CAAC;AACxB,YAAY,QAAQ,EAAE,GAAG;AACzB,YAAY,KAAK,EAAE,CAAC;AACpB,YAAY,YAAY,EAAE,CAAC;AAC3B,YAAY,YAAY,EAAE,CAAC;AAC3B,YAAY,QAAQ,EAAE,KAAK;AAC3B,SAAS;AACT;AACA,IAAI,MAAM,0BAA0B,GAAG;AACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC;AACtF,QAAQ,OAAO;AACf,YAAY,QAAQ,EAAE,SAAS;AAC/B,YAAY,IAAI,EAAE,SAAS;AAC3B,SAAS;AACT;AACA,IAAI,MAAM,mBAAmB,CAAC,OAAO,EAAE;AACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,6DAA6D,EAAE,OAAO,CAAC;AAC5F;AACA;AACA;;;;;;;;;"}
|
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst DumonGeolocation = registerPlugin('DumonGeolocation', {\n web: () => import('./web').then((m) => new m.DumonGeolocationWeb()),\n});\nexport * from './definitions';\nexport { DumonGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class DumonGeolocationWeb extends WebPlugin {\n async startPositioning() {\n console.log('DumonGeolocationWeb: startPositioning() called (no-op)');\n }\n async stopPositioning() {\n console.log('DumonGeolocationWeb: stopPositioning() called (no-op)');\n }\n async getLatestPosition() {\n console.log('DumonGeolocationWeb: getLatestPosition() called (returning dummy data)');\n return {\n source: 'GNSS',\n timestamp: Date.now(),\n latitude: 0,\n longitude: 0,\n accuracy: 999,\n speed: 0,\n acceleration: 0,\n directionRad: 0,\n isMocked: false,\n };\n }\n async checkAndRequestPermissions() {\n console.info('[dumon-geolocation] checkAndRequestPermissions mocked for web.');\n return {\n location: 'granted',\n wifi: 'granted',\n };\n }\n async configureEdgeToEdge(options) {\n console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);\n // No-op\n }\n async setOptions(_options) {\n // No-op on web\n }\n async getGnssStatus() {\n return null;\n }\n async getLocationServicesStatus() {\n // Web stub; assume enabled\n return { gpsEnabled: true, networkEnabled: true };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,gBAAgB,GAAGA,mBAAc,CAAC,kBAAkB,EAAE;AAC5D,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;AACvE,CAAC;;ACFM,MAAM,mBAAmB,SAASC,cAAS,CAAC;AACnD,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC;AAC7E;AACA,IAAI,MAAM,eAAe,GAAG;AAC5B,QAAQ,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC;AAC5E;AACA,IAAI,MAAM,iBAAiB,GAAG;AAC9B,QAAQ,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC;AAC7F,QAAQ,OAAO;AACf,YAAY,MAAM,EAAE,MAAM;AAC1B,YAAY,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;AACjC,YAAY,QAAQ,EAAE,CAAC;AACvB,YAAY,SAAS,EAAE,CAAC;AACxB,YAAY,QAAQ,EAAE,GAAG;AACzB,YAAY,KAAK,EAAE,CAAC;AACpB,YAAY,YAAY,EAAE,CAAC;AAC3B,YAAY,YAAY,EAAE,CAAC;AAC3B,YAAY,QAAQ,EAAE,KAAK;AAC3B,SAAS;AACT;AACA,IAAI,MAAM,0BAA0B,GAAG;AACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC;AACtF,QAAQ,OAAO;AACf,YAAY,QAAQ,EAAE,SAAS;AAC/B,YAAY,IAAI,EAAE,SAAS;AAC3B,SAAS;AACT;AACA,IAAI,MAAM,mBAAmB,CAAC,OAAO,EAAE;AACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,6DAA6D,EAAE,OAAO,CAAC;AAC5F;AACA;AACA,IAAI,MAAM,UAAU,CAAC,QAAQ,EAAE;AAC/B;AACA;AACA,IAAI,MAAM,aAAa,GAAG;AAC1B,QAAQ,OAAO,IAAI;AACnB;AACA,IAAI,MAAM,yBAAyB,GAAG;AACtC;AACA,QAAQ,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;AACzD;AACA;;;;;;;;;"}
|
||||||
10
dist/plugin.js
vendored
10
dist/plugin.js
vendored
@ -37,6 +37,16 @@ var capacitorDumonGeolocation = (function (exports, core) {
|
|||||||
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
async setOptions(_options) {
|
||||||
|
// No-op on web
|
||||||
|
}
|
||||||
|
async getGnssStatus() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
async getLocationServicesStatus() {
|
||||||
|
// Web stub; assume enabled
|
||||||
|
return { gpsEnabled: true, networkEnabled: true };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var web = /*#__PURE__*/Object.freeze({
|
var web = /*#__PURE__*/Object.freeze({
|
||||||
|
|||||||
2
dist/plugin.js.map
vendored
2
dist/plugin.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst DumonGeolocation = registerPlugin('DumonGeolocation', {\n web: () => import('./web').then((m) => new m.DumonGeolocationWeb()),\n});\nexport * from './definitions';\nexport { DumonGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class DumonGeolocationWeb extends WebPlugin {\n async startPositioning() {\n console.log('DumonGeolocationWeb: startPositioning() called (no-op)');\n }\n async stopPositioning() {\n console.log('DumonGeolocationWeb: stopPositioning() called (no-op)');\n }\n async getLatestPosition() {\n console.log('DumonGeolocationWeb: getLatestPosition() called (returning dummy data)');\n return {\n source: 'GNSS',\n timestamp: Date.now(),\n latitude: 0,\n longitude: 0,\n accuracy: 999,\n speed: 0,\n acceleration: 0,\n directionRad: 0,\n isMocked: false,\n };\n }\n async checkAndRequestPermissions() {\n console.info('[dumon-geolocation] checkAndRequestPermissions mocked for web.');\n return {\n location: 'granted',\n wifi: 'granted',\n };\n }\n async configureEdgeToEdge(options) {\n console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);\n // No-op\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,gBAAgB,GAAGA,mBAAc,CAAC,kBAAkB,EAAE;IAC5D,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;IACvE,CAAC;;ICFM,MAAM,mBAAmB,SAASC,cAAS,CAAC;IACnD,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC;IAC7E;IACA,IAAI,MAAM,eAAe,GAAG;IAC5B,QAAQ,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC;IAC5E;IACA,IAAI,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC;IAC7F,QAAQ,OAAO;IACf,YAAY,MAAM,EAAE,MAAM;IAC1B,YAAY,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;IACjC,YAAY,QAAQ,EAAE,CAAC;IACvB,YAAY,SAAS,EAAE,CAAC;IACxB,YAAY,QAAQ,EAAE,GAAG;IACzB,YAAY,KAAK,EAAE,CAAC;IACpB,YAAY,YAAY,EAAE,CAAC;IAC3B,YAAY,YAAY,EAAE,CAAC;IAC3B,YAAY,QAAQ,EAAE,KAAK;IAC3B,SAAS;IACT;IACA,IAAI,MAAM,0BAA0B,GAAG;IACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC;IACtF,QAAQ,OAAO;IACf,YAAY,QAAQ,EAAE,SAAS;IAC/B,YAAY,IAAI,EAAE,SAAS;IAC3B,SAAS;IACT;IACA,IAAI,MAAM,mBAAmB,CAAC,OAAO,EAAE;IACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,6DAA6D,EAAE,OAAO,CAAC;IAC5F;IACA;IACA;;;;;;;;;;;;;;;"}
|
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst DumonGeolocation = registerPlugin('DumonGeolocation', {\n web: () => import('./web').then((m) => new m.DumonGeolocationWeb()),\n});\nexport * from './definitions';\nexport { DumonGeolocation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class DumonGeolocationWeb extends WebPlugin {\n async startPositioning() {\n console.log('DumonGeolocationWeb: startPositioning() called (no-op)');\n }\n async stopPositioning() {\n console.log('DumonGeolocationWeb: stopPositioning() called (no-op)');\n }\n async getLatestPosition() {\n console.log('DumonGeolocationWeb: getLatestPosition() called (returning dummy data)');\n return {\n source: 'GNSS',\n timestamp: Date.now(),\n latitude: 0,\n longitude: 0,\n accuracy: 999,\n speed: 0,\n acceleration: 0,\n directionRad: 0,\n isMocked: false,\n };\n }\n async checkAndRequestPermissions() {\n console.info('[dumon-geolocation] checkAndRequestPermissions mocked for web.');\n return {\n location: 'granted',\n wifi: 'granted',\n };\n }\n async configureEdgeToEdge(options) {\n console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);\n // No-op\n }\n async setOptions(_options) {\n // No-op on web\n }\n async getGnssStatus() {\n return null;\n }\n async getLocationServicesStatus() {\n // Web stub; assume enabled\n return { gpsEnabled: true, networkEnabled: true };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,gBAAgB,GAAGA,mBAAc,CAAC,kBAAkB,EAAE;IAC5D,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;IACvE,CAAC;;ICFM,MAAM,mBAAmB,SAASC,cAAS,CAAC;IACnD,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC;IAC7E;IACA,IAAI,MAAM,eAAe,GAAG;IAC5B,QAAQ,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC;IAC5E;IACA,IAAI,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC;IAC7F,QAAQ,OAAO;IACf,YAAY,MAAM,EAAE,MAAM;IAC1B,YAAY,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;IACjC,YAAY,QAAQ,EAAE,CAAC;IACvB,YAAY,SAAS,EAAE,CAAC;IACxB,YAAY,QAAQ,EAAE,GAAG;IACzB,YAAY,KAAK,EAAE,CAAC;IACpB,YAAY,YAAY,EAAE,CAAC;IAC3B,YAAY,YAAY,EAAE,CAAC;IAC3B,YAAY,QAAQ,EAAE,KAAK;IAC3B,SAAS;IACT;IACA,IAAI,MAAM,0BAA0B,GAAG;IACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC;IACtF,QAAQ,OAAO;IACf,YAAY,QAAQ,EAAE,SAAS;IAC/B,YAAY,IAAI,EAAE,SAAS;IAC3B,SAAS;IACT;IACA,IAAI,MAAM,mBAAmB,CAAC,OAAO,EAAE;IACvC,QAAQ,OAAO,CAAC,IAAI,CAAC,6DAA6D,EAAE,OAAO,CAAC;IAC5F;IACA;IACA,IAAI,MAAM,UAAU,CAAC,QAAQ,EAAE;IAC/B;IACA;IACA,IAAI,MAAM,aAAa,GAAG;IAC1B,QAAQ,OAAO,IAAI;IACnB;IACA,IAAI,MAAM,yBAAyB,GAAG;IACtC;IACA,QAAQ,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;IACzD;IACA;;;;;;;;;;;;;;;"}
|
||||||
2
example-app/package-lock.json
generated
2
example-app/package-lock.json
generated
@ -20,7 +20,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"..": {
|
"..": {
|
||||||
"version": "0.0.1",
|
"version": "1.0.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/android": "^7.0.0",
|
"@capacitor/android": "^7.0.0",
|
||||||
|
|||||||
@ -50,9 +50,43 @@
|
|||||||
<button id="startButton">Start Positioning</button>
|
<button id="startButton">Start Positioning</button>
|
||||||
<button id="stopButton">Stop Positioning</button>
|
<button id="stopButton">Stop Positioning</button>
|
||||||
<button id="getLatestButton">Get Latest Position</button>
|
<button id="getLatestButton">Get Latest Position</button>
|
||||||
|
<button id="permButton">Request Permissions</button>
|
||||||
|
<button id="clearLogButton" style="background-color:#999">Clear Log</button>
|
||||||
|
|
||||||
|
<h1>Modes</h1>
|
||||||
|
<button id="drivingBtn">Driving Mode</button>
|
||||||
|
<button id="normalBtn">Normal Mode</button>
|
||||||
|
|
||||||
|
<h1>Options</h1>
|
||||||
|
<div style="display:flex;gap:1rem;flex-wrap:wrap">
|
||||||
|
<div>
|
||||||
|
<label><input type="checkbox" id="optEnableForwardPrediction" /> enableForwardPrediction</label><br />
|
||||||
|
<label><input type="checkbox" id="optEmitGnssStatus" /> emitGnssStatus</label><br />
|
||||||
|
<label><input type="checkbox" id="optEnableWifiRtt" checked /> enableWifiRtt</label><br />
|
||||||
|
<label><input type="checkbox" id="optEnableLogging" checked /> enableLogging</label><br />
|
||||||
|
<label><input type="checkbox" id="optSuppressMocked" /> suppressMockedUpdates</label><br />
|
||||||
|
<label><input type="checkbox" id="optKeepScreenOn" /> keepScreenOn</label><br />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>emitDebounceMs <input type="number" id="optEmitDebounceMs" placeholder="1000" /></label><br />
|
||||||
|
<label>drivingEmitIntervalMs <input type="number" id="optDrivingEmitIntervalMs" placeholder="1600" /></label><br />
|
||||||
|
<label>wifiScanIntervalMs <input type="number" id="optWifiScanIntervalMs" placeholder="3000" /></label><br />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>distanceThresholdMeters <input type="number" step="0.1" id="optDistanceThreshold" placeholder="7.0" /></label><br />
|
||||||
|
<label>speedChangeThreshold <input type="number" step="0.1" id="optSpeedThreshold" placeholder="0.5" /></label><br />
|
||||||
|
<label>directionChangeThreshold <input type="number" step="0.01" id="optDirectionThreshold" placeholder="0.17" /></label><br />
|
||||||
|
<label>maxPredictionSeconds <input type="number" step="0.1" id="optMaxPrediction" placeholder="1.0" /></label><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button id="applyOptionsButton" style="background-color:#2e7d32">Apply Options</button>
|
||||||
|
|
||||||
|
<h1>Diagnostics</h1>
|
||||||
|
<button id="getGnssStatusButton">Get GNSS Status</button>
|
||||||
|
<button id="getLocationServicesStatusButton">Get Location Services Status</button>
|
||||||
|
|
||||||
<pre id="logArea"></pre>
|
<pre id="logArea"></pre>
|
||||||
|
|
||||||
<script type="module" src="./js/example.js"></script>
|
<script type="module" src="./js/example.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,18 +1,99 @@
|
|||||||
import { DumonGeolocation } from 'dumon-geolocation';
|
import { DumonGeolocation } from 'dumon-geolocation';
|
||||||
|
|
||||||
const logArea = document.getElementById('logArea');
|
const logArea = document.getElementById('logArea');
|
||||||
|
let posListenerHandle = null;
|
||||||
|
let gnssListenerHandle = null;
|
||||||
|
|
||||||
function appendLog(title, data) {
|
function appendLog(title, data) {
|
||||||
const timestamp = new Date().toLocaleTimeString();
|
const timestamp = new Date().toLocaleTimeString();
|
||||||
const formatted = `[${timestamp}] ${title}\n${JSON.stringify(data, null, 2)}\n\n`;
|
const formatted = `[${timestamp}] ${title}\n${JSON.stringify(data, null, 2)}\n\n`;
|
||||||
logArea.textContent = formatted; // + logArea.textContent;
|
logArea.textContent = formatted + logArea.textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLog() {
|
||||||
|
logArea.textContent = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function readNumber(id) {
|
||||||
|
const el = document.getElementById(id);
|
||||||
|
if (!el) return undefined;
|
||||||
|
const v = el.value.trim();
|
||||||
|
if (v === '') return undefined;
|
||||||
|
const n = Number(v);
|
||||||
|
return Number.isFinite(n) ? n : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBool(id) {
|
||||||
|
const el = document.getElementById(id);
|
||||||
|
return !!el?.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function applyOptionsFromForm() {
|
||||||
|
const options = {};
|
||||||
|
|
||||||
|
// Booleans
|
||||||
|
if (document.getElementById('optEnableForwardPrediction'))
|
||||||
|
options.enableForwardPrediction = readBool('optEnableForwardPrediction');
|
||||||
|
if (document.getElementById('optEmitGnssStatus'))
|
||||||
|
options.emitGnssStatus = readBool('optEmitGnssStatus');
|
||||||
|
if (document.getElementById('optEnableWifiRtt'))
|
||||||
|
options.enableWifiRtt = readBool('optEnableWifiRtt');
|
||||||
|
if (document.getElementById('optEnableLogging'))
|
||||||
|
options.enableLogging = readBool('optEnableLogging');
|
||||||
|
if (document.getElementById('optSuppressMocked'))
|
||||||
|
options.suppressMockedUpdates = readBool('optSuppressMocked');
|
||||||
|
if (document.getElementById('optKeepScreenOn'))
|
||||||
|
options.keepScreenOn = readBool('optKeepScreenOn');
|
||||||
|
|
||||||
|
// Numbers
|
||||||
|
const emitDebounceMs = readNumber('optEmitDebounceMs');
|
||||||
|
const drivingEmitIntervalMs = readNumber('optDrivingEmitIntervalMs');
|
||||||
|
const wifiScanIntervalMs = readNumber('optWifiScanIntervalMs');
|
||||||
|
const distanceThresholdMeters = readNumber('optDistanceThreshold');
|
||||||
|
const speedChangeThreshold = readNumber('optSpeedThreshold');
|
||||||
|
const directionChangeThreshold = readNumber('optDirectionThreshold');
|
||||||
|
const maxPredictionSeconds = readNumber('optMaxPrediction');
|
||||||
|
|
||||||
|
if (emitDebounceMs !== undefined) options.emitDebounceMs = emitDebounceMs;
|
||||||
|
if (drivingEmitIntervalMs !== undefined) options.drivingEmitIntervalMs = drivingEmitIntervalMs;
|
||||||
|
if (wifiScanIntervalMs !== undefined) options.wifiScanIntervalMs = wifiScanIntervalMs;
|
||||||
|
if (distanceThresholdMeters !== undefined)
|
||||||
|
options.distanceThresholdMeters = distanceThresholdMeters;
|
||||||
|
if (speedChangeThreshold !== undefined) options.speedChangeThreshold = speedChangeThreshold;
|
||||||
|
if (directionChangeThreshold !== undefined)
|
||||||
|
options.directionChangeThreshold = directionChangeThreshold;
|
||||||
|
if (maxPredictionSeconds !== undefined) options.maxPredictionSeconds = maxPredictionSeconds;
|
||||||
|
|
||||||
|
await DumonGeolocation.setOptions(options);
|
||||||
|
appendLog('setOptions', options);
|
||||||
|
|
||||||
|
// Manage GNSS status listener dynamically
|
||||||
|
const wantGnss = !!options.emitGnssStatus;
|
||||||
|
if (wantGnss && !gnssListenerHandle) {
|
||||||
|
gnssListenerHandle = DumonGeolocation.addListener('onGnssStatus', (data) => {
|
||||||
|
appendLog('onGnssStatus', data);
|
||||||
|
});
|
||||||
|
} else if (!wantGnss && gnssListenerHandle) {
|
||||||
|
await gnssListenerHandle.remove();
|
||||||
|
gnssListenerHandle = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function requestPermissions() {
|
||||||
|
try {
|
||||||
|
const perm = await DumonGeolocation.checkAndRequestPermissions();
|
||||||
|
appendLog('permissions', perm);
|
||||||
|
} catch (err) {
|
||||||
|
appendLog('permissions', { error: err.message });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function startGeolocation() {
|
async function startGeolocation() {
|
||||||
DumonGeolocation.addListener('onPositionUpdate', (data) => {
|
if (!posListenerHandle) {
|
||||||
appendLog('onPositionUpdate', data);
|
posListenerHandle = DumonGeolocation.addListener('onPositionUpdate', (data) => {
|
||||||
});
|
appendLog('onPositionUpdate', data);
|
||||||
|
});
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await DumonGeolocation.startPositioning();
|
await DumonGeolocation.startPositioning();
|
||||||
appendLog('startPositioning', { success: true });
|
appendLog('startPositioning', { success: true });
|
||||||
@ -39,15 +120,58 @@ async function getLatestPosition() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setDrivingMode() {
|
||||||
|
try {
|
||||||
|
await DumonGeolocation.setGpsMode({ mode: 'driving' });
|
||||||
|
appendLog('setGpsMode', { mode: 'driving' });
|
||||||
|
} catch (err) {
|
||||||
|
appendLog('setGpsMode', { error: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setNormalMode() {
|
||||||
|
try {
|
||||||
|
await DumonGeolocation.setGpsMode({ mode: 'normal' });
|
||||||
|
appendLog('setGpsMode', { mode: 'normal' });
|
||||||
|
} catch (err) {
|
||||||
|
appendLog('setGpsMode', { error: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getGnssStatus() {
|
||||||
|
try {
|
||||||
|
const data = await DumonGeolocation.getGnssStatus();
|
||||||
|
appendLog('getGnssStatus', data);
|
||||||
|
} catch (err) {
|
||||||
|
appendLog('getGnssStatus', { error: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getLocationServicesStatus() {
|
||||||
|
try {
|
||||||
|
const data = await DumonGeolocation.getLocationServicesStatus();
|
||||||
|
appendLog('getLocationServicesStatus', data);
|
||||||
|
} catch (err) {
|
||||||
|
appendLog('getLocationServicesStatus', { error: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', async () => {
|
window.addEventListener('DOMContentLoaded', async () => {
|
||||||
document.getElementById('startButton').addEventListener('click', startGeolocation);
|
document.getElementById('startButton').addEventListener('click', startGeolocation);
|
||||||
document.getElementById('stopButton').addEventListener('click', stopGeolocation);
|
document.getElementById('stopButton').addEventListener('click', stopGeolocation);
|
||||||
document.getElementById('getLatestButton').addEventListener('click', getLatestPosition);
|
document.getElementById('getLatestButton').addEventListener('click', getLatestPosition);
|
||||||
|
document.getElementById('permButton').addEventListener('click', requestPermissions);
|
||||||
|
document.getElementById('drivingBtn').addEventListener('click', setDrivingMode);
|
||||||
|
document.getElementById('normalBtn').addEventListener('click', setNormalMode);
|
||||||
|
document.getElementById('applyOptionsButton').addEventListener('click', applyOptionsFromForm);
|
||||||
|
document.getElementById('getGnssStatusButton').addEventListener('click', getGnssStatus);
|
||||||
|
document.getElementById('getLocationServicesStatusButton').addEventListener('click', getLocationServicesStatus);
|
||||||
|
document.getElementById('clearLogButton').addEventListener('click', clearLog);
|
||||||
|
|
||||||
|
// Apply a reasonable default UI config for E2E
|
||||||
await DumonGeolocation.configureEdgeToEdge({
|
await DumonGeolocation.configureEdgeToEdge({
|
||||||
bgColor: '#ffffff',
|
bgColor: '#ffffff',
|
||||||
style: 'DARK',
|
style: 'DARK',
|
||||||
overlay: false, // atau true jika kamu ingin konten masuk ke area statusbar/navbar
|
overlay: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dumon-geolocation",
|
"name": "dumon-geolocation",
|
||||||
"version": "0.0.1",
|
"version": "1.0.2",
|
||||||
"description": "Implement manager GNSS, Wi‑Fi RTT, IMU, Kalman fusion, event emitter",
|
"description": "Implement manager GNSS, Wi‑Fi RTT, IMU, Kalman fusion, event emitter",
|
||||||
"main": "dist/plugin.cjs.js",
|
"main": "dist/plugin.cjs.js",
|
||||||
"module": "dist/esm/index.js",
|
"module": "dist/esm/index.js",
|
||||||
|
|||||||
@ -64,6 +64,28 @@ export interface PositioningData {
|
|||||||
predicted?: boolean;
|
predicted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SatelliteStatus {
|
||||||
|
satellitesInView: number;
|
||||||
|
usedInFix: number;
|
||||||
|
constellationCounts: { [key: string]: number };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DumonGeoOptions {
|
||||||
|
distanceThresholdMeters?: number;
|
||||||
|
speedChangeThreshold?: number;
|
||||||
|
directionChangeThreshold?: number;
|
||||||
|
emitDebounceMs?: number;
|
||||||
|
drivingEmitIntervalMs?: number;
|
||||||
|
wifiScanIntervalMs?: number;
|
||||||
|
enableWifiRtt?: boolean;
|
||||||
|
enableLogging?: boolean;
|
||||||
|
enableForwardPrediction?: boolean;
|
||||||
|
maxPredictionSeconds?: number;
|
||||||
|
emitGnssStatus?: boolean;
|
||||||
|
suppressMockedUpdates?: boolean;
|
||||||
|
keepScreenOn?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PermissionStatus {
|
export interface PermissionStatus {
|
||||||
location: 'granted' | 'denied';
|
location: 'granted' | 'denied';
|
||||||
wifi: 'granted' | 'denied';
|
wifi: 'granted' | 'denied';
|
||||||
@ -74,6 +96,9 @@ export interface DumonGeolocationPlugin {
|
|||||||
stopPositioning(): Promise<void>;
|
stopPositioning(): Promise<void>;
|
||||||
getLatestPosition(): Promise<PositioningData>;
|
getLatestPosition(): Promise<PositioningData>;
|
||||||
checkAndRequestPermissions(): Promise<PermissionStatus>;
|
checkAndRequestPermissions(): Promise<PermissionStatus>;
|
||||||
|
setOptions(options: DumonGeoOptions): Promise<void>;
|
||||||
|
getGnssStatus(): Promise<SatelliteStatus | null>;
|
||||||
|
getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }>;
|
||||||
|
|
||||||
configureEdgeToEdge(options: {
|
configureEdgeToEdge(options: {
|
||||||
bgColor: string;
|
bgColor: string;
|
||||||
@ -87,4 +112,9 @@ export interface DumonGeolocationPlugin {
|
|||||||
eventName: 'onPositionUpdate',
|
eventName: 'onPositionUpdate',
|
||||||
listenerFunc: (data: PositioningData) => void
|
listenerFunc: (data: PositioningData) => void
|
||||||
): PluginListenerHandle;
|
): PluginListenerHandle;
|
||||||
}
|
|
||||||
|
addListener(
|
||||||
|
eventName: 'onGnssStatus',
|
||||||
|
listenerFunc: (data: SatelliteStatus) => void
|
||||||
|
): PluginListenerHandle;
|
||||||
|
}
|
||||||
|
|||||||
17
src/web.ts
17
src/web.ts
@ -1,5 +1,5 @@
|
|||||||
import { WebPlugin } from '@capacitor/core';
|
import { WebPlugin } from '@capacitor/core';
|
||||||
import type { PositioningData } from './definitions';
|
import type { PositioningData, DumonGeoOptions, SatelliteStatus } from './definitions';
|
||||||
|
|
||||||
export class DumonGeolocationWeb extends WebPlugin {
|
export class DumonGeolocationWeb extends WebPlugin {
|
||||||
async startPositioning(): Promise<void> {
|
async startPositioning(): Promise<void> {
|
||||||
@ -44,4 +44,17 @@ export class DumonGeolocationWeb extends WebPlugin {
|
|||||||
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
console.info('[dumon-geolocation] configureEdgeToEdge called on web with:', options);
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
async setOptions(_options: DumonGeoOptions): Promise<void> {
|
||||||
|
// No-op on web
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGnssStatus(): Promise<SatelliteStatus | null> {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLocationServicesStatus(): Promise<{ gpsEnabled: boolean; networkEnabled: boolean }> {
|
||||||
|
// Web stub; assume enabled
|
||||||
|
return { gpsEnabled: true, networkEnabled: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user