The @capgo/capacitor-bluetooth-low-energy package provides comprehensive Bluetooth Low Energy (BLE) functionality for Capacitor apps. This tutorial will guide you through scanning for devices, connecting, and communicating with BLE peripherals.
To install the @capgo/capacitor-bluetooth-low-energy package, run the following command in your project's root directory:
npm install @capgo/capacitor-bluetooth-low-energy
npx cap sync
Add the following usage descriptions to your Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to communicate with BLE devices.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses Bluetooth to communicate with BLE devices.</string>
For background BLE support, also add:
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>bluetooth-peripheral</string>
</array>
The plugin automatically adds required permissions to your AndroidManifest.xml. For Android 12+, you need to request runtime permissions:
await BluetoothLowEnergy.requestPermissions();
The @capgo/capacitor-bluetooth-low-energy package provides the following API methods:
Initialize the BLE plugin. Must be called before any other method.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function initBLE() {
await BluetoothLowEnergy.initialize();
console.log('BLE initialized');
}
Check if Bluetooth is available and enabled on the device.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function checkBluetooth() {
const { available } = await BluetoothLowEnergy.isAvailable();
const { enabled } = await BluetoothLowEnergy.isEnabled();
console.log('Bluetooth available:', available);
console.log('Bluetooth enabled:', enabled);
}
Request Bluetooth permissions (required for Android 12+).
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function requestBLEPermissions() {
const status = await BluetoothLowEnergy.requestPermissions();
console.log('Permission status:', status);
}
Start and stop scanning for BLE devices.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function scanForDevices() {
// Listen for discovered devices
BluetoothLowEnergy.addListener('deviceScanned', (event) => {
console.log('Found device:', event.device.name, event.device.deviceId);
});
// Start scanning with optional filters
await BluetoothLowEnergy.startScan({
services: ['180d'], // Filter by Heart Rate service
timeout: 10000, // Stop after 10 seconds
allowDuplicates: false,
});
}
async function stopScanning() {
await BluetoothLowEnergy.stopScan();
console.log('Scanning stopped');
}
Connect to and disconnect from a BLE device.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function connectToDevice(deviceId: string) {
// Listen for connection events
BluetoothLowEnergy.addListener('deviceConnected', (event) => {
console.log('Connected to:', event.deviceId);
});
BluetoothLowEnergy.addListener('deviceDisconnected', (event) => {
console.log('Disconnected from:', event.deviceId);
});
await BluetoothLowEnergy.connect({ deviceId });
}
async function disconnectFromDevice(deviceId: string) {
await BluetoothLowEnergy.disconnect({ deviceId });
console.log('Disconnected');
}
Discover and retrieve services from a connected device.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function discoverDeviceServices(deviceId: string) {
// Discover services
await BluetoothLowEnergy.discoverServices({ deviceId });
// Get the discovered services
const { services } = await BluetoothLowEnergy.getServices({ deviceId });
services.forEach((service) => {
console.log('Service:', service.uuid);
service.characteristics.forEach((char) => {
console.log(' Characteristic:', char.uuid);
console.log(' Properties:', char.properties);
});
});
}
Read a value from a characteristic.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function readCharacteristicValue(
deviceId: string,
service: string,
characteristic: string
) {
const { value } = await BluetoothLowEnergy.readCharacteristic({
deviceId,
service,
characteristic,
});
console.log('Read value:', value); // Array of bytes
}
Write a value to a characteristic.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function writeCharacteristicValue(
deviceId: string,
service: string,
characteristic: string,
data: number[]
) {
await BluetoothLowEnergy.writeCharacteristic({
deviceId,
service,
characteristic,
value: data,
type: 'withResponse', // or 'withoutResponse'
});
console.log('Value written');
}
Subscribe to and unsubscribe from characteristic notifications.
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
async function subscribeToNotifications(
deviceId: string,
service: string,
characteristic: string
) {
// Listen for value changes
BluetoothLowEnergy.addListener('characteristicChanged', (event) => {
console.log('Value changed:', event.value);
});
await BluetoothLowEnergy.startCharacteristicNotifications({
deviceId,
service,
characteristic,
});
console.log('Subscribed to notifications');
}
async function unsubscribeFromNotifications(
deviceId: string,
service: string,
characteristic: string
) {
await BluetoothLowEnergy.stopCharacteristicNotifications({
deviceId,
service,
characteristic,
});
console.log('Unsubscribed from notifications');
}
Here's a complete example showing how to scan, connect, and read data from a Heart Rate Monitor:
import { BluetoothLowEnergy } from '@capgo/capacitor-bluetooth-low-energy';
const HEART_RATE_SERVICE = '180d';
const HEART_RATE_MEASUREMENT = '2a37';
class HeartRateMonitor {
private deviceId: string | null = null;
async initialize() {
await BluetoothLowEnergy.initialize();
const { available } = await BluetoothLowEnergy.isAvailable();
if (!available) {
throw new Error('Bluetooth not available');
}
await BluetoothLowEnergy.requestPermissions();
}
async scanAndConnect(): Promise<void> {
return new Promise((resolve) => {
BluetoothLowEnergy.addListener('deviceScanned', async (event) => {
if (event.device.name?.includes('Heart')) {
await BluetoothLowEnergy.stopScan();
this.deviceId = event.device.deviceId;
await BluetoothLowEnergy.connect({ deviceId: this.deviceId });
await BluetoothLowEnergy.discoverServices({ deviceId: this.deviceId });
resolve();
}
});
BluetoothLowEnergy.startScan({
services: [HEART_RATE_SERVICE],
timeout: 15000,
});
});
}
async startMonitoring(onHeartRate: (bpm: number) => void) {
if (!this.deviceId) throw new Error('Not connected');
BluetoothLowEnergy.addListener('characteristicChanged', (event) => {
if (event.characteristic === HEART_RATE_MEASUREMENT) {
const flags = event.value[0];
const is16Bit = (flags & 0x01) !== 0;
const heartRate = is16Bit
? (event.value[2] << 8) | event.value[1]
: event.value[1];
onHeartRate(heartRate);
}
});
await BluetoothLowEnergy.startCharacteristicNotifications({
deviceId: this.deviceId,
service: HEART_RATE_SERVICE,
characteristic: HEART_RATE_MEASUREMENT,
});
}
async disconnect() {
if (this.deviceId) {
await BluetoothLowEnergy.stopCharacteristicNotifications({
deviceId: this.deviceId,
service: HEART_RATE_SERVICE,
characteristic: HEART_RATE_MEASUREMENT,
});
await BluetoothLowEnergy.disconnect({ deviceId: this.deviceId });
this.deviceId = null;
}
}
}
// Usage
const monitor = new HeartRateMonitor();
await monitor.initialize();
await monitor.scanAndConnect();
await monitor.startMonitoring((bpm) => {
console.log('Heart Rate:', bpm, 'BPM');
});
That's it! You have successfully learned how to use the @capgo/capacitor-bluetooth-low-energy package to communicate with Bluetooth Low Energy devices in your Capacitor app.