-
Notifications
You must be signed in to change notification settings - Fork 116
Open
Labels
questionFurther information is requestedFurther information is requested
Description
Below is the code I have had to resort to to make this plugin work.
Does anyone have any idea what could be so horribly wrong with my setup? All of my issues are around connecting initially. Once connected, everything's fine.
const timeout = 5_000;
// Test to see if we can write to the device
const canBleClientWrite = (deviceId: string) =>
new Promise<boolean>((resolve, reject) => {
BleClient.write(
deviceId,
BLE_SERVICE,
BLE_WRITE_CHARACTERISTIC,
textToDataView('read_config firmware_id')
)
.then(() => resolve(true))
.catch((e) => resolve(false));
});
// Sometimes the connected devices list lies, make sure we can write successfully (otherwise we're not connected)
const isBleClientConnected = async (deviceId: string) => {
const connectedDevices = await BleClient.getConnectedDevices([BLE_SERVICE]);
const saysItIsConnected = connectedDevices.some((d) => d.deviceId === deviceId);
return saysItIsConnected && (await canBleClientWrite(deviceId));
};
// Android bonding is flaky for unknown reasons, so retry a few times
const bond = async (deviceId: string) => {
let isBonded = await BleClient.isBonded(deviceId);
console.log('[bond] isBonded (pre)', isBonded);
const maxAttempts = 5;
for (let attempt = 1; !isBonded && attempt <= maxAttempts; attempt += 1) {
console.log(`[bond] bonding ${attempt}...`);
await BleClient.createBond(deviceId, { timeout }).catch(() => {
console.log(`[bond] createBond ${attempt} failed`);
});
isBonded = await BleClient.isBonded(deviceId);
console.log(`[bond] isBonded ${attempt}`, isBonded);
}
if (!isBonded) throw new Error('Could not bond');
console.log('[bond] bonded!');
return isBonded;
};
// Connecting to devices is flaky for unknown reasons
const connect = async (deviceId: string) => {
if (isAndroid) await bond(deviceId);
let isConnected = await isBleClientConnected(deviceId);
const maxAttempts = 5;
for (let attempt = 1; !isConnected && attempt <= maxAttempts; attempt += 1) {
console.log(`[connect] connecting ${attempt}...`);
// Sometimes onDisconnect is called immediately, sometimes it times out, and sometimes it works
// Race the onDisconnect versus the timeout versus an actual successful connection
let intervalId: NodeJS.Timeout | null = null;
await Promise.race([
new Promise<void>(async (resolve, reject) => {
await BleClient.connect(deviceId, () => reject('onDisconnect called'), { timeout });
intervalId = setInterval(async () => {
if (await isBleClientConnected(deviceId)) {
resolve();
}
}, 1000);
}),
new Promise<void>((resolve, reject) => {
setTimeout(() => {
reject('Timeout');
}, timeout);
}),
])
.catch((reason) => console.log(`[connect] connect ${attempt} failed`, reason))
.finally(() => (intervalId ? clearInterval(intervalId) : null));
isConnected = await isBleClientConnected(deviceId);
}
if (!isConnected) throw new Error('Could not connect');
console.log('[connect] connected!');
return isConnected;
};Plugin version:
- @capacitor-community/bluetooth-le: ^7.1.1
Smartphone (please complete the following information):
- Device: Samsung Galaxy S9 FE+
- OS: Android
- Browser: Chrome
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
questionFurther information is requestedFurther information is requested