@capgo/capacitor-uwb
v8.0.3
Published
Capacitor plugin for Ultra-Wideband (UWB) ranging on iOS and Android.
Downloads
395
Maintainers
Readme
@capgo/capacitor-uwb
Capacitor plugin for Ultra-Wideband (UWB) ranging on iOS and Android.
Why this plugin
This plugin wraps the native UWB ranging APIs on iOS and Android so a Capacitor app can:
- Check whether the current device supports UWB ranging.
- Run peer-to-peer ranging on iOS with Apple's Nearby Interaction framework.
- Run controller/controlee ranging sessions on Android with Jetpack
androidx.core.uwb. - Receive distance, direction, and session lifecycle updates through plugin listeners.
On iOS, peers exchange NIDiscoveryToken values out-of-band, then call startPeerSession().
On Android, the controller shares ranging parameters out-of-band before the controlee starts its session.
Platform support
| Platform | Support | |----------|---------| | iOS | ✅ Nearby Interaction peer ranging with distance and direction | | Android | ✅ Jetpack UWB controller/controlee sessions (Android 12+, UWB hardware) | | Web | ❌ Not available |
Compatibility
| Plugin version | Capacitor compatibility | Maintained | | -------------- | ----------------------- | ---------- | | v8.. | v8.. | ✅ | | v7.. | v7.. | On demand | | v6.. | v6.. | On demand |
The plugin major version follows the Capacitor major version.
Install
You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:
npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-pluginsThen use the following prompt:
Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-uwb` plugin in my project.If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
bun add @capgo/capacitor-uwb
bunx cap syncUsage
import { CapacitorUwb } from '@capgo/capacitor-uwb';
const availability = await CapacitorUwb.isAvailable();
if (!availability.available) {
return;
}
await CapacitorUwb.addListener('rangingUpdate', (update) => {
console.log(update.distanceMeters, update.direction);
});
// iOS: exchange discovery tokens out-of-band, then start ranging
const { discoveryToken } = await CapacitorUwb.getDiscoveryToken();
await CapacitorUwb.startPeerSession({ peerDiscoveryToken: '<peer-token-base64>' });
// Android: controller shares ranging parameters out-of-band
const controller = await CapacitorUwb.startControllerSession();
await CapacitorUwb.startControleeSession({
rangingParameters: {
...controller.rangingParameters,
peerAddress: controller.localAddress,
},
});
await CapacitorUwb.stopSession();Notes
- Test on real UWB hardware. Simulators and most desktop browsers do not expose UWB radios.
- iOS: Add the Nearby Interaction capability in Xcode and set
NSNearbyInteractionUsageDescriptioninInfo.plist. - Android: The plugin declares
android.permission.UWB_RANGING. Exchange ranging parameters out-of-band between controller and controlee before starting sessions. - Web:
isAvailable()returnssupported: false.
Full setup guides: capgo.app/docs/plugins/uwb
Example app
The example-app/ folder contains a small Vite demo for checking availability, exchanging session parameters, listening for ranging updates, and stopping sessions.
API
isAvailable()getDiscoveryToken()startPeerSession(...)startControllerSession(...)startControleeSession(...)stopSession()addListener('rangingUpdate', ...)addListener('sessionStateChanged', ...)removeAllListeners()getPluginVersion()- Interfaces
- Type Aliases
Capacitor plugin for Ultra-Wideband (UWB) ranging on iOS and Android.
iOS uses Apple's Nearby Interaction framework for peer-to-peer ranging.
Android uses Jetpack androidx.core.uwb for controller/controlee sessions.
Both platforms require exchanging discovery tokens or ranging parameters out-of-band (for example over Bluetooth LE or a backend).
isAvailable()
isAvailable() => Promise<UwbAvailabilityResult>Check whether UWB is supported and currently available on the device.
Returns: Promise<UwbAvailabilityResult>
Since: 8.0.0
getDiscoveryToken()
getDiscoveryToken() => Promise<DiscoveryTokenResult>Get the local Nearby Interaction discovery token on iOS.
Share the returned token with a peer out-of-band, then call
startPeerSession() with the peer token.
Returns: Promise<DiscoveryTokenResult>
Since: 8.0.0
startPeerSession(...)
startPeerSession(options: StartPeerSessionOptions) => Promise<void>Start a Nearby Interaction peer session on iOS.
| Param | Type |
| ------------- | --------------------------------------------------------------------------- |
| options | StartPeerSessionOptions |
Since: 8.0.0
startControllerSession(...)
startControllerSession(options?: StartControllerSessionOptions | undefined) => Promise<AndroidControllerSessionResult>Start an Android UWB controller session and return shareable parameters.
| Param | Type |
| ------------- | --------------------------------------------------------------------------------------- |
| options | StartControllerSessionOptions |
Returns: Promise<AndroidControllerSessionResult>
Since: 8.0.0
startControleeSession(...)
startControleeSession(options: StartControleeSessionOptions) => Promise<void>Start an Android UWB controlee session with parameters from the controller.
| Param | Type |
| ------------- | ------------------------------------------------------------------------------------- |
| options | StartControleeSessionOptions |
Since: 8.0.0
stopSession()
stopSession() => Promise<void>Stop the active UWB ranging session.
Since: 8.0.0
addListener('rangingUpdate', ...)
addListener(eventName: 'rangingUpdate', listenerFunc: (event: RangingUpdateEvent) => void) => Promise<PluginListenerHandle>Listen for distance and direction updates from an active session.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------- |
| eventName | 'rangingUpdate' |
| listenerFunc | (event: RangingUpdateEvent) => void |
Returns: Promise<PluginListenerHandle>
Since: 8.0.0
addListener('sessionStateChanged', ...)
addListener(eventName: 'sessionStateChanged', listenerFunc: (event: SessionStateChangedEvent) => void) => Promise<PluginListenerHandle>Listen for session lifecycle changes.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------------------- |
| eventName | 'sessionStateChanged' |
| listenerFunc | (event: SessionStateChangedEvent) => void |
Returns: Promise<PluginListenerHandle>
Since: 8.0.0
removeAllListeners()
removeAllListeners() => Promise<void>Remove all registered listeners for this plugin.
Since: 8.0.0
getPluginVersion()
getPluginVersion() => Promise<PluginVersionResult>Get the current native plugin version.
Returns: Promise<PluginVersionResult>
Since: 8.0.0
Interfaces
UwbAvailabilityResult
Result returned by isAvailable().
| Prop | Type | Description | Since |
| --------------- | ---------------------------------------- | ------------------------------------------------------------------- | ----- |
| supported | boolean | Whether the device hardware supports UWB ranging. | 8.0.0 |
| available | boolean | Whether UWB is currently available and ready for a ranging session. | 8.0.0 |
| platform | 'ios' | 'android' | 'web' | Platform label returned by the native or web implementation. | 8.0.0 |
DiscoveryTokenResult
Result returned by getDiscoveryToken() on iOS.
| Prop | Type | Description | Since |
| -------------------- | ------------------- | ------------------------------------------------------------------- | ----- |
| discoveryToken | string | Base64-encoded NIDiscoveryToken to share with a peer out-of-band. | 8.0.0 |
StartPeerSessionOptions
Options for startPeerSession() on iOS.
| Prop | Type | Description | Since |
| ------------------------------- | -------------------- | ------------------------------------------------------------- | ----- |
| peerDiscoveryToken | string | Base64-encoded peer NIDiscoveryToken. | 8.0.0 |
| isCameraAssistanceEnabled | boolean | Whether to enable camera assistance when supported (iOS 16+). | 8.0.0 |
AndroidControllerSessionResult
Parameters returned when starting an Android controller session.
| Prop | Type | Description | Since |
| ----------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------- | ----- |
| rangingParameters | AndroidRangingParameters | Ranging parameters to share with the controlee out-of-band. | 8.0.0 |
| localAddress | string | Local UWB address as a base64-encoded byte array. | 8.0.0 |
AndroidRangingParameters
Android ranging parameters exchanged out-of-band between controller and controlee.
| Prop | Type | Description | Since |
| ------------------------ | --------------------------------------------------------------- | ------------------------------------------------------------- | ----- |
| sessionId | number | Session identifier shared by both peers. | 8.0.0 |
| sessionKeyInfo | string | Optional base64-encoded session key info. | 8.0.0 |
| subSessionId | number | Optional sub-session identifier for provisioned STS. | 8.0.0 |
| subSessionKeyInfo | string | Optional base64-encoded sub-session key info. | 8.0.0 |
| complexChannel | UwbComplexChannel | Channel configuration for the ranging session. | 8.0.0 |
| peerAddress | string | Peer UWB address as a base64-encoded byte array. | 8.0.0 |
| uwbConfigType | number | UWB config type. Defaults to unicast DS-TWR on Android. | 8.0.0 |
| slotDurationMillis | number | Slot duration in milliseconds. | 8.0.0 |
| updateRateType | number | Ranging update rate type from RangingParameters on Android. | 8.0.0 |
UwbComplexChannel
Android UWB complex channel exchanged out-of-band with a peer.
| Prop | Type | Description | Since |
| ------------------- | ------------------- | -------------------------------------------- | ----- |
| channel | number | UWB channel number. | 8.0.0 |
| preambleIndex | number | Preamble index used for the ranging session. | 8.0.0 |
StartControllerSessionOptions
Options for startControllerSession() on Android.
| Prop | Type | Description | Since |
| ------------------------ | --------------------------------------------------------------- | -------------------------------------------------------------------------- | ----- |
| sessionId | number | Session identifier shared with the controlee. | 8.0.0 |
| sessionKeyInfo | string | Optional base64-encoded session key info. | 8.0.0 |
| subSessionId | number | Optional sub-session identifier. | 8.0.0 |
| subSessionKeyInfo | string | Optional base64-encoded sub-session key info. | 8.0.0 |
| complexChannel | UwbComplexChannel | UWB channel configuration. | 8.0.0 |
| uwbConfigType | number | UWB config type. Defaults to unicast DS-TWR. | 8.0.0 |
| slotDurationMillis | number | Slot duration in milliseconds. | 8.0.0 |
| updateRateType | number | Ranging update rate type from RangingParameters on Android. | 8.0.0 |
| peerAddress | string | Optional controlee UWB address. When provided, ranging starts immediately. | 8.0.0 |
StartControleeSessionOptions
Options for startControleeSession() on Android.
| Prop | Type | Description | Since |
| ----------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------ | ----- |
| rangingParameters | AndroidRangingParameters | Ranging parameters received from the controller out-of-band. | 8.0.0 |
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
RangingUpdateEvent
Payload emitted by the rangingUpdate listener.
| Prop | Type | Description | Since |
| ---------------------------- | ----------------------------------------------------- | ------------------------------------------------------------ | ----- |
| distanceMeters | number | Estimated distance to the peer in meters. | 8.0.0 |
| direction | UwbDirection | Direction vector toward the peer when available. | 8.0.0 |
| azimuthRadians | number | Azimuth angle in radians when available. | 8.0.0 |
| elevationRadians | number | Elevation angle in radians when available. | 8.0.0 |
| horizontalAngleRadians | number | Horizontal angle in radians when available. | 8.0.0 |
| timestamp | number | Unix timestamp in milliseconds when the update was received. | 8.0.0 |
UwbDirection
3D direction vector reported by UWB ranging.
| Prop | Type | Description | Since |
| ------- | ------------------- | ------------------------------------ | ----- |
| x | number | X component of the direction vector. | 8.0.0 |
| y | number | Y component of the direction vector. | 8.0.0 |
| z | number | Z component of the direction vector. | 8.0.0 |
SessionStateChangedEvent
Payload emitted by the sessionStateChanged listener.
| Prop | Type | Description | Since |
| ------------ | ----------------------------------------------------------- | ---------------------------------------------------- | ----- |
| state | UwbSessionState | Current session state. | 8.0.0 |
| reason | string | Optional human-readable reason or error description. | 8.0.0 |
PluginVersionResult
Result returned when requesting the plugin version.
| Prop | Type | Description | Since |
| ------------- | ------------------- | ----------------------------- | ----- |
| version | string | Native plugin version string. | 8.0.0 |
Type Aliases
UwbSessionState
Session lifecycle states reported by the plugin.
'initialized' | 'running' | 'suspended' | 'resumed' | 'invalidated' | 'stopped' | 'peerDisconnected'
