Skip to content

Commit

Permalink
bugfix/FAT-588 Introduce a cancellable auto disconnect for BLE
Browse files Browse the repository at this point in the history
  • Loading branch information
juan-cortes committed Nov 21, 2022
1 parent 935e84e commit d0b9100
Showing 1 changed file with 27 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ async function open(deviceOrId: Device | string, needsReconnect: boolean) {
if (typeof deviceOrId === "string") {
if (transportsCache[deviceOrId]) {
log("ble-verbose", "Transport in cache, using that.");
const maybeTimeout = transportsCache[deviceOrId].disconnectTimeout;
if (maybeTimeout) {
log("ble-verbose", "Clearing queued disconnect");
clearTimeout(transportsCache[deviceOrId].disconnectTimeout);
}
return transportsCache[deviceOrId];
}

Expand Down Expand Up @@ -418,6 +423,7 @@ export default class BluetoothTransport extends Transport {
notifyObservable: Observable<any>;
deviceModel: DeviceModel;
notYetDisconnected = true;
disconnectTimeout: null | ReturnType<typeof setTimeout> = null;

constructor(
device: Device,
Expand Down Expand Up @@ -539,34 +545,30 @@ export default class BluetoothTransport extends Transport {
};

async close(): Promise<void> {
// Prevent double runs
let alreadyDisconnected = false;

// Actually disconnect from the device onClose
const triggerDisconnect = () => {
if (!alreadyDisconnected) {
BluetoothTransport.disconnect(this.id); // This triggers cache cleanup above.
alreadyDisconnected = true;
}
};
// Clear any potential leftover timeouts
if (this.disconnectTimeout) {
clearTimeout(this.disconnectTimeout);
}

// For cases where an exchange doesn't resolve and we triggered a `close` we
// introduce a timeout to forcefully disconnect in order to unblock subsequent
// usages of the `withDevice` logic. It's also a good practice to disconnect
// from the device when not actively interacting with it.
if (this.exchangeBusyPromise) {
const forceDisconnect = new Promise<void>((resolve) =>
setTimeout(() => {
triggerDisconnect();
resolve();
}, connectOptions.forceDisconnectTimeout as number)
);
let resolve;
const disconnectPromise = new Promise<void>((res) => {
resolve = res;
});

await Promise.race([this.exchangeBusyPromise, forceDisconnect]);
// At this point we've either disconnected forcefully, or completed the exchange
}
// Queue a disconnect
this.disconnectTimeout = setTimeout(() => {
BluetoothTransport.disconnect(this.id);
resolve();
}, connectOptions.forceDisconnectTimeout as number);

// For cases where an exchange hasn't resolve and we triggered a `close` we
// introduce a timeout to forcefully disconnect in order to unblock subsequent
// usages of the `withDevice` logic.
await Promise.race([
this.exchangeBusyPromise || Promise.resolve(),
disconnectPromise,
]);

triggerDisconnect();
return;
}
}

0 comments on commit d0b9100

Please sign in to comment.