Skip to content

useBluetooth

Category
Export Size
626 B
Last Changed
5 days ago

Reactive Web Bluetooth API. Provides the ability to connect and interact with Bluetooth Low Energy peripherals.

The Web Bluetooth API lets websites discover and communicate with devices over the Bluetooth 4 wireless standard using the Generic Attribute Profile (GATT).

N.B. It is currently partially implemented in Android M, Chrome OS, Mac, and Windows 10. For a full overview of browser compatibility please see Web Bluetooth API Browser Compatibility

N.B. There are a number of caveats to be aware of with the web bluetooth API specification. Please refer to the Web Bluetooth W3C Draft Report for numerous caveats around device detection and connection.

N.B. This API is not available in Web Workers (not exposed via WorkerNavigator).

Demo

Usage

tsx
import { 
useBluetooth
} from '@reause/core'
const {
isSupported
,
isConnected
,
device
,
requestDevice
,
server
,
error
,
} =
useBluetooth
({
acceptAllDevices
: true,
})

Call requestDevice() from a user gesture (e.g. a click handler), then work with server once isConnected is true:

tsx
function 
Component
() {
const {
isSupported
,
isConnected
,
device
,
requestDevice
,
error
} =
useBluetooth
({
acceptAllDevices
: true,
}) return ( <
div
>
<
button
type="button" onClick={() => void
requestDevice
()}>
Request
Bluetooth Device
</button> {device ? ( <
div
>
Device Name: {device.name} </div> ) : null} <
div
>{
isConnected
? 'Connected' : 'Not Connected'}</div>
{error ? ( <
div
>
Error
:
{
String
(
error
)}
</div> ) : null} {isSupported ? null : <
div
>Your browser does not support the Bluetooth Web API</div>}
</div> ) }

Return Values

PropertyTypeDescription
isSupportedbooleanWhether the Web Bluetooth API is supported
isConnectedbooleanWhether a device is currently connected
deviceBluetoothDevice | undefinedThe connected Bluetooth device
serverBluetoothRemoteGATTServer | undefinedThe GATT server for the connected device
errorunknown | nullAny error that occurred during connection
requestDevice() => Promise<void>Function to request a Bluetooth device

Unlike upstream, the members are plain values read off the returned object instead of refs — read them during render (or from result.current in tests); no .value is involved.

When the device has paired and is connected, you can then work with the server object as you wish.

Usage Battery Level Example

This sample illustrates the use of the Web Bluetooth API to read battery level and be notified of changes from a nearby Bluetooth Device advertising Battery information with Bluetooth Low Energy.

Here, we use the characteristicvaluechanged event listener to handle reading battery level characteristic value. This event listener will optionally handle upcoming notifications as well.

tsx
import type { BluetoothRemoteGATTCharacteristic } from '@reause/core'
import { 
useBluetooth
,
useEventListener
} from '@reause/core'
import {
useEffect
,
useState
} from 'react'
export default function
Component
() {
const {
isSupported
,
isConnected
,
device
,
requestDevice
,
server
,
error
,
} =
useBluetooth
({
acceptAllDevices
: true,
optionalServices
: [
'battery_service', ], }) const [
batteryPercent
,
setBatteryPercent
] =
useState
<number>()
const [
batteryLevelCharacteristic
,
setBatteryLevelCharacteristic
]
=
useState
<BluetoothRemoteGATTCharacteristic>()
// Attempt to get the battery levels once, on the initial connection:
useEffect
(() => {
if (!
isConnected
|| !
server
||
batteryLevelCharacteristic
)
return let
cancelled
= false
async function
getBatteryLevels
() {
// Get the battery service: const
batteryService
= await
server
.
getPrimaryService
('battery_service')
// Get the current battery level characteristic: const
characteristic
= await
batteryService
.
getCharacteristic
('battery_level')
if (
cancelled
)
return
setBatteryLevelCharacteristic
(
characteristic
)
// Convert received buffer to number: const
batteryLevel
= await
characteristic
.
readValue
()
if (!
cancelled
)
setBatteryPercent
(
batteryLevel
.
getUint8
(0))
} void
getBatteryLevels
()
return () => {
cancelled
= true
} }, [
isConnected
,
server
,
batteryLevelCharacteristic
])
// Listen to when characteristic value changes on `characteristicvaluechanged` event:
useEventListener
(
batteryLevelCharacteristic
, 'characteristicvaluechanged', (
event
) => {
const
target
=
event
.target as BluetoothRemoteGATTCharacteristic
setBatteryPercent
(
target
.
value
.
getUint8
(0))
}, {
passive
: true })
return ( <
div
>
<
button
type="button" onClick={() => void
requestDevice
()}>
Request
Bluetooth Device
</button> {device ? ( <
div
>
Device Name: {device.name} </div> ) : null} {batteryPercent != null ? <
div
>{`Battery Level: ${batteryPercent}%`}</div>
: null} {error ? ( <
div
>
Error
:
{
String
(
error
)}
</div> ) : null} {isSupported ? null : <
div
>Your browser does not support the Bluetooth Web API</div>}
</div> ) }

