expo-beacon 0.6.20 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/expo/modules/beacon/BeaconConstants.kt +15 -9
- package/android/src/main/java/expo/modules/beacon/BeaconEventReceiver.kt +13 -0
- package/android/src/main/java/expo/modules/beacon/BeaconForegroundService.kt +48 -4
- package/android/src/main/java/expo/modules/beacon/ExpoBeaconModule.kt +18 -1
- package/build/ExpoBeacon.types.d.ts +11 -0
- package/build/ExpoBeacon.types.d.ts.map +1 -1
- package/build/ExpoBeacon.types.js.map +1 -1
- package/ios/ExpoBeaconModule.swift +35 -1
- package/package.json +1 -1
- package/src/ExpoBeacon.types.ts +12 -0
|
@@ -26,8 +26,21 @@ internal const val MONITORING_SCAN_PERIOD_MS = 1100L
|
|
|
26
26
|
*/
|
|
27
27
|
internal const val MONITORING_BETWEEN_SCAN_PERIOD_MS = 1000L
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
|
|
29
|
+
/**
|
|
30
|
+
* AltBeacon region exit period — how long after the last sighting before
|
|
31
|
+
* MonitorNotifier.didExitRegion fires. Set generously to avoid premature
|
|
32
|
+
* monitor-level exits that bypass ranging hysteresis.
|
|
33
|
+
*/
|
|
34
|
+
internal const val REGION_EXIT_PERIOD_MS = 60000L
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Grace window after the last ranging sighting during which MonitorNotifier.didExitRegion
|
|
38
|
+
* is suppressed. Matched to REGION_EXIT_PERIOD_MS so that a monitor-level exit is only
|
|
39
|
+
* honoured when ranging has *also* been silent for the full exit period — preventing
|
|
40
|
+
* false exits caused by Android 17+'s intermittent BLE scan gaps where ranging may
|
|
41
|
+
* be briefly quiet even though the beacon is still within range.
|
|
42
|
+
*/
|
|
43
|
+
internal const val RECENT_RANGING_SIGHTING_GRACE_MS = REGION_EXIT_PERIOD_MS
|
|
31
44
|
|
|
32
45
|
/**
|
|
33
46
|
* Number of consecutive ranging misses before emitting a distance-based exit event.
|
|
@@ -46,13 +59,6 @@ internal const val DISTANCE_INACTIVITY_MS = 60_000L
|
|
|
46
59
|
/** Number of consecutive readings required to confirm a distance-based enter or exit transition. */
|
|
47
60
|
internal const val HYSTERESIS_COUNT = 3
|
|
48
61
|
|
|
49
|
-
/**
|
|
50
|
-
* AltBeacon region exit period — how long after the last sighting before
|
|
51
|
-
* MonitorNotifier.didExitRegion fires. Set generously to avoid premature
|
|
52
|
-
* monitor-level exits that bypass ranging hysteresis.
|
|
53
|
-
*/
|
|
54
|
-
internal const val REGION_EXIT_PERIOD_MS = 60000L
|
|
55
|
-
|
|
56
62
|
/** Default minimum RSSI (dBm) below which beacon readings are discarded as unreliable. */
|
|
57
63
|
internal const val DEFAULT_MIN_RSSI = -85
|
|
58
64
|
|
|
@@ -22,6 +22,19 @@ class BeaconEventReceiver(
|
|
|
22
22
|
|
|
23
23
|
val identifier = intent.getStringExtra("identifier") ?: return
|
|
24
24
|
val eventType = intent.getStringExtra("event") ?: return
|
|
25
|
+
|
|
26
|
+
// Handle error events uniformly — no beacon coordinates needed
|
|
27
|
+
if (eventType == "error") {
|
|
28
|
+
val errorCode = intent.getStringExtra("errorCode") ?: ""
|
|
29
|
+
val errorMessage = intent.getStringExtra("errorMessage") ?: ""
|
|
30
|
+
onEvent("onBeaconError", mapOf(
|
|
31
|
+
"identifier" to identifier,
|
|
32
|
+
"code" to errorCode,
|
|
33
|
+
"message" to errorMessage
|
|
34
|
+
))
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
val beaconType = intent.getStringExtra("beaconType") ?: "ibeacon"
|
|
26
39
|
val distance = intent.getDoubleExtra("distance", -1.0)
|
|
27
40
|
val rssi = intent.getIntExtra("rssi", 0)
|
|
@@ -115,6 +115,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
115
115
|
// SecurityException on Android 14+ if BT permissions missing,
|
|
116
116
|
// or other platform-specific issues. Stop gracefully instead of crashing.
|
|
117
117
|
Log.e(TAG, "startForeground failed — stopping service", e)
|
|
118
|
+
sendErrorBroadcast(null, "SERVICE_START_FAILED", "startForeground failed — stopping service: ${e.message}")
|
|
118
119
|
stopSelf()
|
|
119
120
|
return START_NOT_STICKY
|
|
120
121
|
}
|
|
@@ -214,6 +215,12 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
214
215
|
beaconManager.startMonitoringBeaconsInRegion(region)
|
|
215
216
|
} catch (e: RemoteException) {
|
|
216
217
|
Log.e(TAG, "Failed to start monitoring iBeacon region ${region.uniqueId}", e)
|
|
218
|
+
sendErrorBroadcast(region.uniqueId, "MONITORING_FAILED", "Failed to start monitoring iBeacon region ${region.uniqueId}")
|
|
219
|
+
} catch (e: SecurityException) {
|
|
220
|
+
// Android 17+ may throw SecurityException if BLUETOOTH_SCAN/CONNECT were
|
|
221
|
+
// not held at the exact moment monitoring starts.
|
|
222
|
+
Log.e(TAG, "Security exception starting monitoring for ${region.uniqueId} — check BT permissions", e)
|
|
223
|
+
sendErrorBroadcast(region.uniqueId, "SECURITY_EXCEPTION", "Security exception starting monitoring for ${region.uniqueId} — check BT permissions")
|
|
217
224
|
}
|
|
218
225
|
// Start ranging this region for distance logging
|
|
219
226
|
if (distanceLogRegions.add(region)) {
|
|
@@ -222,6 +229,11 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
222
229
|
} catch (e: RemoteException) {
|
|
223
230
|
distanceLogRegions.remove(region)
|
|
224
231
|
Log.e(TAG, "Failed to start ranging iBeacon region ${region.uniqueId}", e)
|
|
232
|
+
sendErrorBroadcast(region.uniqueId, "RANGING_FAILED", "Failed to start ranging iBeacon region ${region.uniqueId}")
|
|
233
|
+
} catch (e: SecurityException) {
|
|
234
|
+
distanceLogRegions.remove(region)
|
|
235
|
+
Log.e(TAG, "Security exception starting ranging for ${region.uniqueId} — check BT permissions", e)
|
|
236
|
+
sendErrorBroadcast(region.uniqueId, "SECURITY_EXCEPTION", "Security exception starting ranging for ${region.uniqueId} — check BT permissions")
|
|
225
237
|
}
|
|
226
238
|
}
|
|
227
239
|
}
|
|
@@ -244,6 +256,10 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
244
256
|
beaconManager.startMonitoringBeaconsInRegion(region)
|
|
245
257
|
} catch (ex: RemoteException) {
|
|
246
258
|
Log.e(TAG, "Failed to start monitoring Eddystone region $identifier", ex)
|
|
259
|
+
sendErrorBroadcast(identifier, "MONITORING_FAILED", "Failed to start monitoring Eddystone region $identifier")
|
|
260
|
+
} catch (ex: SecurityException) {
|
|
261
|
+
Log.e(TAG, "Security exception starting monitoring for Eddystone $identifier — check BT permissions", ex)
|
|
262
|
+
sendErrorBroadcast(identifier, "SECURITY_EXCEPTION", "Security exception starting monitoring for Eddystone $identifier — check BT permissions")
|
|
247
263
|
}
|
|
248
264
|
if (distanceLogRegions.add(region)) {
|
|
249
265
|
try {
|
|
@@ -251,6 +267,11 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
251
267
|
} catch (ex: RemoteException) {
|
|
252
268
|
distanceLogRegions.remove(region)
|
|
253
269
|
Log.e(TAG, "Failed to start ranging Eddystone region $identifier", ex)
|
|
270
|
+
sendErrorBroadcast(identifier, "RANGING_FAILED", "Failed to start ranging Eddystone region $identifier")
|
|
271
|
+
} catch (ex: SecurityException) {
|
|
272
|
+
distanceLogRegions.remove(region)
|
|
273
|
+
Log.e(TAG, "Security exception starting ranging for Eddystone $identifier — check BT permissions", ex)
|
|
274
|
+
sendErrorBroadcast(identifier, "SECURITY_EXCEPTION", "Security exception starting ranging for Eddystone $identifier — check BT permissions")
|
|
254
275
|
}
|
|
255
276
|
}
|
|
256
277
|
}
|
|
@@ -358,10 +379,15 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
358
379
|
HysteresisAction.NONE -> {}
|
|
359
380
|
}
|
|
360
381
|
} else {
|
|
361
|
-
// No valid beacon reading —
|
|
362
|
-
//
|
|
363
|
-
|
|
364
|
-
|
|
382
|
+
// No valid beacon reading — track consecutive misses for disappearance-based
|
|
383
|
+
// exit detection. enterCounters/exitCounters are intentionally NOT reset here.
|
|
384
|
+
// On Android 17+ (API 37) the BLE scan callbacks are more intermittent: valid
|
|
385
|
+
// readings are interspersed with occasional null cycles even when the beacon is
|
|
386
|
+
// nearby. Resetting direction counters on every null would prevent the hysteresis
|
|
387
|
+
// from ever accumulating to HYSTERESIS_COUNT, breaking enter/exit entirely while
|
|
388
|
+
// still allowing distance events (which fire on each individual valid reading).
|
|
389
|
+
// Direction counters are reset by evaluateDistanceHysteresis when a valid reading
|
|
390
|
+
// contradicts the current direction (e.g., in-range reading resets exitCounters).
|
|
365
391
|
val count = (missCounters[region.uniqueId] ?: 0) + 1
|
|
366
392
|
missCounters[region.uniqueId] = count
|
|
367
393
|
|
|
@@ -565,6 +591,24 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
565
591
|
sendBroadcast(intent)
|
|
566
592
|
}
|
|
567
593
|
|
|
594
|
+
private fun sendErrorBroadcast(identifier: String?, code: String, message: String) {
|
|
595
|
+
val params = buildMap<String, Any?> {
|
|
596
|
+
put("identifier", identifier ?: "")
|
|
597
|
+
put("event", "error")
|
|
598
|
+
put("code", code)
|
|
599
|
+
put("message", message)
|
|
600
|
+
}
|
|
601
|
+
logBeaconEvent("onBeaconError", params)
|
|
602
|
+
val intent = Intent(ACTION_BEACON_EVENT).apply {
|
|
603
|
+
putExtra("identifier", identifier ?: "")
|
|
604
|
+
putExtra("event", "error")
|
|
605
|
+
putExtra("errorCode", code)
|
|
606
|
+
putExtra("errorMessage", message)
|
|
607
|
+
setPackage(packageName)
|
|
608
|
+
}
|
|
609
|
+
sendBroadcast(intent)
|
|
610
|
+
}
|
|
611
|
+
|
|
568
612
|
private fun monitoringEventName(isEddystone: Boolean, eventType: String): String? {
|
|
569
613
|
return when (eventType) {
|
|
570
614
|
"enter" -> if (isEddystone) "onEddystoneEnter" else "onBeaconEnter"
|
|
@@ -85,15 +85,17 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
85
85
|
override fun definition() = ModuleDefinition {
|
|
86
86
|
Name("ExpoBeacon")
|
|
87
87
|
|
|
88
|
-
Events("onBeaconEnter", "onBeaconExit", "onBeaconDistance", "onBeaconTimeout", "onBeaconFound", "onEddystoneFound", "onEddystoneEnter", "onEddystoneExit", "onEddystoneDistance", "onEddystoneTimeout")
|
|
88
|
+
Events("onBeaconEnter", "onBeaconExit", "onBeaconDistance", "onBeaconTimeout", "onBeaconFound", "onEddystoneFound", "onEddystoneEnter", "onEddystoneExit", "onEddystoneDistance", "onEddystoneTimeout", "onBeaconError")
|
|
89
89
|
|
|
90
90
|
AsyncFunction("scanForBeaconsAsync") { uuids: List<String>?, scanDurationMs: Int, promise: Promise ->
|
|
91
91
|
if (scanDurationMs <= 0) {
|
|
92
92
|
promise.reject("INVALID_DURATION", "Scan duration must be a positive integer", null)
|
|
93
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "INVALID_DURATION", "message" to "Scan duration must be a positive integer"))
|
|
93
94
|
return@AsyncFunction
|
|
94
95
|
}
|
|
95
96
|
if (scanPromise != null || eddystoneScanPromise != null) {
|
|
96
97
|
promise.reject("SCAN_IN_PROGRESS", "A scan is already running", null)
|
|
98
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "SCAN_IN_PROGRESS", "message" to "A scan is already running"))
|
|
97
99
|
return@AsyncFunction
|
|
98
100
|
}
|
|
99
101
|
scanResults.clear()
|
|
@@ -120,12 +122,14 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
120
122
|
if (scanPromise != null) {
|
|
121
123
|
cancelActiveScan()
|
|
122
124
|
scanPromise?.reject("SCAN_CANCELLED", "Scan was cancelled", null)
|
|
125
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "SCAN_CANCELLED", "message" to "Scan was cancelled"))
|
|
123
126
|
scanPromise = null
|
|
124
127
|
scanUuidFilter = emptySet()
|
|
125
128
|
}
|
|
126
129
|
if (eddystoneScanPromise != null) {
|
|
127
130
|
cancelActiveScan()
|
|
128
131
|
eddystoneScanPromise?.reject("SCAN_CANCELLED", "Scan was cancelled", null)
|
|
132
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "SCAN_CANCELLED", "message" to "Scan was cancelled"))
|
|
129
133
|
eddystoneScanPromise = null
|
|
130
134
|
}
|
|
131
135
|
unbindIfIdle()
|
|
@@ -158,10 +162,12 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
158
162
|
AsyncFunction("scanForEddystonesAsync") { scanDurationMs: Int, promise: Promise ->
|
|
159
163
|
if (scanDurationMs <= 0) {
|
|
160
164
|
promise.reject("INVALID_DURATION", "Scan duration must be a positive integer", null)
|
|
165
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "INVALID_DURATION", "message" to "Scan duration must be a positive integer"))
|
|
161
166
|
return@AsyncFunction
|
|
162
167
|
}
|
|
163
168
|
if (scanPromise != null || eddystoneScanPromise != null) {
|
|
164
169
|
promise.reject("SCAN_IN_PROGRESS", "A scan is already running", null)
|
|
170
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "SCAN_IN_PROGRESS", "message" to "A scan is already running"))
|
|
165
171
|
return@AsyncFunction
|
|
166
172
|
}
|
|
167
173
|
scanResults.clear()
|
|
@@ -277,6 +283,7 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
277
283
|
AsyncFunction("startMonitoring") { options: Any?, promise: Promise ->
|
|
278
284
|
val ctx = appContext.reactContext ?: run {
|
|
279
285
|
promise.reject("NO_CONTEXT", "React context is not available", null)
|
|
286
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "NO_CONTEXT", "message" to "React context is not available"))
|
|
280
287
|
return@AsyncFunction
|
|
281
288
|
}
|
|
282
289
|
var maxDistance: Double? = null
|
|
@@ -302,18 +309,22 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
302
309
|
}
|
|
303
310
|
if (maxDistance != null && (!maxDistance.isFinite() || maxDistance <= 0.0)) {
|
|
304
311
|
promise.reject("INVALID_MAX_DISTANCE", "maxDistance must be a finite number greater than 0", null)
|
|
312
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "INVALID_MAX_DISTANCE", "message" to "maxDistance must be a finite number greater than 0"))
|
|
305
313
|
return@AsyncFunction
|
|
306
314
|
}
|
|
307
315
|
if (exitDistance != null && (!exitDistance.isFinite() || exitDistance <= 0.0)) {
|
|
308
316
|
promise.reject("INVALID_EXIT_DISTANCE", "exitDistance must be a finite number greater than 0", null)
|
|
317
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "INVALID_EXIT_DISTANCE", "message" to "exitDistance must be a finite number greater than 0"))
|
|
309
318
|
return@AsyncFunction
|
|
310
319
|
}
|
|
311
320
|
if (exitDistance != null && maxDistance == null) {
|
|
312
321
|
promise.reject("INVALID_EXIT_DISTANCE", "exitDistance requires maxDistance to be set", null)
|
|
322
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "INVALID_EXIT_DISTANCE", "message" to "exitDistance requires maxDistance to be set"))
|
|
313
323
|
return@AsyncFunction
|
|
314
324
|
}
|
|
315
325
|
if (maxDistance != null && exitDistance != null && exitDistance < maxDistance) {
|
|
316
326
|
promise.reject("INVALID_EXIT_DISTANCE", "exitDistance must be greater than or equal to maxDistance", null)
|
|
327
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "INVALID_EXIT_DISTANCE", "message" to "exitDistance must be greater than or equal to maxDistance"))
|
|
317
328
|
return@AsyncFunction
|
|
318
329
|
}
|
|
319
330
|
ctx.getSharedPreferences(MONITORING_OPTIONS_PREFS, Context.MODE_PRIVATE)
|
|
@@ -332,6 +343,7 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
332
343
|
ContextCompat.checkSelfPermission(ctx, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED
|
|
333
344
|
if (!hasLocation || !hasBgLocation) {
|
|
334
345
|
promise.reject("PERMISSION_DENIED", "Location permissions required for background monitoring. Call requestPermissionsAsync() first.", null)
|
|
346
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "PERMISSION_DENIED", "message" to "Location permissions required for background monitoring. Call requestPermissionsAsync() first."))
|
|
335
347
|
return@AsyncFunction
|
|
336
348
|
}
|
|
337
349
|
// Android 12+ requires BLUETOOTH_SCAN for BLE operations;
|
|
@@ -341,6 +353,7 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
341
353
|
val hasBtConnect = ContextCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED
|
|
342
354
|
if (!hasBtScan || !hasBtConnect) {
|
|
343
355
|
promise.reject("PERMISSION_DENIED", "Bluetooth permissions required for beacon monitoring. Call requestPermissionsAsync() first.", null)
|
|
356
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "PERMISSION_DENIED", "message" to "Bluetooth permissions required for beacon monitoring. Call requestPermissionsAsync() first."))
|
|
344
357
|
return@AsyncFunction
|
|
345
358
|
}
|
|
346
359
|
}
|
|
@@ -351,6 +364,7 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
351
364
|
} catch (e: Exception) {
|
|
352
365
|
unregisterEventReceiver()
|
|
353
366
|
promise.reject("SERVICE_START_FAILED", "Failed to start monitoring service: ${e.message}", e)
|
|
367
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "SERVICE_START_FAILED", "message" to "Failed to start monitoring service: ${e.message}"))
|
|
354
368
|
return@AsyncFunction
|
|
355
369
|
}
|
|
356
370
|
promise.resolve(null)
|
|
@@ -365,6 +379,7 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
365
379
|
AsyncFunction("stopMonitoring") { promise: Promise ->
|
|
366
380
|
val ctx = appContext.reactContext ?: run {
|
|
367
381
|
promise.reject("NO_CONTEXT", "React context is not available", null)
|
|
382
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "NO_CONTEXT", "message" to "React context is not available"))
|
|
368
383
|
return@AsyncFunction
|
|
369
384
|
}
|
|
370
385
|
BeaconForegroundService.stop(ctx)
|
|
@@ -510,6 +525,7 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
510
525
|
AsyncFunction("requestBatteryOptimizationExemption") { promise: Promise ->
|
|
511
526
|
val ctx = appContext.reactContext ?: run {
|
|
512
527
|
promise.reject("NO_CONTEXT", "React context is not available", null)
|
|
528
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "NO_CONTEXT", "message" to "React context is not available"))
|
|
513
529
|
return@AsyncFunction
|
|
514
530
|
}
|
|
515
531
|
val pm = ctx.getSystemService(Context.POWER_SERVICE) as? PowerManager
|
|
@@ -532,6 +548,7 @@ class ExpoBeaconModule : Module(), BeaconConsumer {
|
|
|
532
548
|
promise.resolve(true)
|
|
533
549
|
} catch (e: Exception) {
|
|
534
550
|
promise.reject("BATTERY_OPT_ERROR", "Failed to open battery optimization settings: ${e.message}", e)
|
|
551
|
+
sendEvent("onBeaconError", mapOf("identifier" to "", "code" to "BATTERY_OPT_ERROR", "message" to "Failed to open battery optimization settings: ${e.message}"))
|
|
535
552
|
}
|
|
536
553
|
}
|
|
537
554
|
|
|
@@ -245,6 +245,15 @@ export type EddystoneTimeoutEvent = {
|
|
|
245
245
|
/** Current distance in metres at the time the timeout fired. */
|
|
246
246
|
distance: number;
|
|
247
247
|
};
|
|
248
|
+
/** Payload for native beacon error events (monitoring/ranging failures). */
|
|
249
|
+
export type BeaconErrorEvent = {
|
|
250
|
+
/** Region or constraint identifier, empty string if unavailable. */
|
|
251
|
+
identifier: string;
|
|
252
|
+
/** Machine-readable error code (e.g. "MONITORING_FAILED", "RANGING_FAILED", "SECURITY_EXCEPTION"). */
|
|
253
|
+
code: string;
|
|
254
|
+
/** Human-readable error message from the native layer. */
|
|
255
|
+
message: string;
|
|
256
|
+
};
|
|
248
257
|
/** Module event map. */
|
|
249
258
|
export type ExpoBeaconModuleEvents = {
|
|
250
259
|
onBeaconEnter: (params: BeaconRegionEvent) => void;
|
|
@@ -261,6 +270,8 @@ export type ExpoBeaconModuleEvents = {
|
|
|
261
270
|
onEddystoneDistance: (params: EddystoneDistanceEvent) => void;
|
|
262
271
|
/** Fired once after a paired Eddystone has been continuously in range for its configured `timeoutSeconds`. */
|
|
263
272
|
onEddystoneTimeout: (params: EddystoneTimeoutEvent) => void;
|
|
273
|
+
/** Fired when a native monitoring or ranging failure occurs (logged to DB and forwarded to JS). */
|
|
274
|
+
onBeaconError: (params: BeaconErrorEvent) => void;
|
|
264
275
|
};
|
|
265
276
|
/** Options for filtering event logs. */
|
|
266
277
|
export type EventLogQueryOptions = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoBeacon.types.d.ts","sourceRoot":"","sources":["../src/ExpoBeacon.types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ExpoBeacon.types.d.ts","sourceRoot":"","sources":["../src/ExpoBeacon.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoBeacon.types.js","sourceRoot":"","sources":["../src/ExpoBeacon.types.ts"],"names":[],"mappings":"","sourcesContent":["/** Raw beacon discovered during a scan. */\r\nexport type BeaconScanResult = {\r\n uuid: string; // iBeacon proximity UUID (uppercase, formatted)\r\n major: number; // iBeacon major value (0–65535)\r\n minor: number; // iBeacon minor value (0–65535)\r\n rssi: number; // Signal strength in dBm (negative number)\r\n distance: number; // Estimated distance in meters\r\n txPower: number; // Calibrated TX power\r\n /** BLE advertising device name. May be undefined on iOS (CoreLocation does not expose it for iBeacon). */\r\n name?: string;\r\n};\r\n\r\n/**\r\n * A beacon that has been paired/registered for monitoring.\r\n *\r\n * Note: Paired beacon data is stored unencrypted in UserDefaults (iOS) /\r\n * SharedPreferences (Android) and may be included in device backups.\r\n */\r\nexport type PairedBeacon = {\r\n identifier: string; // User-defined label (e.g. \"lobby-door\")\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n /** BLE advertising device name, if provided at pairing time. */\r\n name?: string;\r\n /**\r\n * Timeout in seconds. When set, the module fires `onBeaconTimeout` once\r\n * after the beacon has been continuously in range for this duration.\r\n * The timer resets if the beacon exits and re-enters range.\r\n *\r\n * The timeout countdown also starts if no BLE readings are received\r\n * for 60 seconds (e.g. due to Doze mode or background throttling).\r\n */\r\n timeoutSeconds?: number;\r\n};\r\n\r\n/** Payload for enter/exit region events. */\r\nexport type BeaconRegionEvent = {\r\n identifier: string; // Matches PairedBeacon.identifier\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n event: \"enter\" | \"exit\";\r\n /** Measured distance in metres at the time of the event (–1 if unavailable). */\r\n distance: number;\r\n /** Signal strength in dBm at the time of the event (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for periodic distance update events during monitoring. */\r\nexport type BeaconDistanceEvent = {\r\n identifier: string;\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n distance: number;\r\n /** Signal strength in dBm (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for beacon timeout events (beacon in range for configured duration). */\r\nexport type BeaconTimeoutEvent = {\r\n identifier: string;\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n /** Current distance in metres at the time the timeout fired. */\r\n distance: number;\r\n};\r\n\r\n/** Configuration for beacon enter/exit event notifications. */\r\nexport type BeaconNotificationConfig = {\r\n /** Whether to show enter/exit notifications. Default: true. */\r\n enabled?: boolean;\r\n /** Notification title on beacon enter. Default: \"Beacon Entered\". */\r\n enterTitle?: string;\r\n /** Notification title on beacon exit. Default: \"Beacon Exited\". */\r\n exitTitle?: string;\r\n /** Notification title on beacon timeout. Default: \"Beacon Timeout\". */\r\n timeoutTitle?: string;\r\n /**\r\n * Notification body template. Supports {identifier} and {event} placeholders.\r\n * Default: \"{identifier} region {event}ed\".\r\n */\r\n body?: string;\r\n /** Play a sound with the notification (iOS only). Default: true. */\r\n sound?: boolean;\r\n /** Android drawable resource name for the notification icon (e.g. \"ic_notification\"). */\r\n icon?: string;\r\n};\r\n\r\n/** Configuration for the Android foreground service notification (persistent status bar entry). */\r\nexport type ForegroundServiceConfig = {\r\n /** Title of the persistent notification. Default: \"Beacon Monitoring Active\". */\r\n title?: string;\r\n /** Body text of the persistent notification. Default: \"Monitoring for iBeacons in the background\". */\r\n text?: string;\r\n /** Android drawable resource name for the notification icon. */\r\n icon?: string;\r\n};\r\n\r\n/** Configuration for the Android notification channel. */\r\nexport type NotificationChannelConfig = {\r\n /** Channel display name shown in system settings. Default: \"Beacon Monitoring\". */\r\n name?: string;\r\n /** Channel description shown in system settings. Default: \"Used for background iBeacon region monitoring\". */\r\n description?: string;\r\n /**\r\n * Channel importance level. Default: 'low'.\r\n * Note: Android may ignore decreases in importance after first channel creation until the app is reinstalled.\r\n */\r\n importance?: \"low\" | \"default\" | \"high\";\r\n};\r\n\r\n/** Combined notification configuration for all notification types. */\r\nexport type NotificationConfig = {\r\n /** Settings for beacon enter/exit event notifications. */\r\n beaconEvents?: BeaconNotificationConfig;\r\n /** Settings for the persistent foreground service notification (Android only). */\r\n foregroundService?: ForegroundServiceConfig;\r\n /** Settings for the Android notification channel (Android only). */\r\n channel?: NotificationChannelConfig;\r\n};\r\n\r\n/** Snapshot of the current monitoring configuration and active state. */\r\nexport type MonitoringConfig = {\r\n /** Whether background monitoring is currently active. */\r\n isMonitoring: boolean;\r\n maxDistance?: number;\r\n exitDistance?: number;\r\n minRssi?: number;\r\n level?: 'all' | 'events';\r\n notifications?: NotificationConfig;\r\n};\r\n\r\n/** Current state snapshot for a paired monitored device. */\r\nexport type MonitoredDeviceState =\r\n | {\r\n kind: \"ibeacon\";\r\n identifier: string;\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n state: \"entered\" | \"exited\";\r\n /** Current distance in metres, or null when exited or no live reading is available. */\r\n distance: number | null;\r\n }\r\n | {\r\n kind: \"eddystone\";\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n state: \"entered\" | \"exited\";\r\n /** Current distance in metres, or null when exited or no live reading is available. */\r\n distance: number | null;\r\n };\r\n\r\n/** Options accepted by startMonitoring(). */\r\nexport type MonitoringOptions = {\r\n /**\r\n * Maximum distance in metres for distance-based enter events.\r\n * Exit events are always emitted when the region is lost.\r\n */\r\n maxDistance?: number;\r\n /**\r\n * Distance in metres at which exit events fire (must be ≥ maxDistance).\r\n * Creates a hysteresis band between enter and exit thresholds to prevent\r\n * rapid toggling near the boundary.\r\n *\r\n * Default when omitted: `maxDistance + min(maxDistance × 0.5, 2.5)`.\r\n * Only used when `maxDistance` is set.\r\n */\r\n exitDistance?: number;\r\n /**\r\n * Minimum RSSI (dBm) for a beacon reading to be considered valid.\r\n * Readings below this threshold are discarded as unreliable, preventing\r\n * false detections from reflected or distant signals.\r\n *\r\n * Default: -85. Typical range: -100 (very permissive) to -70 (strict).\r\n */\r\n minRssi?: number;\r\n /**\r\n * Controls which event types are emitted, logged, and forwarded to the API.\r\n *\r\n * - `'all'` (default): distance + enter + exit + timeout events.\r\n * - `'events'`: enter + exit + timeout only (no distance events).\r\n */\r\n level?: 'all' | 'events';\r\n /** Notification configuration overrides to apply for this monitoring session. */\r\n notifications?: NotificationConfig;\r\n};\r\n\r\n/** Eddystone frame type. */\r\nexport type EddystoneFrameType = \"uid\" | \"url\";\r\n\r\n/** Raw Eddystone beacon discovered during a scan. */\r\nexport type EddystoneScanResult = {\r\n frameType: EddystoneFrameType;\r\n /** 10-byte namespace ID as hex string (20 chars). Present for UID frames. */\r\n namespace?: string;\r\n /** 6-byte instance ID as hex string (12 chars). Present for UID frames. */\r\n instance?: string;\r\n /** Decoded URL. Present for URL frames. */\r\n url?: string;\r\n rssi: number;\r\n distance: number;\r\n txPower: number;\r\n /** BLE advertising device name. */\r\n name?: string;\r\n};\r\n\r\n/**\r\n * An Eddystone-UID beacon that has been paired/registered for monitoring.\r\n *\r\n * Note: Paired beacon data is stored unencrypted in UserDefaults (iOS) /\r\n * SharedPreferences (Android) and may be included in device backups.\r\n */\r\nexport type PairedEddystone = {\r\n identifier: string;\r\n /** 10-byte namespace ID as hex string (20 chars). */\r\n namespace: string;\r\n /** 6-byte instance ID as hex string (12 chars). */\r\n instance: string;\r\n /** BLE advertising device name, if provided at pairing time. */\r\n name?: string;\r\n /**\r\n * Timeout in seconds. When set, the module fires `onEddystoneTimeout` once\r\n * after the beacon has been continuously in range for this duration.\r\n * The timer resets if the beacon exits and re-enters range.\r\n *\r\n * The timeout countdown also starts if no BLE readings are received\r\n * for 60 seconds (e.g. due to Doze mode or background throttling).\r\n */\r\n timeoutSeconds?: number;\r\n};\r\n\r\n/** Payload for Eddystone enter/exit region events. */\r\nexport type EddystoneRegionEvent = {\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n event: \"enter\" | \"exit\";\r\n /** Measured distance in metres at the time of the event (–1 if unavailable). */\r\n distance: number;\r\n /** Signal strength in dBm at the time of the event (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for periodic Eddystone distance update events during monitoring. */\r\nexport type EddystoneDistanceEvent = {\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n distance: number;\r\n /** Signal strength in dBm (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for Eddystone timeout events (beacon in range for configured duration). */\r\nexport type EddystoneTimeoutEvent = {\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n /** Current distance in metres at the time the timeout fired. */\r\n distance: number;\r\n};\r\n\r\n/** Module event map. */\r\nexport type ExpoBeaconModuleEvents = {\r\n onBeaconEnter: (params: BeaconRegionEvent) => void;\r\n onBeaconExit: (params: BeaconRegionEvent) => void;\r\n onBeaconDistance: (params: BeaconDistanceEvent) => void;\r\n /** Fired once after a paired beacon has been continuously in range for its configured `timeoutSeconds`. */\r\n onBeaconTimeout: (params: BeaconTimeoutEvent) => void;\r\n /** Fired continuously during a live scan as each iBeacon is detected. */\r\n onBeaconFound: (params: BeaconScanResult) => void;\r\n /** Fired continuously during a live scan as each Eddystone beacon is detected. */\r\n onEddystoneFound: (params: EddystoneScanResult) => void;\r\n onEddystoneEnter: (params: EddystoneRegionEvent) => void;\r\n onEddystoneExit: (params: EddystoneRegionEvent) => void;\r\n onEddystoneDistance: (params: EddystoneDistanceEvent) => void;\r\n /** Fired once after a paired Eddystone has been continuously in range for its configured `timeoutSeconds`. */\r\n onEddystoneTimeout: (params: EddystoneTimeoutEvent) => void;\r\n};\r\n\r\n/** Options for filtering event logs. */\r\nexport type EventLogQueryOptions = {\r\n /** Maximum number of log entries to return (default: 1000, max: 10000). */\r\n limit?: number;\r\n /** Filter by event type (e.g. \"onBeaconEnter\", \"onBeaconExit\"). */\r\n eventType?: string;\r\n /** Only return events with timestamp >= this value (ms since epoch). */\r\n sinceTimestamp?: number;\r\n};\r\n\r\n/** A single logged beacon event entry. */\r\nexport type EventLogEntry = {\r\n id: number;\r\n /** Timestamp in milliseconds since epoch. */\r\n timestamp: number;\r\n /** The event type that was logged (e.g. \"onBeaconEnter\"). */\r\n eventType: string;\r\n /** Beacon identifier, if available. */\r\n identifier?: string;\r\n /** The full event payload that was sent to JS. */\r\n data: Record<string, unknown>;\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoBeacon.types.js","sourceRoot":"","sources":["../src/ExpoBeacon.types.ts"],"names":[],"mappings":"","sourcesContent":["/** Raw beacon discovered during a scan. */\r\nexport type BeaconScanResult = {\r\n uuid: string; // iBeacon proximity UUID (uppercase, formatted)\r\n major: number; // iBeacon major value (0–65535)\r\n minor: number; // iBeacon minor value (0–65535)\r\n rssi: number; // Signal strength in dBm (negative number)\r\n distance: number; // Estimated distance in meters\r\n txPower: number; // Calibrated TX power\r\n /** BLE advertising device name. May be undefined on iOS (CoreLocation does not expose it for iBeacon). */\r\n name?: string;\r\n};\r\n\r\n/**\r\n * A beacon that has been paired/registered for monitoring.\r\n *\r\n * Note: Paired beacon data is stored unencrypted in UserDefaults (iOS) /\r\n * SharedPreferences (Android) and may be included in device backups.\r\n */\r\nexport type PairedBeacon = {\r\n identifier: string; // User-defined label (e.g. \"lobby-door\")\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n /** BLE advertising device name, if provided at pairing time. */\r\n name?: string;\r\n /**\r\n * Timeout in seconds. When set, the module fires `onBeaconTimeout` once\r\n * after the beacon has been continuously in range for this duration.\r\n * The timer resets if the beacon exits and re-enters range.\r\n *\r\n * The timeout countdown also starts if no BLE readings are received\r\n * for 60 seconds (e.g. due to Doze mode or background throttling).\r\n */\r\n timeoutSeconds?: number;\r\n};\r\n\r\n/** Payload for enter/exit region events. */\r\nexport type BeaconRegionEvent = {\r\n identifier: string; // Matches PairedBeacon.identifier\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n event: \"enter\" | \"exit\";\r\n /** Measured distance in metres at the time of the event (–1 if unavailable). */\r\n distance: number;\r\n /** Signal strength in dBm at the time of the event (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for periodic distance update events during monitoring. */\r\nexport type BeaconDistanceEvent = {\r\n identifier: string;\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n distance: number;\r\n /** Signal strength in dBm (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for beacon timeout events (beacon in range for configured duration). */\r\nexport type BeaconTimeoutEvent = {\r\n identifier: string;\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n /** Current distance in metres at the time the timeout fired. */\r\n distance: number;\r\n};\r\n\r\n/** Configuration for beacon enter/exit event notifications. */\r\nexport type BeaconNotificationConfig = {\r\n /** Whether to show enter/exit notifications. Default: true. */\r\n enabled?: boolean;\r\n /** Notification title on beacon enter. Default: \"Beacon Entered\". */\r\n enterTitle?: string;\r\n /** Notification title on beacon exit. Default: \"Beacon Exited\". */\r\n exitTitle?: string;\r\n /** Notification title on beacon timeout. Default: \"Beacon Timeout\". */\r\n timeoutTitle?: string;\r\n /**\r\n * Notification body template. Supports {identifier} and {event} placeholders.\r\n * Default: \"{identifier} region {event}ed\".\r\n */\r\n body?: string;\r\n /** Play a sound with the notification (iOS only). Default: true. */\r\n sound?: boolean;\r\n /** Android drawable resource name for the notification icon (e.g. \"ic_notification\"). */\r\n icon?: string;\r\n};\r\n\r\n/** Configuration for the Android foreground service notification (persistent status bar entry). */\r\nexport type ForegroundServiceConfig = {\r\n /** Title of the persistent notification. Default: \"Beacon Monitoring Active\". */\r\n title?: string;\r\n /** Body text of the persistent notification. Default: \"Monitoring for iBeacons in the background\". */\r\n text?: string;\r\n /** Android drawable resource name for the notification icon. */\r\n icon?: string;\r\n};\r\n\r\n/** Configuration for the Android notification channel. */\r\nexport type NotificationChannelConfig = {\r\n /** Channel display name shown in system settings. Default: \"Beacon Monitoring\". */\r\n name?: string;\r\n /** Channel description shown in system settings. Default: \"Used for background iBeacon region monitoring\". */\r\n description?: string;\r\n /**\r\n * Channel importance level. Default: 'low'.\r\n * Note: Android may ignore decreases in importance after first channel creation until the app is reinstalled.\r\n */\r\n importance?: \"low\" | \"default\" | \"high\";\r\n};\r\n\r\n/** Combined notification configuration for all notification types. */\r\nexport type NotificationConfig = {\r\n /** Settings for beacon enter/exit event notifications. */\r\n beaconEvents?: BeaconNotificationConfig;\r\n /** Settings for the persistent foreground service notification (Android only). */\r\n foregroundService?: ForegroundServiceConfig;\r\n /** Settings for the Android notification channel (Android only). */\r\n channel?: NotificationChannelConfig;\r\n};\r\n\r\n/** Snapshot of the current monitoring configuration and active state. */\r\nexport type MonitoringConfig = {\r\n /** Whether background monitoring is currently active. */\r\n isMonitoring: boolean;\r\n maxDistance?: number;\r\n exitDistance?: number;\r\n minRssi?: number;\r\n level?: 'all' | 'events';\r\n notifications?: NotificationConfig;\r\n};\r\n\r\n/** Current state snapshot for a paired monitored device. */\r\nexport type MonitoredDeviceState =\r\n | {\r\n kind: \"ibeacon\";\r\n identifier: string;\r\n uuid: string;\r\n major: number;\r\n minor: number;\r\n state: \"entered\" | \"exited\";\r\n /** Current distance in metres, or null when exited or no live reading is available. */\r\n distance: number | null;\r\n }\r\n | {\r\n kind: \"eddystone\";\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n state: \"entered\" | \"exited\";\r\n /** Current distance in metres, or null when exited or no live reading is available. */\r\n distance: number | null;\r\n };\r\n\r\n/** Options accepted by startMonitoring(). */\r\nexport type MonitoringOptions = {\r\n /**\r\n * Maximum distance in metres for distance-based enter events.\r\n * Exit events are always emitted when the region is lost.\r\n */\r\n maxDistance?: number;\r\n /**\r\n * Distance in metres at which exit events fire (must be ≥ maxDistance).\r\n * Creates a hysteresis band between enter and exit thresholds to prevent\r\n * rapid toggling near the boundary.\r\n *\r\n * Default when omitted: `maxDistance + min(maxDistance × 0.5, 2.5)`.\r\n * Only used when `maxDistance` is set.\r\n */\r\n exitDistance?: number;\r\n /**\r\n * Minimum RSSI (dBm) for a beacon reading to be considered valid.\r\n * Readings below this threshold are discarded as unreliable, preventing\r\n * false detections from reflected or distant signals.\r\n *\r\n * Default: -85. Typical range: -100 (very permissive) to -70 (strict).\r\n */\r\n minRssi?: number;\r\n /**\r\n * Controls which event types are emitted, logged, and forwarded to the API.\r\n *\r\n * - `'all'` (default): distance + enter + exit + timeout events.\r\n * - `'events'`: enter + exit + timeout only (no distance events).\r\n */\r\n level?: 'all' | 'events';\r\n /** Notification configuration overrides to apply for this monitoring session. */\r\n notifications?: NotificationConfig;\r\n};\r\n\r\n/** Eddystone frame type. */\r\nexport type EddystoneFrameType = \"uid\" | \"url\";\r\n\r\n/** Raw Eddystone beacon discovered during a scan. */\r\nexport type EddystoneScanResult = {\r\n frameType: EddystoneFrameType;\r\n /** 10-byte namespace ID as hex string (20 chars). Present for UID frames. */\r\n namespace?: string;\r\n /** 6-byte instance ID as hex string (12 chars). Present for UID frames. */\r\n instance?: string;\r\n /** Decoded URL. Present for URL frames. */\r\n url?: string;\r\n rssi: number;\r\n distance: number;\r\n txPower: number;\r\n /** BLE advertising device name. */\r\n name?: string;\r\n};\r\n\r\n/**\r\n * An Eddystone-UID beacon that has been paired/registered for monitoring.\r\n *\r\n * Note: Paired beacon data is stored unencrypted in UserDefaults (iOS) /\r\n * SharedPreferences (Android) and may be included in device backups.\r\n */\r\nexport type PairedEddystone = {\r\n identifier: string;\r\n /** 10-byte namespace ID as hex string (20 chars). */\r\n namespace: string;\r\n /** 6-byte instance ID as hex string (12 chars). */\r\n instance: string;\r\n /** BLE advertising device name, if provided at pairing time. */\r\n name?: string;\r\n /**\r\n * Timeout in seconds. When set, the module fires `onEddystoneTimeout` once\r\n * after the beacon has been continuously in range for this duration.\r\n * The timer resets if the beacon exits and re-enters range.\r\n *\r\n * The timeout countdown also starts if no BLE readings are received\r\n * for 60 seconds (e.g. due to Doze mode or background throttling).\r\n */\r\n timeoutSeconds?: number;\r\n};\r\n\r\n/** Payload for Eddystone enter/exit region events. */\r\nexport type EddystoneRegionEvent = {\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n event: \"enter\" | \"exit\";\r\n /** Measured distance in metres at the time of the event (–1 if unavailable). */\r\n distance: number;\r\n /** Signal strength in dBm at the time of the event (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for periodic Eddystone distance update events during monitoring. */\r\nexport type EddystoneDistanceEvent = {\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n distance: number;\r\n /** Signal strength in dBm (0 if unavailable). */\r\n rssi?: number;\r\n};\r\n\r\n/** Payload for Eddystone timeout events (beacon in range for configured duration). */\r\nexport type EddystoneTimeoutEvent = {\r\n identifier: string;\r\n namespace: string;\r\n instance: string;\r\n /** Current distance in metres at the time the timeout fired. */\r\n distance: number;\r\n};\r\n\r\n/** Payload for native beacon error events (monitoring/ranging failures). */\r\nexport type BeaconErrorEvent = {\r\n /** Region or constraint identifier, empty string if unavailable. */\r\n identifier: string;\r\n /** Machine-readable error code (e.g. \"MONITORING_FAILED\", \"RANGING_FAILED\", \"SECURITY_EXCEPTION\"). */\r\n code: string;\r\n /** Human-readable error message from the native layer. */\r\n message: string;\r\n};\r\n\r\n/** Module event map. */\r\nexport type ExpoBeaconModuleEvents = {\r\n onBeaconEnter: (params: BeaconRegionEvent) => void;\r\n onBeaconExit: (params: BeaconRegionEvent) => void;\r\n onBeaconDistance: (params: BeaconDistanceEvent) => void;\r\n /** Fired once after a paired beacon has been continuously in range for its configured `timeoutSeconds`. */\r\n onBeaconTimeout: (params: BeaconTimeoutEvent) => void;\r\n /** Fired continuously during a live scan as each iBeacon is detected. */\r\n onBeaconFound: (params: BeaconScanResult) => void;\r\n /** Fired continuously during a live scan as each Eddystone beacon is detected. */\r\n onEddystoneFound: (params: EddystoneScanResult) => void;\r\n onEddystoneEnter: (params: EddystoneRegionEvent) => void;\r\n onEddystoneExit: (params: EddystoneRegionEvent) => void;\r\n onEddystoneDistance: (params: EddystoneDistanceEvent) => void;\r\n /** Fired once after a paired Eddystone has been continuously in range for its configured `timeoutSeconds`. */\r\n onEddystoneTimeout: (params: EddystoneTimeoutEvent) => void;\r\n /** Fired when a native monitoring or ranging failure occurs (logged to DB and forwarded to JS). */\r\n onBeaconError: (params: BeaconErrorEvent) => void;\r\n};\r\n\r\n/** Options for filtering event logs. */\r\nexport type EventLogQueryOptions = {\r\n /** Maximum number of log entries to return (default: 1000, max: 10000). */\r\n limit?: number;\r\n /** Filter by event type (e.g. \"onBeaconEnter\", \"onBeaconExit\"). */\r\n eventType?: string;\r\n /** Only return events with timestamp >= this value (ms since epoch). */\r\n sinceTimestamp?: number;\r\n};\r\n\r\n/** A single logged beacon event entry. */\r\nexport type EventLogEntry = {\r\n id: number;\r\n /** Timestamp in milliseconds since epoch. */\r\n timestamp: number;\r\n /** The event type that was logged (e.g. \"onBeaconEnter\"). */\r\n eventType: string;\r\n /** Beacon identifier, if available. */\r\n identifier?: string;\r\n /** The full event payload that was sent to JS. */\r\n data: Record<string, unknown>;\r\n};\r\n"]}
|
|
@@ -145,17 +145,19 @@ public class ExpoBeaconModule: Module {
|
|
|
145
145
|
self.migrateUserDefaultsIfNeeded()
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
Events("onBeaconEnter", "onBeaconExit", "onBeaconDistance", "onBeaconTimeout", "onBeaconFound", "onEddystoneFound", "onEddystoneEnter", "onEddystoneExit", "onEddystoneDistance", "onEddystoneTimeout")
|
|
148
|
+
Events("onBeaconEnter", "onBeaconExit", "onBeaconDistance", "onBeaconTimeout", "onBeaconFound", "onEddystoneFound", "onEddystoneEnter", "onEddystoneExit", "onEddystoneDistance", "onEddystoneTimeout", "onBeaconError")
|
|
149
149
|
|
|
150
150
|
// MARK: - Scan
|
|
151
151
|
|
|
152
152
|
AsyncFunction("scanForBeaconsAsync") { (uuids: [String], scanDurationMs: Int, promise: Promise) in
|
|
153
153
|
guard scanDurationMs > 0 else {
|
|
154
154
|
promise.reject("INVALID_DURATION", "Scan duration must be a positive integer")
|
|
155
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "INVALID_DURATION", "message": "Scan duration must be a positive integer"])
|
|
155
156
|
return
|
|
156
157
|
}
|
|
157
158
|
guard self.scanPromise == nil else {
|
|
158
159
|
promise.reject("SCAN_IN_PROGRESS", "A scan is already in progress")
|
|
160
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "SCAN_IN_PROGRESS", "message": "A scan is already in progress"])
|
|
159
161
|
return
|
|
160
162
|
}
|
|
161
163
|
|
|
@@ -181,6 +183,7 @@ public class ExpoBeaconModule: Module {
|
|
|
181
183
|
promise.reject("WILDCARD_NOT_SUPPORTED",
|
|
182
184
|
"iOS does not support wildcard iBeacon scanning. " +
|
|
183
185
|
"Provide at least one proximity UUID, or pair beacons first.")
|
|
186
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "WILDCARD_NOT_SUPPORTED", "message": "iOS does not support wildcard iBeacon scanning. Provide at least one proximity UUID, or pair beacons first."])
|
|
184
187
|
self.scanPromise = nil
|
|
185
188
|
return
|
|
186
189
|
}
|
|
@@ -188,6 +191,7 @@ public class ExpoBeaconModule: Module {
|
|
|
188
191
|
for uuidStr in uuids {
|
|
189
192
|
guard let uuid = UUID(uuidString: uuidStr) else {
|
|
190
193
|
promise.reject("INVALID_UUID", "Invalid UUID: \(uuidStr)")
|
|
194
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "INVALID_UUID", "message": "Invalid UUID: \(uuidStr)"])
|
|
191
195
|
self.scanPromise = nil
|
|
192
196
|
return
|
|
193
197
|
}
|
|
@@ -201,6 +205,7 @@ public class ExpoBeaconModule: Module {
|
|
|
201
205
|
self.requestLocationPermission { granted in
|
|
202
206
|
guard granted else {
|
|
203
207
|
promise.reject("PERMISSION_DENIED", "Location permission required for beacon scanning")
|
|
208
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "PERMISSION_DENIED", "message": "Location permission required for beacon scanning"])
|
|
204
209
|
self.scanPromise = nil
|
|
205
210
|
return
|
|
206
211
|
}
|
|
@@ -356,18 +361,22 @@ public class ExpoBeaconModule: Module {
|
|
|
356
361
|
}
|
|
357
362
|
if let dist = maxDistance, (!dist.isFinite || dist <= 0) {
|
|
358
363
|
promise.reject("INVALID_MAX_DISTANCE", "maxDistance must be a finite number greater than 0")
|
|
364
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "INVALID_MAX_DISTANCE", "message": "maxDistance must be a finite number greater than 0"])
|
|
359
365
|
return
|
|
360
366
|
}
|
|
361
367
|
if let exitDist = exitDistance, (!exitDist.isFinite || exitDist <= 0) {
|
|
362
368
|
promise.reject("INVALID_EXIT_DISTANCE", "exitDistance must be a finite number greater than 0")
|
|
369
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "INVALID_EXIT_DISTANCE", "message": "exitDistance must be a finite number greater than 0"])
|
|
363
370
|
return
|
|
364
371
|
}
|
|
365
372
|
if exitDistance != nil && maxDistance == nil {
|
|
366
373
|
promise.reject("INVALID_EXIT_DISTANCE", "exitDistance requires maxDistance to be set")
|
|
374
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "INVALID_EXIT_DISTANCE", "message": "exitDistance requires maxDistance to be set"])
|
|
367
375
|
return
|
|
368
376
|
}
|
|
369
377
|
if let dist = maxDistance, let exitDist = exitDistance, exitDist < dist {
|
|
370
378
|
promise.reject("INVALID_EXIT_DISTANCE", "exitDistance must be greater than or equal to maxDistance")
|
|
379
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "INVALID_EXIT_DISTANCE", "message": "exitDistance must be greater than or equal to maxDistance"])
|
|
371
380
|
return
|
|
372
381
|
}
|
|
373
382
|
if let dist = maxDistance {
|
|
@@ -391,6 +400,7 @@ public class ExpoBeaconModule: Module {
|
|
|
391
400
|
self.requestLocationPermission { granted in
|
|
392
401
|
guard granted else {
|
|
393
402
|
promise.reject("PERMISSION_DENIED", "Location permission required for monitoring")
|
|
403
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "PERMISSION_DENIED", "message": "Location permission required for monitoring"])
|
|
394
404
|
return
|
|
395
405
|
}
|
|
396
406
|
// Request Always authorization non-blockingly for background support.
|
|
@@ -452,10 +462,12 @@ public class ExpoBeaconModule: Module {
|
|
|
452
462
|
AsyncFunction("scanForEddystonesAsync") { (scanDurationMs: Int, promise: Promise) in
|
|
453
463
|
guard scanDurationMs > 0 else {
|
|
454
464
|
promise.reject("INVALID_DURATION", "Scan duration must be a positive integer")
|
|
465
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "INVALID_DURATION", "message": "Scan duration must be a positive integer"])
|
|
455
466
|
return
|
|
456
467
|
}
|
|
457
468
|
guard self.eddystoneScanPromise == nil else {
|
|
458
469
|
promise.reject("SCAN_IN_PROGRESS", "An Eddystone scan is already in progress")
|
|
470
|
+
self.sendLoggedEvent("onBeaconError", ["identifier": "", "code": "SCAN_IN_PROGRESS", "message": "An Eddystone scan is already in progress"])
|
|
459
471
|
return
|
|
460
472
|
}
|
|
461
473
|
self.eddystoneScanPromise = promise
|
|
@@ -640,6 +652,7 @@ public class ExpoBeaconModule: Module {
|
|
|
640
652
|
let maxRegions = 20
|
|
641
653
|
if beacons.count > maxRegions {
|
|
642
654
|
print("[ExpoBeacon] Warning: \(beacons.count) paired beacons exceeds the iOS limit of \(maxRegions) monitored regions. Only the first \(maxRegions) will be monitored.")
|
|
655
|
+
sendLoggedEvent("onBeaconError", ["identifier": "", "code": "REGION_LIMIT_EXCEEDED", "message": "\(beacons.count) paired beacons exceeds the iOS limit of \(maxRegions) monitored regions. Only the first \(maxRegions) will be monitored."])
|
|
643
656
|
}
|
|
644
657
|
|
|
645
658
|
for b in beacons.prefix(maxRegions) {
|
|
@@ -1363,6 +1376,7 @@ public class ExpoBeaconModule: Module {
|
|
|
1363
1376
|
let data = json.data(using: .utf8) else { return [:] }
|
|
1364
1377
|
guard let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
1365
1378
|
print("[ExpoBeacon] Warning: failed to parse notification config JSON")
|
|
1379
|
+
sendLoggedEvent("onBeaconError", ["identifier": "", "code": "CONFIG_PARSE_ERROR", "message": "Failed to parse notification config JSON"])
|
|
1366
1380
|
return [:]
|
|
1367
1381
|
}
|
|
1368
1382
|
return dict
|
|
@@ -1626,10 +1640,20 @@ public class ExpoBeaconModule: Module {
|
|
|
1626
1640
|
let id = region?.identifier ?? "unknown"
|
|
1627
1641
|
Logger(subsystem: "expo.modules.beacon", category: "monitoring")
|
|
1628
1642
|
.error("Monitoring failed for region \(id, privacy: .public): \(error.localizedDescription, privacy: .public)")
|
|
1643
|
+
sendLoggedEvent("onBeaconError", [
|
|
1644
|
+
"identifier": id,
|
|
1645
|
+
"code": "MONITORING_FAILED",
|
|
1646
|
+
"message": error.localizedDescription
|
|
1647
|
+
])
|
|
1629
1648
|
}
|
|
1630
1649
|
|
|
1631
1650
|
fileprivate func handleDidFailRanging(for constraint: CLBeaconIdentityConstraint, error: Error) {
|
|
1632
1651
|
print("[ExpoBeacon] Ranging failed for constraint \(constraint.uuid): \(error.localizedDescription)")
|
|
1652
|
+
sendLoggedEvent("onBeaconError", [
|
|
1653
|
+
"identifier": constraint.uuid.uuidString,
|
|
1654
|
+
"code": "RANGING_FAILED",
|
|
1655
|
+
"message": error.localizedDescription
|
|
1656
|
+
])
|
|
1633
1657
|
|
|
1634
1658
|
// If a one-shot scan is active and this constraint belongs to it, reject the promise
|
|
1635
1659
|
if scanPromise != nil && scanConstraints.contains(where: { $0 == constraint }) {
|
|
@@ -1643,6 +1667,14 @@ public class ExpoBeaconModule: Module {
|
|
|
1643
1667
|
scanPromise = nil
|
|
1644
1668
|
}
|
|
1645
1669
|
}
|
|
1670
|
+
|
|
1671
|
+
fileprivate func handleBluetoothStateError(code: String, message: String) {
|
|
1672
|
+
sendLoggedEvent("onBeaconError", [
|
|
1673
|
+
"identifier": "",
|
|
1674
|
+
"code": code,
|
|
1675
|
+
"message": message
|
|
1676
|
+
])
|
|
1677
|
+
}
|
|
1646
1678
|
}
|
|
1647
1679
|
|
|
1648
1680
|
// MARK: - CLLocationManagerDelegate
|
|
@@ -1695,10 +1727,12 @@ private class BluetoothDelegate: NSObject, CBCentralManagerDelegate {
|
|
|
1695
1727
|
case .unauthorized:
|
|
1696
1728
|
print("[ExpoBeacon] Bluetooth authorization denied — Eddystone scanning/monitoring unavailable. " +
|
|
1697
1729
|
"Ensure NSBluetoothAlwaysUsageDescription is set in Info.plist.")
|
|
1730
|
+
module?.handleBluetoothStateError(code: "BLUETOOTH_UNAUTHORIZED", message: "Bluetooth authorization denied — Eddystone scanning/monitoring unavailable")
|
|
1698
1731
|
module?.eddystoneScanPromise?.reject("BLUETOOTH_UNAUTHORIZED", "Bluetooth permission denied")
|
|
1699
1732
|
module?.eddystoneScanPromise = nil
|
|
1700
1733
|
case .poweredOff:
|
|
1701
1734
|
print("[ExpoBeacon] Bluetooth is powered off — Eddystone scanning/monitoring unavailable.")
|
|
1735
|
+
module?.handleBluetoothStateError(code: "BLUETOOTH_OFF", message: "Bluetooth is powered off — Eddystone scanning/monitoring unavailable")
|
|
1702
1736
|
module?.eddystoneScanPromise?.reject("BLUETOOTH_OFF", "Bluetooth is powered off")
|
|
1703
1737
|
module?.eddystoneScanPromise = nil
|
|
1704
1738
|
default:
|
package/package.json
CHANGED
package/src/ExpoBeacon.types.ts
CHANGED
|
@@ -265,6 +265,16 @@ export type EddystoneTimeoutEvent = {
|
|
|
265
265
|
distance: number;
|
|
266
266
|
};
|
|
267
267
|
|
|
268
|
+
/** Payload for native beacon error events (monitoring/ranging failures). */
|
|
269
|
+
export type BeaconErrorEvent = {
|
|
270
|
+
/** Region or constraint identifier, empty string if unavailable. */
|
|
271
|
+
identifier: string;
|
|
272
|
+
/** Machine-readable error code (e.g. "MONITORING_FAILED", "RANGING_FAILED", "SECURITY_EXCEPTION"). */
|
|
273
|
+
code: string;
|
|
274
|
+
/** Human-readable error message from the native layer. */
|
|
275
|
+
message: string;
|
|
276
|
+
};
|
|
277
|
+
|
|
268
278
|
/** Module event map. */
|
|
269
279
|
export type ExpoBeaconModuleEvents = {
|
|
270
280
|
onBeaconEnter: (params: BeaconRegionEvent) => void;
|
|
@@ -281,6 +291,8 @@ export type ExpoBeaconModuleEvents = {
|
|
|
281
291
|
onEddystoneDistance: (params: EddystoneDistanceEvent) => void;
|
|
282
292
|
/** Fired once after a paired Eddystone has been continuously in range for its configured `timeoutSeconds`. */
|
|
283
293
|
onEddystoneTimeout: (params: EddystoneTimeoutEvent) => void;
|
|
294
|
+
/** Fired when a native monitoring or ranging failure occurs (logged to DB and forwarded to JS). */
|
|
295
|
+
onBeaconError: (params: BeaconErrorEvent) => void;
|
|
284
296
|
};
|
|
285
297
|
|
|
286
298
|
/** Options for filtering event logs. */
|