expo-beacon 0.8.1 → 0.8.3
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/BeaconApiForwarder.kt +0 -3
- package/android/src/main/java/expo/modules/beacon/BeaconForegroundService.kt +123 -0
- package/android/src/main/java/expo/modules/beacon/CarPlayMonitor.kt +21 -2
- package/build/ExpoBeacon.types.d.ts +40 -0
- package/build/ExpoBeacon.types.d.ts.map +1 -1
- package/build/ExpoBeacon.types.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/ios/BeaconApiForwarder.swift +0 -5
- package/ios/BeaconCarPlaySceneDelegate.swift +78 -0
- package/ios/BluetoothDelegate.swift +43 -0
- package/ios/CarPlayMonitor.swift +96 -12
- package/ios/ExpoBeacon.podspec +5 -2
- package/ios/ExpoBeaconConstants.swift +41 -0
- package/ios/ExpoBeaconModule+CarPlay.swift +61 -0
- package/ios/ExpoBeaconModule+Eddystone.swift +365 -0
- package/ios/ExpoBeaconModule+EventLogging.swift +98 -0
- package/ios/ExpoBeaconModule+Monitoring.swift +383 -0
- package/ios/ExpoBeaconModule+Notifications.swift +101 -0
- package/ios/ExpoBeaconModule+Permissions.swift +55 -0
- package/ios/ExpoBeaconModule+Scanning.swift +54 -0
- package/ios/ExpoBeaconModule+Storage.swift +97 -0
- package/ios/ExpoBeaconModule+Timers.swift +100 -0
- package/ios/ExpoBeaconModule.swift +91 -1381
- package/ios/LocationDelegate.swift +48 -0
- package/package.json +1 -1
- package/plugin/build/index.d.ts +5 -1
- package/plugin/build/index.d.ts.map +1 -1
- package/plugin/build/index.js +3 -2
- package/plugin/build/withBeaconIOS.d.ts +19 -1
- package/plugin/build/withBeaconIOS.d.ts.map +1 -1
- package/plugin/build/withBeaconIOS.js +41 -1
- package/src/ExpoBeacon.types.ts +42 -0
- package/src/index.ts +2 -0
|
@@ -28,9 +28,6 @@ internal class BeaconApiForwarder(private val context: Context) {
|
|
|
28
28
|
context.getSharedPreferences(API_PREFS, Context.MODE_PRIVATE)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
val isConfigured: Boolean
|
|
32
|
-
get() = prefs.getString(API_URL_KEY, null)?.isNotEmpty() == true
|
|
33
|
-
|
|
34
31
|
fun configure(url: String, apiKey: String?, id: String? = null) {
|
|
35
32
|
prefs.edit().apply {
|
|
36
33
|
putString(API_URL_KEY, url)
|
|
@@ -19,6 +19,7 @@ import org.altbeacon.beacon.*
|
|
|
19
19
|
import org.json.JSONArray
|
|
20
20
|
|
|
21
21
|
private const val CHANNEL_ID = "expo_beacon_channel"
|
|
22
|
+
private const val CARPLAY_CHANNEL_ID = "expo_beacon_carplay_channel"
|
|
22
23
|
internal const val FOREGROUND_NOTIF_ID = 1001
|
|
23
24
|
/**
|
|
24
25
|
* Base ID for per-beacon enter/exit notifications; incremented per unique region.
|
|
@@ -26,6 +27,14 @@ internal const val FOREGROUND_NOTIF_ID = 1001
|
|
|
26
27
|
* before ID collision. Sufficient for real-world beacon deployments.
|
|
27
28
|
*/
|
|
28
29
|
private const val ENTER_EXIT_NOTIF_BASE_ID = 2000
|
|
30
|
+
/**
|
|
31
|
+
* Fixed notification IDs for CarPlay connect / disconnect events. Each event
|
|
32
|
+
* type uses a single ID so repeated events of the same type replace the prior
|
|
33
|
+
* notification rather than stacking, while connect and disconnect remain
|
|
34
|
+
* independently visible.
|
|
35
|
+
*/
|
|
36
|
+
private const val CARPLAY_CONNECTED_NOTIF_ID = 3000
|
|
37
|
+
private const val CARPLAY_DISCONNECTED_NOTIF_ID = 3001
|
|
29
38
|
|
|
30
39
|
class BeaconForegroundService : Service(), BeaconConsumer {
|
|
31
40
|
|
|
@@ -94,6 +103,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
94
103
|
super.onCreate()
|
|
95
104
|
activeService = this
|
|
96
105
|
createNotificationChannel()
|
|
106
|
+
createCarPlayNotificationChannel()
|
|
97
107
|
apiForwarder = BeaconApiForwarder(this)
|
|
98
108
|
beaconManager = BeaconManager.getInstanceForApplication(this).also { manager ->
|
|
99
109
|
BeaconParsers.ensureRegistered(manager)
|
|
@@ -856,6 +866,60 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
856
866
|
}
|
|
857
867
|
// Best-effort delivery to the live JS bridge if a module instance is bound.
|
|
858
868
|
try { boundModule?.get()?.forwardCarPlayEventFromService(eventName, payload) } catch (_: Throwable) {}
|
|
869
|
+
// Local notification for connect/disconnect (config-gated).
|
|
870
|
+
try {
|
|
871
|
+
when (eventName) {
|
|
872
|
+
"onCarPlayConnected" -> showCarPlayNotification(
|
|
873
|
+
"connected",
|
|
874
|
+
payload["transport"] as? String,
|
|
875
|
+
)
|
|
876
|
+
"onCarPlayDisconnected" -> showCarPlayNotification("disconnected", null)
|
|
877
|
+
}
|
|
878
|
+
} catch (e: Throwable) {
|
|
879
|
+
Log.w(TAG, "CarPlay notification post failed", e)
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
private fun showCarPlayNotification(eventType: String, transport: String?) {
|
|
884
|
+
val config = readNotificationConfig()
|
|
885
|
+
val eventsConfig = config.optJSONObject("carPlayEvents")
|
|
886
|
+
|
|
887
|
+
// Respect the enabled flag (defaults to true)
|
|
888
|
+
if (eventsConfig != null && !eventsConfig.optBoolean("enabled", true)) return
|
|
889
|
+
|
|
890
|
+
val defaultTitle = if (eventType == "connected") "CarPlay Connected" else "CarPlay Disconnected"
|
|
891
|
+
val title = when (eventType) {
|
|
892
|
+
"connected" -> eventsConfig?.optString("connectedTitle")?.takeIf { it.isNotEmpty() } ?: defaultTitle
|
|
893
|
+
else -> eventsConfig?.optString("disconnectedTitle")?.takeIf { it.isNotEmpty() } ?: defaultTitle
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
val bodyTemplate = eventsConfig?.optString("body")?.takeIf { it.isNotEmpty() }
|
|
897
|
+
?: "CarPlay session {event}"
|
|
898
|
+
val message = bodyTemplate
|
|
899
|
+
.replace("{event}", eventType)
|
|
900
|
+
.replace("{transport}", transport ?: "")
|
|
901
|
+
|
|
902
|
+
val iconName = eventsConfig?.optString("icon")?.takeIf { it.isNotEmpty() }
|
|
903
|
+
val iconResId = iconName?.let { name ->
|
|
904
|
+
try { resources.getIdentifier(name, "drawable", packageName).takeIf { it != 0 } }
|
|
905
|
+
catch (_: Exception) { null }
|
|
906
|
+
} ?: android.R.drawable.ic_dialog_info
|
|
907
|
+
|
|
908
|
+
val notification = NotificationCompat.Builder(this, CARPLAY_CHANNEL_ID)
|
|
909
|
+
.setSmallIcon(iconResId)
|
|
910
|
+
.setContentTitle(title)
|
|
911
|
+
.setContentText(message)
|
|
912
|
+
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
|
913
|
+
.setAutoCancel(true)
|
|
914
|
+
.build()
|
|
915
|
+
|
|
916
|
+
val notifId = if (eventType == "connected") CARPLAY_CONNECTED_NOTIF_ID
|
|
917
|
+
else CARPLAY_DISCONNECTED_NOTIF_ID
|
|
918
|
+
try {
|
|
919
|
+
NotificationManagerCompat.from(this).notify(notifId, notification)
|
|
920
|
+
} catch (_: SecurityException) {
|
|
921
|
+
// POST_NOTIFICATIONS not granted — silently skip notification
|
|
922
|
+
}
|
|
859
923
|
}
|
|
860
924
|
|
|
861
925
|
private fun createNotificationChannel() {
|
|
@@ -884,6 +948,31 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
884
948
|
}
|
|
885
949
|
}
|
|
886
950
|
|
|
951
|
+
private fun createCarPlayNotificationChannel() {
|
|
952
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
953
|
+
val config = readNotificationConfig()
|
|
954
|
+
val channelConfig = config.optJSONObject("carPlayChannel")
|
|
955
|
+
|
|
956
|
+
val channelName = channelConfig?.optString("name")?.takeIf { it.isNotEmpty() }
|
|
957
|
+
?: "CarPlay / Android Auto"
|
|
958
|
+
val channelDesc = channelConfig?.optString("description")?.takeIf { it.isNotEmpty() }
|
|
959
|
+
?: "CarPlay and Android Auto connect/disconnect notifications"
|
|
960
|
+
val importance = when (channelConfig?.optString("importance")) {
|
|
961
|
+
"high" -> NotificationManager.IMPORTANCE_HIGH
|
|
962
|
+
"low" -> NotificationManager.IMPORTANCE_LOW
|
|
963
|
+
else -> NotificationManager.IMPORTANCE_DEFAULT
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
val notifMgr = getSystemService(NotificationManager::class.java)
|
|
967
|
+
if (notifMgr?.getNotificationChannel(CARPLAY_CHANNEL_ID) == null) {
|
|
968
|
+
val channel = NotificationChannel(CARPLAY_CHANNEL_ID, channelName, importance).apply {
|
|
969
|
+
description = channelDesc
|
|
970
|
+
}
|
|
971
|
+
notifMgr?.createNotificationChannel(channel)
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
887
976
|
private fun buildForegroundNotification(): Notification {
|
|
888
977
|
return Companion.buildForegroundNotification(this)
|
|
889
978
|
}
|
|
@@ -926,6 +1015,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
926
1015
|
context.getSharedPreferences(PREF_IS_MONITORING, Context.MODE_PRIVATE)
|
|
927
1016
|
.edit().putBoolean("active", true).apply()
|
|
928
1017
|
ensureNotificationChannel(context)
|
|
1018
|
+
ensureCarPlayNotificationChannel(context)
|
|
929
1019
|
val intent = Intent(context, BeaconForegroundService::class.java)
|
|
930
1020
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
931
1021
|
context.startForegroundService(intent)
|
|
@@ -976,6 +1066,7 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
976
1066
|
fun enableCarPlay(context: Context) {
|
|
977
1067
|
setCarPlayEnabled(context, true)
|
|
978
1068
|
ensureNotificationChannel(context)
|
|
1069
|
+
ensureCarPlayNotificationChannel(context)
|
|
979
1070
|
val intent = Intent(context, BeaconForegroundService::class.java)
|
|
980
1071
|
.setAction(ACTION_ENABLE_CARPLAY)
|
|
981
1072
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
@@ -1050,6 +1141,38 @@ class BeaconForegroundService : Service(), BeaconConsumer {
|
|
|
1050
1141
|
}
|
|
1051
1142
|
}
|
|
1052
1143
|
|
|
1144
|
+
/**
|
|
1145
|
+
* Ensure the CarPlay notification channel exists. Mirrors
|
|
1146
|
+
* [ensureNotificationChannel] for the dedicated CarPlay channel so that
|
|
1147
|
+
* users can mute CarPlay notifications independently in system settings.
|
|
1148
|
+
*/
|
|
1149
|
+
fun ensureCarPlayNotificationChannel(context: Context) {
|
|
1150
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
1151
|
+
val json = context.getSharedPreferences(NOTIFICATION_CONFIG_PREFS, Context.MODE_PRIVATE)
|
|
1152
|
+
.getString("config", null)
|
|
1153
|
+
val config = try { org.json.JSONObject(json ?: "") } catch (_: Exception) { org.json.JSONObject() }
|
|
1154
|
+
val channelConfig = config.optJSONObject("carPlayChannel")
|
|
1155
|
+
|
|
1156
|
+
val channelName = channelConfig?.optString("name")?.takeIf { it.isNotEmpty() }
|
|
1157
|
+
?: "CarPlay / Android Auto"
|
|
1158
|
+
val channelDesc = channelConfig?.optString("description")?.takeIf { it.isNotEmpty() }
|
|
1159
|
+
?: "CarPlay and Android Auto connect/disconnect notifications"
|
|
1160
|
+
val importance = when (channelConfig?.optString("importance")) {
|
|
1161
|
+
"high" -> NotificationManager.IMPORTANCE_HIGH
|
|
1162
|
+
"low" -> NotificationManager.IMPORTANCE_LOW
|
|
1163
|
+
else -> NotificationManager.IMPORTANCE_DEFAULT
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
val notifMgr = context.getSystemService(NotificationManager::class.java)
|
|
1167
|
+
if (notifMgr?.getNotificationChannel(CARPLAY_CHANNEL_ID) == null) {
|
|
1168
|
+
val channel = NotificationChannel(CARPLAY_CHANNEL_ID, channelName, importance).apply {
|
|
1169
|
+
description = channelDesc
|
|
1170
|
+
}
|
|
1171
|
+
notifMgr?.createNotificationChannel(channel)
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1053
1176
|
/**
|
|
1054
1177
|
* Build the foreground notification from any Context (service or module).
|
|
1055
1178
|
* Shared so that ExpoBeaconModule can pass the same notification to
|
|
@@ -7,6 +7,10 @@ import android.util.Log
|
|
|
7
7
|
import androidx.car.app.connection.CarConnection
|
|
8
8
|
import androidx.lifecycle.LiveData
|
|
9
9
|
import androidx.lifecycle.Observer
|
|
10
|
+
import java.text.SimpleDateFormat
|
|
11
|
+
import java.util.Date
|
|
12
|
+
import java.util.Locale
|
|
13
|
+
import java.util.TimeZone
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
16
|
* Wraps [CarConnection] LiveData to surface Android Auto / Automotive OS
|
|
@@ -72,6 +76,8 @@ internal class CarPlayMonitor(private val context: Context) {
|
|
|
72
76
|
if (lastConnected == connected) return
|
|
73
77
|
lastConnected = connected
|
|
74
78
|
val callback = emit ?: return
|
|
79
|
+
val now = System.currentTimeMillis()
|
|
80
|
+
val nowIso = formatIso(now)
|
|
75
81
|
if (connected) {
|
|
76
82
|
val transport = when (type) {
|
|
77
83
|
CarConnection.CONNECTION_TYPE_PROJECTION -> "projection"
|
|
@@ -80,15 +86,24 @@ internal class CarPlayMonitor(private val context: Context) {
|
|
|
80
86
|
}
|
|
81
87
|
callback("onCarPlayConnected", mapOf(
|
|
82
88
|
"transport" to transport,
|
|
83
|
-
"timestamp" to
|
|
89
|
+
"timestamp" to now,
|
|
90
|
+
"timestampIso" to nowIso,
|
|
84
91
|
))
|
|
85
92
|
} else {
|
|
86
93
|
callback("onCarPlayDisconnected", mapOf(
|
|
87
|
-
"timestamp" to
|
|
94
|
+
"timestamp" to now,
|
|
95
|
+
"timestampIso" to nowIso,
|
|
88
96
|
))
|
|
89
97
|
}
|
|
90
98
|
}
|
|
91
99
|
|
|
100
|
+
private fun formatIso(millis: Long): String {
|
|
101
|
+
// SimpleDateFormat is not thread-safe — synchronize on the shared instance.
|
|
102
|
+
synchronized(ISO_FORMAT) {
|
|
103
|
+
return ISO_FORMAT.format(Date(millis))
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
92
107
|
private fun runOnMain(block: () -> Unit) {
|
|
93
108
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
94
109
|
block()
|
|
@@ -99,5 +114,9 @@ internal class CarPlayMonitor(private val context: Context) {
|
|
|
99
114
|
|
|
100
115
|
private companion object {
|
|
101
116
|
const val TAG = "CarPlayMonitor"
|
|
117
|
+
// ISO 8601 UTC with millisecond precision. Safe for all supported APIs (minSdk 23).
|
|
118
|
+
private val ISO_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US).apply {
|
|
119
|
+
timeZone = TimeZone.getTimeZone("UTC")
|
|
120
|
+
}
|
|
102
121
|
}
|
|
103
122
|
}
|
|
@@ -104,14 +104,50 @@ export type NotificationChannelConfig = {
|
|
|
104
104
|
*/
|
|
105
105
|
importance?: "low" | "default" | "high";
|
|
106
106
|
};
|
|
107
|
+
/** Configuration for CarPlay / Android Auto connect/disconnect notifications. */
|
|
108
|
+
export type CarPlayNotificationConfig = {
|
|
109
|
+
/** Whether to show CarPlay connect/disconnect notifications. Default: true. */
|
|
110
|
+
enabled?: boolean;
|
|
111
|
+
/** Notification title on CarPlay/Android Auto connect. Default: "CarPlay Connected". */
|
|
112
|
+
connectedTitle?: string;
|
|
113
|
+
/** Notification title on CarPlay/Android Auto disconnect. Default: "CarPlay Disconnected". */
|
|
114
|
+
disconnectedTitle?: string;
|
|
115
|
+
/**
|
|
116
|
+
* Notification body template. Supports `{event}` ("connected"/"disconnected") and
|
|
117
|
+
* `{transport}` (e.g. "wired", "wireless", "projection", "native", "unknown") placeholders.
|
|
118
|
+
* Note: `{transport}` is only meaningful for connect events; on disconnect it is replaced with an empty string.
|
|
119
|
+
* Default: "CarPlay session {event}".
|
|
120
|
+
*/
|
|
121
|
+
body?: string;
|
|
122
|
+
/** Play a sound with the notification (iOS only). Default: true. */
|
|
123
|
+
sound?: boolean;
|
|
124
|
+
/** Android drawable resource name for the notification icon (e.g. "ic_notification"). */
|
|
125
|
+
icon?: string;
|
|
126
|
+
};
|
|
127
|
+
/** Configuration for the Android notification channel used for CarPlay events. */
|
|
128
|
+
export type CarPlayChannelConfig = {
|
|
129
|
+
/** Channel display name shown in system settings. Default: "CarPlay / Android Auto". */
|
|
130
|
+
name?: string;
|
|
131
|
+
/** Channel description shown in system settings. Default: "CarPlay and Android Auto connect/disconnect notifications". */
|
|
132
|
+
description?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Channel importance level. Default: 'default' (so connect/disconnect events make a sound).
|
|
135
|
+
* Note: Android may ignore decreases in importance after first channel creation until the app is reinstalled.
|
|
136
|
+
*/
|
|
137
|
+
importance?: "low" | "default" | "high";
|
|
138
|
+
};
|
|
107
139
|
/** Combined notification configuration for all notification types. */
|
|
108
140
|
export type NotificationConfig = {
|
|
109
141
|
/** Settings for beacon enter/exit event notifications. */
|
|
110
142
|
beaconEvents?: BeaconNotificationConfig;
|
|
143
|
+
/** Settings for CarPlay / Android Auto connect/disconnect notifications. */
|
|
144
|
+
carPlayEvents?: CarPlayNotificationConfig;
|
|
111
145
|
/** Settings for the persistent foreground service notification (Android only). */
|
|
112
146
|
foregroundService?: ForegroundServiceConfig;
|
|
113
147
|
/** Settings for the Android notification channel (Android only). */
|
|
114
148
|
channel?: NotificationChannelConfig;
|
|
149
|
+
/** Settings for the Android notification channel used for CarPlay events (Android only). */
|
|
150
|
+
carPlayChannel?: CarPlayChannelConfig;
|
|
115
151
|
};
|
|
116
152
|
/** Snapshot of the current monitoring configuration and active state. */
|
|
117
153
|
export type MonitoringConfig = {
|
|
@@ -261,11 +297,15 @@ export type CarPlayConnectedEvent = {
|
|
|
261
297
|
transport: CarPlayTransport;
|
|
262
298
|
/** Timestamp in milliseconds since epoch. */
|
|
263
299
|
timestamp: number;
|
|
300
|
+
/** ISO 8601 UTC representation of {@link timestamp} (e.g. "2026-05-12T14:23:45.678Z"). */
|
|
301
|
+
timestampIso?: string;
|
|
264
302
|
};
|
|
265
303
|
/** Payload fired when the device disconnects from a CarPlay or Android Auto session. */
|
|
266
304
|
export type CarPlayDisconnectedEvent = {
|
|
267
305
|
/** Timestamp in milliseconds since epoch. */
|
|
268
306
|
timestamp: number;
|
|
307
|
+
/** ISO 8601 UTC representation of {@link timestamp} (e.g. "2026-05-12T14:23:45.678Z"). */
|
|
308
|
+
timestampIso?: string;
|
|
269
309
|
};
|
|
270
310
|
/** Payload for native beacon error events (monitoring/ranging failures). */
|
|
271
311
|
export type BeaconErrorEvent = {
|
|
@@ -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 /** Seconds after last beacon sighting before an exit event fires. Default: 300. */\r\n exitTimeoutSeconds?: number;\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 /**\r\n * Seconds after last beacon sighting before an exit event fires when the beacon\r\n * disappears without moving outside the exit distance threshold.\r\n *\r\n * Default: 300 (5 minutes). Minimum: 1.\r\n */\r\n exitTimeoutSeconds?: number;\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/** Transport reported with CarPlay / Android Auto connection events. */\r\nexport type CarPlayTransport =\r\n | \"wired\" // iOS CarPlay over USB / Lightning\r\n | \"wireless\" // iOS CarPlay over Bluetooth + Wi-Fi\r\n | \"projection\" // Android Auto projection (phone projecting to head unit)\r\n | \"native\" // Android Automotive OS (running on the head unit)\r\n | \"unknown\";\r\n\r\n/** Payload fired when the device connects to a CarPlay or Android Auto session. */\r\nexport type CarPlayConnectedEvent = {\r\n transport: CarPlayTransport;\r\n /** Timestamp in milliseconds since epoch. */\r\n timestamp: number;\r\n};\r\n\r\n/** Payload fired when the device disconnects from a CarPlay or Android Auto session. */\r\nexport type CarPlayDisconnectedEvent = {\r\n /** Timestamp in milliseconds since epoch. */\r\n timestamp: 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 /** Fired when the device connects to a CarPlay (iOS) or Android Auto (Android) session. */\r\n onCarPlayConnected: (params: CarPlayConnectedEvent) => void;\r\n /** Fired when the device disconnects from a CarPlay (iOS) or Android Auto (Android) session. */\r\n onCarPlayDisconnected: (params: CarPlayDisconnectedEvent) => 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/** Configuration for CarPlay / Android Auto connect/disconnect notifications. */\r\nexport type CarPlayNotificationConfig = {\r\n /** Whether to show CarPlay connect/disconnect notifications. Default: true. */\r\n enabled?: boolean;\r\n /** Notification title on CarPlay/Android Auto connect. Default: \"CarPlay Connected\". */\r\n connectedTitle?: string;\r\n /** Notification title on CarPlay/Android Auto disconnect. Default: \"CarPlay Disconnected\". */\r\n disconnectedTitle?: string;\r\n /**\r\n * Notification body template. Supports `{event}` (\"connected\"/\"disconnected\") and\r\n * `{transport}` (e.g. \"wired\", \"wireless\", \"projection\", \"native\", \"unknown\") placeholders.\r\n * Note: `{transport}` is only meaningful for connect events; on disconnect it is replaced with an empty string.\r\n * Default: \"CarPlay session {event}\".\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 notification channel used for CarPlay events. */\r\nexport type CarPlayChannelConfig = {\r\n /** Channel display name shown in system settings. Default: \"CarPlay / Android Auto\". */\r\n name?: string;\r\n /** Channel description shown in system settings. Default: \"CarPlay and Android Auto connect/disconnect notifications\". */\r\n description?: string;\r\n /**\r\n * Channel importance level. Default: 'default' (so connect/disconnect events make a sound).\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 CarPlay / Android Auto connect/disconnect notifications. */\r\n carPlayEvents?: CarPlayNotificationConfig;\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 /** Settings for the Android notification channel used for CarPlay events (Android only). */\r\n carPlayChannel?: CarPlayChannelConfig;\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 /** Seconds after last beacon sighting before an exit event fires. Default: 300. */\r\n exitTimeoutSeconds?: number;\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 /**\r\n * Seconds after last beacon sighting before an exit event fires when the beacon\r\n * disappears without moving outside the exit distance threshold.\r\n *\r\n * Default: 300 (5 minutes). Minimum: 1.\r\n */\r\n exitTimeoutSeconds?: number;\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/** Transport reported with CarPlay / Android Auto connection events. */\r\nexport type CarPlayTransport =\r\n | \"wired\" // iOS CarPlay over USB / Lightning\r\n | \"wireless\" // iOS CarPlay over Bluetooth + Wi-Fi\r\n | \"projection\" // Android Auto projection (phone projecting to head unit)\r\n | \"native\" // Android Automotive OS (running on the head unit)\r\n | \"unknown\";\r\n\r\n/** Payload fired when the device connects to a CarPlay or Android Auto session. */\r\nexport type CarPlayConnectedEvent = {\r\n transport: CarPlayTransport;\r\n /** Timestamp in milliseconds since epoch. */\r\n timestamp: number;\r\n /** ISO 8601 UTC representation of {@link timestamp} (e.g. \"2026-05-12T14:23:45.678Z\"). */\r\n timestampIso?: string;\r\n};\r\n\r\n/** Payload fired when the device disconnects from a CarPlay or Android Auto session. */\r\nexport type CarPlayDisconnectedEvent = {\r\n /** Timestamp in milliseconds since epoch. */\r\n timestamp: number;\r\n /** ISO 8601 UTC representation of {@link timestamp} (e.g. \"2026-05-12T14:23:45.678Z\"). */\r\n timestampIso?: string;\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 /** Fired when the device connects to a CarPlay (iOS) or Android Auto (Android) session. */\r\n onCarPlayConnected: (params: CarPlayConnectedEvent) => void;\r\n /** Fired when the device disconnects from a CarPlay (iOS) or Android Auto (Android) session. */\r\n onCarPlayDisconnected: (params: CarPlayDisconnectedEvent) => 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"]}
|
package/build/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { default } from "./ExpoBeaconModule.js";
|
|
2
|
-
export type { BeaconScanResult, PairedBeacon, BeaconRegionEvent, BeaconDistanceEvent, BeaconTimeoutEvent, ExpoBeaconModuleEvents, NotificationConfig, MonitoringOptions, MonitoringConfig, MonitoredDeviceState, BeaconNotificationConfig, ForegroundServiceConfig, NotificationChannelConfig, EddystoneFrameType, EddystoneScanResult, PairedEddystone, EddystoneRegionEvent, EddystoneDistanceEvent, EddystoneTimeoutEvent, EventLogQueryOptions, EventLogEntry, CarPlayTransport, CarPlayConnectedEvent, CarPlayDisconnectedEvent, } from "./ExpoBeacon.types";
|
|
2
|
+
export type { BeaconScanResult, PairedBeacon, BeaconRegionEvent, BeaconDistanceEvent, BeaconTimeoutEvent, ExpoBeaconModuleEvents, NotificationConfig, MonitoringOptions, MonitoringConfig, MonitoredDeviceState, BeaconNotificationConfig, CarPlayNotificationConfig, CarPlayChannelConfig, ForegroundServiceConfig, NotificationChannelConfig, EddystoneFrameType, EddystoneScanResult, PairedEddystone, EddystoneRegionEvent, EddystoneDistanceEvent, EddystoneTimeoutEvent, EventLogQueryOptions, EventLogEntry, CarPlayTransport, CarPlayConnectedEvent, CarPlayDisconnectedEvent, } from "./ExpoBeacon.types";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGhD,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGhD,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC"}
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["// Native module (default export)\r\nexport { default } from \"./ExpoBeaconModule.js\";\r\n\r\n// All public types\r\nexport type {\r\n BeaconScanResult,\r\n PairedBeacon,\r\n BeaconRegionEvent,\r\n BeaconDistanceEvent,\r\n BeaconTimeoutEvent,\r\n ExpoBeaconModuleEvents,\r\n NotificationConfig,\r\n MonitoringOptions,\r\n MonitoringConfig,\r\n MonitoredDeviceState,\r\n BeaconNotificationConfig,\r\n ForegroundServiceConfig,\r\n NotificationChannelConfig,\r\n EddystoneFrameType,\r\n EddystoneScanResult,\r\n PairedEddystone,\r\n EddystoneRegionEvent,\r\n EddystoneDistanceEvent,\r\n EddystoneTimeoutEvent,\r\n EventLogQueryOptions,\r\n EventLogEntry,\r\n CarPlayTransport,\r\n CarPlayConnectedEvent,\r\n CarPlayDisconnectedEvent,\r\n} from \"./ExpoBeacon.types\";\r\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["// Native module (default export)\r\nexport { default } from \"./ExpoBeaconModule.js\";\r\n\r\n// All public types\r\nexport type {\r\n BeaconScanResult,\r\n PairedBeacon,\r\n BeaconRegionEvent,\r\n BeaconDistanceEvent,\r\n BeaconTimeoutEvent,\r\n ExpoBeaconModuleEvents,\r\n NotificationConfig,\r\n MonitoringOptions,\r\n MonitoringConfig,\r\n MonitoredDeviceState,\r\n BeaconNotificationConfig,\r\n CarPlayNotificationConfig,\r\n CarPlayChannelConfig,\r\n ForegroundServiceConfig,\r\n NotificationChannelConfig,\r\n EddystoneFrameType,\r\n EddystoneScanResult,\r\n PairedEddystone,\r\n EddystoneRegionEvent,\r\n EddystoneDistanceEvent,\r\n EddystoneTimeoutEvent,\r\n EventLogQueryOptions,\r\n EventLogEntry,\r\n CarPlayTransport,\r\n CarPlayConnectedEvent,\r\n CarPlayDisconnectedEvent,\r\n} from \"./ExpoBeacon.types\";\r\n"]}
|
|
@@ -14,11 +14,6 @@ final class BeaconApiForwarder {
|
|
|
14
14
|
private let defaults: UserDefaults
|
|
15
15
|
private let session: URLSession
|
|
16
16
|
|
|
17
|
-
var isConfigured: Bool {
|
|
18
|
-
guard let url = defaults.string(forKey: API_URL_KEY) else { return false }
|
|
19
|
-
return !url.isEmpty
|
|
20
|
-
}
|
|
21
|
-
|
|
22
17
|
init(defaults: UserDefaults? = nil) {
|
|
23
18
|
self.defaults = defaults ?? (UserDefaults(suiteName: "expo.modules.beacon") ?? .standard)
|
|
24
19
|
let config = URLSessionConfiguration.default
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
import CarPlay
|
|
4
|
+
import os.log
|
|
5
|
+
|
|
6
|
+
/// CarPlay scene delegate used when the consumer app is provisioned with the
|
|
7
|
+
/// `com.apple.developer.carplay-driving-task` entitlement (driver / fleet
|
|
8
|
+
/// workflow apps).
|
|
9
|
+
///
|
|
10
|
+
/// Wiring is performed by the config plugin (`carplayDrivingTask: true`):
|
|
11
|
+
/// 1. The entitlement is added to the app's `*.entitlements`.
|
|
12
|
+
/// 2. `Info.plist` `UIApplicationSceneManifest` declares a
|
|
13
|
+
/// `CPTemplateApplicationSceneSessionRoleApplication` configuration with
|
|
14
|
+
/// `UISceneDelegateClassName = "ExpoBeacon.BeaconCarPlaySceneDelegate"`.
|
|
15
|
+
///
|
|
16
|
+
/// When CarPlay attaches, iOS launches (or wakes) the app and instantiates this
|
|
17
|
+
/// delegate. We notify the shared `CarPlayMonitor` which produces an
|
|
18
|
+
/// `onCarPlayConnected` event through the standard pipeline (JS bridge,
|
|
19
|
+
/// SQLite log, HTTP forwarder, lifecycle plugin registry).
|
|
20
|
+
///
|
|
21
|
+
/// Apple requires that a CarPlay-entitled app present a meaningful CarPlay UI.
|
|
22
|
+
/// We install a minimal `CPInformationTemplate` titled "Driver tracking active"
|
|
23
|
+
/// as the root template so the app passes review without forcing every consumer
|
|
24
|
+
/// to build a full CarPlay UX. Consumers that need richer UI can subclass this
|
|
25
|
+
/// delegate (or replace the scene class) and override `makeRootTemplate()`.
|
|
26
|
+
///
|
|
27
|
+
/// IMPORTANT: This class must be accessible to the Objective-C runtime so that
|
|
28
|
+
/// `Info.plist`'s `UISceneDelegateClassName` string can resolve via
|
|
29
|
+
/// `NSClassFromString`. Hence `@objc(...)` and `: NSObject`.
|
|
30
|
+
@objc(BeaconCarPlaySceneDelegate)
|
|
31
|
+
open class BeaconCarPlaySceneDelegate: NSObject, CPTemplateApplicationSceneDelegate {
|
|
32
|
+
|
|
33
|
+
private static let log = OSLog(subsystem: "expo.modules.beacon", category: "CarPlayScene")
|
|
34
|
+
|
|
35
|
+
private var interfaceController: CPInterfaceController?
|
|
36
|
+
|
|
37
|
+
public override init() {
|
|
38
|
+
super.init()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// MARK: - CPTemplateApplicationSceneDelegate
|
|
42
|
+
|
|
43
|
+
public func templateApplicationScene(
|
|
44
|
+
_ templateApplicationScene: CPTemplateApplicationScene,
|
|
45
|
+
didConnect interfaceController: CPInterfaceController
|
|
46
|
+
) {
|
|
47
|
+
os_log("CarPlay templateApplicationScene didConnect", log: Self.log, type: .info)
|
|
48
|
+
self.interfaceController = interfaceController
|
|
49
|
+
let template = makeRootTemplate()
|
|
50
|
+
interfaceController.setRootTemplate(template, animated: false, completion: nil)
|
|
51
|
+
CarPlayMonitor.shared.notifyEntitledConnect()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public func templateApplicationScene(
|
|
55
|
+
_ templateApplicationScene: CPTemplateApplicationScene,
|
|
56
|
+
didDisconnectInterfaceController interfaceController: CPInterfaceController
|
|
57
|
+
) {
|
|
58
|
+
os_log("CarPlay templateApplicationScene didDisconnect", log: Self.log, type: .info)
|
|
59
|
+
self.interfaceController = nil
|
|
60
|
+
CarPlayMonitor.shared.notifyEntitledDisconnect()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// MARK: - Override hooks
|
|
64
|
+
|
|
65
|
+
/// Build the root template shown when CarPlay attaches. Override in a
|
|
66
|
+
/// consumer subclass to install a richer template (e.g. `CPListTemplate`,
|
|
67
|
+
/// `CPMapTemplate`, `CPNowPlayingTemplate`). Default is a minimal
|
|
68
|
+
/// `CPInformationTemplate` confirming the app is tracking.
|
|
69
|
+
open func makeRootTemplate() -> CPTemplate {
|
|
70
|
+
let item = CPInformationItem(title: "Status", detail: "Tracking active")
|
|
71
|
+
return CPInformationTemplate(
|
|
72
|
+
title: "Driver tracking",
|
|
73
|
+
layout: .leading,
|
|
74
|
+
items: [item],
|
|
75
|
+
actions: []
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import CoreBluetooth
|
|
2
|
+
|
|
3
|
+
// MARK: - CBCentralManagerDelegate (Eddystone BLE scanning)
|
|
4
|
+
|
|
5
|
+
internal final class BluetoothDelegate: NSObject, CBCentralManagerDelegate {
|
|
6
|
+
private weak var module: ExpoBeaconModule?
|
|
7
|
+
|
|
8
|
+
init(module: ExpoBeaconModule) {
|
|
9
|
+
self.module = module
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
|
13
|
+
switch central.state {
|
|
14
|
+
case .poweredOn:
|
|
15
|
+
module?.ensureBleScanRunning()
|
|
16
|
+
case .unauthorized:
|
|
17
|
+
print("[ExpoBeacon] Bluetooth authorization denied — Eddystone scanning/monitoring unavailable. " +
|
|
18
|
+
"Ensure NSBluetoothAlwaysUsageDescription is set in Info.plist.")
|
|
19
|
+
module?.handleBluetoothStateError(code: "BLUETOOTH_UNAUTHORIZED", message: "Bluetooth authorization denied — Eddystone scanning/monitoring unavailable")
|
|
20
|
+
module?.eddystoneScanPromise?.reject("BLUETOOTH_UNAUTHORIZED", "Bluetooth permission denied")
|
|
21
|
+
module?.eddystoneScanPromise = nil
|
|
22
|
+
case .poweredOff:
|
|
23
|
+
print("[ExpoBeacon] Bluetooth is powered off — Eddystone scanning/monitoring unavailable.")
|
|
24
|
+
module?.handleBluetoothStateError(code: "BLUETOOTH_OFF", message: "Bluetooth is powered off — Eddystone scanning/monitoring unavailable")
|
|
25
|
+
module?.eddystoneScanPromise?.reject("BLUETOOTH_OFF", "Bluetooth is powered off")
|
|
26
|
+
module?.eddystoneScanPromise = nil
|
|
27
|
+
default:
|
|
28
|
+
break
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func centralManager(_ central: CBCentralManager,
|
|
33
|
+
didDiscover peripheral: CBPeripheral,
|
|
34
|
+
advertisementData: [String: Any],
|
|
35
|
+
rssi RSSI: NSNumber) {
|
|
36
|
+
module?.handleEddystoneDiscovery(advertisementData: advertisementData, rssi: RSSI)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String: Any]) {
|
|
40
|
+
// State restoration: CBCentralManager was recreated by iOS after app was killed.
|
|
41
|
+
// Scanning will be re-started in centralManagerDidUpdateState when state is .poweredOn.
|
|
42
|
+
}
|
|
43
|
+
}
|