The Bluetooth LE bridge scans for peripherals, connects, lists services and characteristics, reads and writes them, and streams notifications to the page as events. It’s backed by Shiny.BluetoothLE.
Android, iOS, Mac Catalyst, macOS (AppKit) and Windows. Linux answers 501.
dotnet add package Shiny.AppDeviceBridge.BluetoothLE
builder. UseAppDeviceBridge (
bridge => bridge. AddBluetoothLEBridge (),
Client
C#
TypeScript
IBluetoothLEBridge
AddBluetoothLEBridgeClient()
BluetoothLEBridge
Listen before you start: a scan and a characteristic subscription run only while something listens to their events,
and starting one without a listener answers 409 not_listening — see Events .
Characteristic values travel as base64 in JSON.
import { BluetoothLEBridge } from "@shinyorg/appdevicebridge" ;
const ble = new BluetoothLEBridge ();
const status = await ble. requestAccess ();
const stopScan = await ble. onScanResult ( r => console. log (r.uuid, r.name, r.rssi));
await ble. startScan ({ serviceUuids: [ "180D" ] }); // heart rate
stopScan (); // the scan stops once nothing listens
const peripheral = await ble. connect (uuid, { timeoutMs: 10_000 });
const value = await ble. read (uuid, "180A" , "2A29" ); // manufacturer name, base64
await ble. onNotification ( n => render ( atob (n.data ?? "" )));
await ble. startNotifications (uuid, "180D" , "2A37" );
Platform setup is Shiny.BluetoothLE’s: NSBluetoothAlwaysUsageDescription on Apple platforms, BLUETOOTH_SCAN and
BLUETOOTH_CONNECT (location before Android 12) on Android.
GET /_bridge/ ble/statusWhether Bluetooth is available to the app, and whether a scan is running. POST /_bridge/ ble/accessRequests Bluetooth access. POST /_bridge/ ble/scanStarts scanning; results arrive through onScanResult, so listen first: without a listener it fails with 409. DELETE /_bridge/ ble/scanStops scanning. GET /_bridge/ ble/peripheralsThe peripherals connected now. GET /_bridge/ ble/peripherals/{uuid} A peripheral seen in a scan. POST /_bridge/ ble/peripherals/{uuid} /connectionConnects. DELETE /_bridge/ ble/peripherals/{uuid} /connectionDisconnects, ending its notifications. GET /_bridge/ ble/peripherals/{uuid} /rssiThe connected peripheral's signal strength. GET /_bridge/ ble/peripherals/{uuid} /servicesThe connected peripheral's services. GET /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristicsA service's characteristics. GET /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} Reads a characteristic. PUT /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} Writes a characteristic. POST /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} /notificationsSubscribes to a characteristic; values arrive through onNotification, so listen first: without a listener it fails with 409. DELETE /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} /notificationsUnsubscribes from a characteristic. Whether Bluetooth is available to the app, and whether a scan is running.
C# IBluetoothLEBridge.GetStatusAsyncTS BluetoothLEBridge.getStatus
Response 200 BleStatus BleStatus · 2 fields Requests Bluetooth access.
C# IBluetoothLEBridge.RequestAccessAsyncTS BluetoothLEBridge.requestAccess
Response 200 BleStatus BleStatus · 2 fields Starts scanning; results arrive through onScanResult, so listen first: without a listener it fails with 409. Starting again replaces the running scan, and the scan stops once nothing listens to it.
C# IBluetoothLEBridge.StartScanAsyncTS BluetoothLEBridge.startScan
Body application/json · BleScanRequest BleScanRequest · 1 field serviceUuidsstring [] | null Only report peripherals advertising one of these services; every peripheral when empty.
Response 204 No contentErrors 409 ConflictStops scanning.
C# IBluetoothLEBridge.StopScanAsyncTS BluetoothLEBridge.stopScan
Response 204 No contentGET /_bridge/ ble/peripherals# The peripherals connected now.
C# IBluetoothLEBridge.GetConnectedPeripheralsAsyncTS BluetoothLEBridge.getConnectedPeripherals
Response 200 BlePeripheral []BlePeripheral · 4 fields GET /_bridge/ ble/peripherals/{uuid} # A peripheral seen in a scan.
C# IBluetoothLEBridge.GetPeripheralAsyncTS BluetoothLEBridge.getPeripheral
Parameter In Type uuidpath string required
Response 200 BlePeripheral BlePeripheral · 4 fields POST /_bridge/ ble/peripherals/{uuid} /connection# Connects. Fails with 504 on timeout, 409 when the connection fails.
C# IBluetoothLEBridge.ConnectAsyncTS BluetoothLEBridge.connect
Parameter In Type uuidpath string required
Body application/json · BleConnectRequest BleConnectRequest · 2 fields autoConnectboolean Reconnect when the peripheral comes back in range. timeoutMsnumber | null How long to wait for the connection; 30 seconds when null.
Response 200 BlePeripheral BlePeripheral · 4 fields Errors 409 Conflict504 DELETE /_bridge/ ble/peripherals/{uuid} /connection# Disconnects, ending its notifications.
C# IBluetoothLEBridge.DisconnectAsyncTS BluetoothLEBridge.disconnect
Parameter In Type uuidpath string required
Response 204 No contentGET /_bridge/ ble/peripherals/{uuid} /services# The connected peripheral's services.
C# IBluetoothLEBridge.GetServicesAsyncTS BluetoothLEBridge.getServices
Parameter In Type uuidpath string required
Response 200 BleService []BleService · 1 field GET /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics# A service's characteristics.
C# IBluetoothLEBridge.GetCharacteristicsAsyncTS BluetoothLEBridge.getCharacteristics
Parameter In Type uuidpath string required servicepath string required
Response 200 BleCharacteristic []BleCharacteristic · 4 fields GET /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} # Reads a characteristic.
C# IBluetoothLEBridge.ReadAsyncTS BluetoothLEBridge.read
Parameter In Type uuidpath string required servicepath string required characteristicpath string required
Response 200 BleCharacteristicValue BleCharacteristicValue · 3 fields serviceUuidstring characteristicUuidstring datastring | null Base64 in JSON.
PUT /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} # Writes a characteristic.
C# IBluetoothLEBridge.WriteAsyncTS BluetoothLEBridge.write
Parameter In Type uuidpath string required servicepath string required characteristicpath string required
Body application/json · BleWriteRequest BleWriteRequest · 2 fields dataBlob | ArrayBuffer | Uint8Array Base64 in JSON. withResponseboolean Wait for the peripheral to acknowledge the write.
Response 204 No contentPOST /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} /notifications# Subscribes to a characteristic; values arrive through onNotification, so listen first: without a listener it fails with 409. Every subscription ends once that has no listener left; peripherals stay connected.
C# IBluetoothLEBridge.StartNotificationsAsyncTS BluetoothLEBridge.startNotifications
Parameter In Type uuidpath string required servicepath string required characteristicpath string required
Response 204 No contentErrors 409 ConflictDELETE /_bridge/ ble/peripherals/{uuid} /services/{service} /characteristics/{characteristic} /notifications# Unsubscribes from a characteristic.
C# IBluetoothLEBridge.StopNotificationsAsyncTS BluetoothLEBridge.stopNotifications
Parameter In Type uuidpath string required servicepath string required characteristicpath string required
Response 204 No content
A peripheral seen by the running scan. Raised for every advertisement.
C# IBluetoothLEBridge.OnScanResultAsyncTS BluetoothLEBridge.onScanResult
Payload BleScanResult uuidstring namestring | null rssinumber localNamestring | null isConnectableboolean | null serviceUuidsstring [] | null txPowernumber | null manufacturerIdnumber | null manufacturerDatastring | null Base64 in JSON.
A peripheral this page connected to changed connection state.
C# IBluetoothLEBridge.OnStatusAsyncTS BluetoothLEBridge.onStatus
Payload BlePeripheralStatus A subscribed characteristic changed.
C# IBluetoothLEBridge.OnNotificationAsyncTS BluetoothLEBridge.onNotification
Payload BleNotification peripheralUuidstring serviceUuidstring characteristicUuidstring datastring | null Base64 in JSON.
A scan or a notification subscription failed and has ended.
C# IBluetoothLEBridge.OnErrorAsyncTS BluetoothLEBridge.onError
Payload BleError operationstring scan or notify.peripheralUuidstring | null messagestring
JSON property names are camelCase and enums travel as their names. A ? marks a property the payload may omit;| null one that may be null.
Where a permission stands. Reported by every bridge that needs one; the names match Shiny's own.
"Unknown""NotSupported""NotSetup""Disabled""Restricted""Denied""Available"
serviceUuids?string [] | null Only report peripherals advertising one of these services; every peripheral when empty.
"Disconnected""Disconnecting""Connected""Connecting"
autoConnect?boolean Reconnect when the peripheral comes back in range. timeoutMs?number | null How long to wait for the connection; 30 seconds when null.
BleCharacteristicPropertyenum # What a characteristic supports.
"Broadcast""Read""WriteWithoutResponse""Write""Notify""Indicate""AuthenticatedSignedWrites""ExtendedProperties""NotifyEncryptionRequired""IndicateEncryptionRequired"
BleCharacteristicValueobject # serviceUuidstring characteristicUuidstring datastring | null Base64 in JSON.
dataBlob | ArrayBuffer | Uint8Array Base64 in JSON. withResponse?boolean Wait for the peripheral to acknowledge the write.
An advertisement.
uuidstring namestring | null rssinumber localNamestring | null isConnectableboolean | null serviceUuidsstring [] | null txPowernumber | null manufacturerIdnumber | null manufacturerDatastring | null Base64 in JSON.
BlePeripheralStatusobject # peripheralUuidstring serviceUuidstring characteristicUuidstring datastring | null Base64 in JSON.
operationstring scan or notify.peripheralUuidstring | null messagestring
These routes sit under AppDeviceBridgePolicies.Bridges like every other bridge: callers on this device by default.
See Security .