Bluetooth Low Energy (BLE)
Hardware-accelerated Bluetooth Low Energy (BLE) functionality for Zynth applications, supporting both Central and Peripheral modes.
The @zynthjs/bluetooth package provides a unified API over CoreBluetooth (iOS) and BluetoothGatt (Android). It handles the complexities of scanning, connection stability, and GATT service/characteristic interactions.
Central Mode usage
Scanning for Devices
The startScanAsync method initiates a native BLE scan. You must listen for the device_found event to receive results.
import { BluetoothBLE } from "@zynthjs/bluetooth";
const discover = async () => {
// 1. Listen for results
const sub = BluetoothBLE.addListener((event) => {
if (event.type === "device_found") {
console.log("Device found:", event.device.name, event.device.id);
}
});
// 2. Start scanning (supports filtering by service UUIDs)
await BluetoothBLE.startScanAsync({
serviceUuids: ["180D"] // Pulse Ox
});
// 3. Stop after 10s
setTimeout(() => {
BluetoothBLE.stopScanAsync();
sub.remove();
}, 10000);
};
Connecting and GATT Operations
Once you have a deviceId, you can connect and interact with its services.
const interact = async (deviceId: string) => {
// 1. Establish connection
const conn = await BluetoothBLE.connectAsync({ deviceId });
const { connectionId } = conn;
// 2. Discover services
const services = await BluetoothBLE.discoverServicesAsync(connectionId);
// 3. Read a characteristic
const dataBase64 = await BluetoothBLE.readCharacteristicAsync({
connectionId,
serviceUuid: "180D",
characteristicUuid: "2A37"
});
// 4. Register for notifications
await BluetoothBLE.setNotificationAsync({
connectionId,
serviceUuid: "180D",
characteristicUuid: "2A37",
enabled: true
});
};
Peripheral Mode usage
Zynth allows your app to act as a BLE Peripheral (GATT Server), advertising services to other devices.
const startServer = async () => {
const state = await BluetoothBLE.startPeripheralAsync({
localName: "ZynthSensor",
serviceUuid: "FFF0",
characteristicUuid: "FFF1",
initialValueBase64: "SGVsbG8=" // "Hello"
});
console.log("Peripheral running:", state.running);
};
// Update the value later to notify connected centrals
const notify = async (data: string) => {
await BluetoothBLE.updatePeripheralCharacteristicAsync(btoa(data));
};
Special cases
- Reconnection Policy: Zynth includes a built-in exponential backoff reconnection system. If a connection is lost, you can use
reconnectAsyncwith a custompolicy(max attempts, delays, etc.) to restore the session. - MTU Negotiation: Android devices often start with a small MTU (23 bytes). Use
requestMtuAsyncto negotiate a larger packet size (up to 517 bytes) for higher throughput. - Permissions: Bluetooth permissions are handled natively. Use
requestPermissionsAsync()to trigger the system dialogs. On Android 12+, this includesBLUETOOTH_SCAN,BLUETOOTH_CONNECT, andACCESS_FINE_LOCATION.
API Reference
BluetoothBLE Methods
startScanAsync(options?: BleScanOptions): Promise<boolean>connectAsync(options: BleConnectOptions): Promise<BleConnectionInfo>discoverServicesAsync(connectionId: string): Promise<string[]>readCharacteristicAsync(target: BleCharacteristicTarget): Promise<string>writeCharacteristicAsync(options: BleWriteCharacteristicOptions): Promise<boolean>setNotificationAsync(options: BleNotificationOptions): Promise<boolean>startPeripheralAsync(config: BlePeripheralConfig): Promise<BlePeripheralState>updatePeripheralCharacteristicAsync(dataBase64: string): Promise<boolean>