This feature is only available at request - get free access by emailing us at ble@despia.com
Drive a full BLE central stack from JavaScript, scan for peripherals, connect to them, discover services and characteristics, read and write values, and subscribe to notifications. Connection state and notification data are delivered through global
window callbacks, with automatic persistence and replay when the app is backgrounded or closed.
Foreground BLE works out of the box. Background scanning, background connections, and background notifications require the Bluetooth addon to be enabled in Despia Editor > App > Addons, followed by a fresh native build.
Installation
- Bundle
- CDN
How it works
Commands are dispatched throughdespia(). Results, events, and data come back through global window callbacks that you define before issuing any command. The native side never buffers foreground events, so a callback defined after the event fires misses that event.
window.bluetoothActive to true on grant and fires onBleState with the current power state.
Permission and power state
Permission is exposed aswindow.bluetoothActive (boolean). Power and permission combined come through onBleState, which fires on every change without polling, including mid-session permission revoke from the system Settings app.
scan and connect issued while the radio is off are deferred internally and run automatically once Bluetooth is powered on. Every other command silently no-ops if its precondition is not met (read before connect, write before discover, etc).
Scanning for devices
Filter by service UUID rather than by name, iOS does not always include the advertised name. Pass a comma-separated UUID list, omit it to scan everything. Bound every scan with aduration (milliseconds) so it stops automatically.
scan clears the previous scan’s discovered-device cache. iOS suspends scanning in the background, so always keep scans short and foreground.
Connecting and discovering services
Pass theid from an onBleDevice event into connect. After connected fires, call discover to retrieve the full service and characteristic tree. Use the properties array on each characteristic to decide between read, write, and subscribe.
auto_connect=true to have the bridge re-issue the connection automatically after an unexpected disconnect. An explicit disconnect clears this.
Reading and writing characteristics
Aread resolves to onBleData with source: 'read'. Writes accept three payload formats, pick exactly one, the bridge never guesses. Precedence if more than one is supplied is text then hex then value.
onBleWriteComplete immediately on dispatch, BLE has no transport-level ack for this mode, so success: true confirms the bytes left the radio, not that the peripheral received them. If the characteristic does not support write-with-response, the bridge falls back automatically.
Subscribing to notifications
Notifications are the only event source that survives the app being backgrounded or terminated. Subscribe afterconnected, and define a handler that works for both live events and replayed ones.
Background delivery and replay
When the app is not active,window.onBleX callbacks do not fire live. The bridge persists every event to disk (capped at the most recent 500, oldest dropped) and replays them in FIFO order through window.onBleEvent on the next app activation. Each replayed payload carries background: true and event: '<original callback name>'.
id, char, and timestamp, an event captured right at the foreground-to-background boundary can occasionally surface through both paths.
Always implement onBleEvent if anything that happens while backgrounded matters to your app. Scanning generally does not progress in the background on iOS, connections and notifications do once the Bluetooth addon is enabled.
Backend mirroring with server POST
Passserver=<url> to connect and subscribe to have the bridge POST every connection-state change and every notification to your backend as JSON. This runs independently of the web layer and continues to fire when the app is backgrounded or closed, so your server receives data even when no callback can run.
application/json POSTs:
battery is the device battery as an integer 0 to 100, or -1 if unavailable. Reads are intentionally not mirrored, only notifications and connection-state changes. The iOS POST is fire-and-forget with no retry, treat it as best-effort telemetry rather than a guaranteed-delivery channel and rely on the in-app event plus replay for correctness.
RSSI and signal strength
End-to-end, ESP32 text display
Scan filtered by service, connect to the first matching peripheral, discover, write a UTF-8 string without response.Editor setup for background BLE
Foreground scan, connect, read, write, and subscribe work without any Editor configuration. Enable the addon when you need notifications or connections to survive the app being backgrounded or closed.1
Enable the Bluetooth addon
Open the Despia Editor, go to App → Addons, and toggle Bluetooth on.
2
Rebuild the native app
Trigger a fresh build from the Despia Editor and reinstall on device. The addon is compiled into the binary, it cannot be applied over the air.
3
Verify background delivery
Connect to a peripheral with
auto_connect=true, subscribe to a notifying characteristic, background the app, then trigger a notification from the peripheral. On next app open, onBleEvent should replay the queued events with background: true.UUID formats and case
Three input formats are accepted, 16-bit (180d), 32-bit (8 hex), and 128-bit dashed (12345678-1234-1234-1234-1234567890ab). Other shapes cause the command to silently no-op. UUIDs returned in callback payloads are always lower-cased 128-bit strings, compare case-insensitively. valueHex is the one exception, it is upper-case hex.
Gotchas
idis an opaque per-iOS-device UUID, not a MAC address, and can change across reinstalls. Re-scan to obtain a freshidrather than hard-coding it.- Always define
window.onBleXcallbacks before issuing any command. There is no foreground buffering. - Always call
discoverbeforeread,write, orsubscribe. Pre-discovery calls no-op. - Write-without-response
success: trueconfirms dispatch, not delivery. Use write-with-response or an application-level ack when correctness matters. - iOS auto-negotiates ATT MTU on connect, small writes (tens of bytes) are fine. Chunk at the application layer for payloads beyond roughly 180 bytes.
- Server POST from iOS is fire-and-forget. Treat it as best-effort and rely on the in-app event plus replay for guaranteed delivery.
- Always bound
scanwithdurationor callstopscan. An unbounded scan drains the battery.
Resources
NPM Package
despia-native