More samples can be found on Google Chrome's Web Bluetooth Samples.

Type Declarations

Toggle
ts
export type BluetoothServiceUUID = string | number

export interface BluetoothLEScanFilter {
    services?: BluetoothServiceUUID[];
    name?: string;
    namePrefix?: string;
}

export interface BluetoothRequestDeviceOptions {
    acceptAllDevices?: boolean;
    filters?: BluetoothLEScanFilter[];
    optionalServices?: BluetoothServiceUUID[];
}

export interface Bluetooth {
    requestDevice: (options?: BluetoothRequestDeviceOptions) => Promise<BluetoothDevice>;
    getAvailability: () => Promise<boolean>;
}

export interface BluetoothCharacteristicProperties {
    readonly broadcast: boolean;
    readonly read: boolean;
    readonly writeWithoutResponse: boolean;
    readonly write: boolean;
    readonly notify: boolean;
    readonly indicate: boolean;
    readonly authenticatedSignedWrites: boolean;
    readonly reliableWrite: boolean;
    readonly writableAuxiliaries: boolean;
}

export interface BluetoothRemoteGATTCharacteristic extends EventTarget {
    readonly service: BluetoothRemoteGATTService;
    readonly uuid: string;
    readonly properties: BluetoothCharacteristicProperties;
    readonly value: DataView;
    getDescriptor: (uuid: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTDescriptor>;
    getDescriptors: (uuid?: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTDescriptor[]>;
    readValue: () => Promise<DataView>;
    writeValue: (value: BufferSource) => Promise<void>;
    writeValueWithResponse: (value: BufferSource) => Promise<void>;
    writeValueWithoutResponse: (value: BufferSource) => Promise<void>;
    startNotifications: () => Promise<BluetoothRemoteGATTCharacteristic>;
    stopNotifications: () => Promise<BluetoothRemoteGATTCharacteristic>;
}

export interface BluetoothRemoteGATTDescriptor extends EventTarget {
    readonly characteristic: BluetoothRemoteGATTCharacteristic;
    readonly uuid: string;
    readonly value: DataView;
    readValue: () => Promise<DataView>;
    writeValue: (value: BufferSource) => Promise<void>;
}

export interface BluetoothRemoteGATTService extends EventTarget {
    readonly device: BluetoothDevice;
    readonly uuid: string;
    readonly isPrimary: boolean;
    getCharacteristic: (characteristic: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTCharacteristic>;
    getCharacteristics: (characteristic?: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTCharacteristic[]>;
    getIncludedService: (service: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTService>;
    getIncludedServices: (service?: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTService[]>;
}

export interface BluetoothRemoteGATTServer {
    readonly connected: boolean;
    readonly device: BluetoothDevice;
    connect: () => Promise<BluetoothRemoteGATTServer>;
    disconnect: () => void;
    getPrimaryService: (service: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTService>;
    getPrimaryServices: (service?: BluetoothServiceUUID) => Promise<BluetoothRemoteGATTService[]>;
}

export interface BluetoothDevice extends EventTarget {
    readonly id: string;
    readonly name?: string;
    readonly gatt?: BluetoothRemoteGATTServer;
    readonly connected?: boolean;
    readonly watchingAdvertisements: boolean;
    forget: () => Promise<void>;
    watchAdvertisements: () => Promise<void>;
    unwatchAdvertisements: () => void;
}

export interface UseBluetoothRequestDeviceOptions {
    filters?: BluetoothLEScanFilter[] | undefined;
    optionalServices?: BluetoothServiceUUID[] | undefined;
}

export interface UseBluetoothOptions extends UseBluetoothRequestDeviceOptions, ConfigurableNavigator {
    acceptAllDevices?: boolean;
}

export interface UseBluetoothReturn {
    isSupported: boolean;
    isConnected: boolean;
    device: BluetoothDevice | undefined;
    requestDevice: () => Promise<void>;
    server: BluetoothRemoteGATTServer | undefined;
    error: unknown | null;
}

export interface ConfigurableNavigator {
    navigator?: Navigator;
}

export interface UseUserMediaOptions extends ConfigurableNavigator {
    enabled?: boolean;
    autoSwitch?: boolean;
    constraints?: MediaStreamConstraints;
}

export function useBluetooth(options?: UseBluetoothOptions): UseBluetoothReturn

Source

Source · Demo · VueUse

Contributors

hairyf

Changelog

v0.1.0 on
1f0f4 - fix(core): resolve useBluetooth audit findings (#521)
e8045 - feat(core): add useBluetooth (#84)

Released under the MIT License. v0.1.8