
Security News
Ruby's Bundler 4.0.18 Extends Cooldown to bundle lock and bundle cache
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.
@wklm/react
Advanced tools
React hooks for Bluetooth Low Energy — useDevice, useScan, useProfile. Real-time BLE data in React
A production-ready React SDK for Web Bluetooth, enabling seamless BLE device integration in your React applications. Works with the WebBLE Safari Extension to provide full Web Bluetooth API support across all browsers.
npm install @wklm/react
# or
yarn add @wklm/react
# or
pnpm add @wklm/react
import { WebBLE } from '@wklm/react';
function App() {
return (
<WebBLE.Provider>
<YourApp />
</WebBLE.Provider>
);
}
import { WebBLE } from '@wklm/react';
function MyComponent() {
const { requestDevice, isAvailable } = WebBLE.useBluetooth();
const handleConnect = async () => {
const device = await requestDevice({
filters: [{ services: ['heart_rate'] }]
});
if (device) {
console.log('Connected to', device.name);
}
};
if (!isAvailable) {
return <div>Bluetooth not available</div>;
}
return (
<button onClick={handleConnect}>
Connect to Heart Rate Monitor
</button>
);
}
useBluetooth()Main hook for Bluetooth operations.
const {
isAvailable, // Is Web Bluetooth available?
isExtensionInstalled, // Is WebBLE extension installed?
requestDevice, // Request device from user
getDevices, // Get paired devices
requestLEScan // Start BLE scanning
} = WebBLE.useBluetooth();
useDevice(deviceId)Manage a specific Bluetooth device.
const {
device, // Device object
isConnected, // Connection status
connect, // Connect to device
disconnect, // Disconnect from device
services, // Available GATT services
connectionState, // 'connecting' | 'connected' | 'disconnecting' | 'disconnected'
rssi // Signal strength
} = WebBLE.useDevice(deviceId);
useCharacteristic(characteristicId)Read/write BLE characteristics.
const {
value, // Current value (DataView)
properties, // Characteristic properties
readValue, // Read from characteristic
writeValue, // Write to characteristic
startNotifications, // Subscribe to changes
stopNotifications // Unsubscribe from changes
} = WebBLE.useCharacteristic(characteristicId);
useNotifications(characteristicId)Real-time notifications from BLE devices.
const {
value, // Latest value
isSubscribed, // Subscription status
subscribe, // Start notifications
unsubscribe, // Stop notifications
history // Value history
} = WebBLE.useNotifications(characteristicId);
useScan(options)Scan for nearby BLE devices.
const {
isScanning, // Scan status
devices, // Found devices
startScan, // Begin scanning
stopScan, // Stop scanning
error // Scan errors
} = WebBLE.useScan({
filters: [{ namePrefix: 'Device' }],
keepRepeatedDevices: true
});
useConnection(deviceId)Advanced connection management.
const {
connectionState, // Detailed state
connectionQuality, // Signal quality
reconnect, // Manual reconnect
connectionPriority, // Get/set priority
setConnectionPriority // Update priority
} = WebBLE.useConnection(deviceId);
<DeviceScanner />Full-featured device selection UI.
<WebBLE.DeviceScanner
filters={[{ services: ['heart_rate'] }]}
onDeviceSelected={(device) => console.log('Selected:', device)}
showSignalStrength
autoConnect
/>
<ServiceExplorer />GATT service/characteristic explorer.
<WebBLE.ServiceExplorer
deviceId={deviceId}
expandedByDefault
showRawValues
onCharacteristicRead={(char, value) => console.log(char, value)}
/>
<ConnectionStatus />Connection state indicator.
<WebBLE.ConnectionStatus
deviceId={deviceId}
showDetails
showSignalStrength
className="connection-indicator"
/>
<InstallationWizard />Extension installation helper.
<WebBLE.InstallationWizard
onComplete={() => console.log('Extension installed!')}
className="install-wizard"
/>
const provider = (
<WebBLE.Provider config={{
autoReconnect: true,
reconnectAttempts: 5,
reconnectDelay: 1000
}}>
<App />
</WebBLE.Provider>
);
const { device } = WebBLE.useDevice(deviceId, {
cacheTimeout: 60000, // Cache for 1 minute
cachePolicy: 'write-through'
});
function MyComponent() {
const { requestDevice } = WebBLE.useBluetooth();
const connect = async () => {
try {
const device = await requestDevice();
// Handle device
} catch (error) {
if (error.name === 'NotFoundError') {
// User cancelled
} else if (error.name === 'NotAllowedError') {
// Permission denied
}
}
};
}
import { WebBLE, BluetoothDevice, BluetoothService } from '@wklm/react';
interface HeartRateData {
heartRate: number;
contactDetected: boolean;
}
function useHeartRate(device: BluetoothDevice): HeartRateData | null {
const { value } = WebBLE.useNotifications('heart_rate_measurement');
if (!value) return null;
return {
heartRate: value.getUint8(1),
contactDetected: Boolean(value.getUint8(0) & 0x01)
};
}
function HeartRateMonitor() {
const { requestDevice } = WebBLE.useBluetooth();
const [deviceId, setDeviceId] = useState<string>();
const { device, isConnected } = WebBLE.useDevice(deviceId);
const { value } = WebBLE.useNotifications('heart_rate_measurement');
const connect = async () => {
const device = await requestDevice({
filters: [{ services: ['heart_rate'] }]
});
if (device) setDeviceId(device.id);
};
const heartRate = value ? value.getUint8(1) : 0;
return (
<div>
{!isConnected ? (
<button onClick={connect}>Connect</button>
) : (
<div>Heart Rate: {heartRate} BPM</div>
)}
</div>
);
}
function SmartLight({ deviceId }: { deviceId: string }) {
const { writeValue } = WebBLE.useCharacteristic('light_control');
const setColor = (r: number, g: number, b: number) => {
const data = new Uint8Array([r, g, b]);
writeValue(data);
};
return (
<div>
<button onClick={() => setColor(255, 0, 0)}>Red</button>
<button onClick={() => setColor(0, 255, 0)}>Green</button>
<button onClick={() => setColor(0, 0, 255)}>Blue</button>
</div>
);
}
| Browser | Support | Notes |
|---|---|---|
| Safari 16+ | ✅ Full | Requires WebBLE Extension |
| Chrome 56+ | ✅ Full | Native support |
| Edge 79+ | ✅ Full | Native support |
| Firefox | ⚠️ Partial | Behind flag |
| iOS Safari | ✅ Full | Requires WebBLE Extension |
interface WebBLEProviderProps {
config?: {
autoReconnect?: boolean;
reconnectAttempts?: number;
reconnectDelay?: number;
cacheTimeout?: number;
debugMode?: boolean;
};
children: ReactNode;
}
interface RequestDeviceOptions {
filters?: Array<{
services?: string[];
name?: string;
namePrefix?: string;
manufacturerData?: Array<{
companyIdentifier: number;
dataPrefix?: ArrayBuffer;
}>;
}>;
optionalServices?: string[];
acceptAllDevices?: boolean;
}
interface BluetoothLEScanOptions {
filters?: BluetoothLEScanFilter[];
keepRepeatedDevices?: boolean;
acceptAllAdvertisements?: boolean;
}
We welcome contributions! Please see our Contributing Guide for details.
# Clone the repo
git clone https://github.com/wklm/WebBLE-Safari-Extension.git
# Install dependencies
cd packages/react-sdk
npm install
# Run tests
npm test
# Build
npm run build
# Run all tests
npm test
# Run with coverage
npm run test:coverage
# Run in watch mode
npm run test:watch
MIT © wklm
Built with the WebBLE Safari Extension to bring Web Bluetooth to all browsers.
FAQs
React hooks for Bluetooth Low Energy — useDevice, useScan, useProfile. Real-time BLE data in React
The npm package @wklm/react receives a total of 4 weekly downloads. As such, @wklm/react popularity was classified as not popular.
We found that @wklm/react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.