After reviewing the following StackOverflow resources:
- Web Bluetooth & Chrome Extension: User cancelled the requestDevice() chooser
- Electron Web Bluetooth API requestDevice() Error
- Can you manipulate web bluetooth chooser that shows after calling requestDevice()?
However, the solutions provided in these sources do not seem to be effective.
Here is my main
file:
import { app, BrowserWindow } from "electron";
/**
* Reference: https://www.electronjs.org/docs/tutorial/quick-start#create-the-main-script-file
*/
async function createWindow(): Promise<BrowserWindow> {
// Creating a browser window
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
},
});
/**
* Handle bluetooth connection
* Reference: https://www.electronjs.org/docs/latest/tutorial/devices#web-bluetooth-api
*/
win.webContents.on("select-bluetooth-device", (event, devices, callback) => {
event.preventDefault();
if (devices.length > 0) {
callback(devices[0].deviceId);
}
});
// Load index.html
win.maximize();
await win.loadFile("./dist/renderer/index.html");
return win;
}
function setUpElectronApp(): void {
// Browser window
let win: BrowserWindow | undefined;
// Enable webBluetooth
app.commandLine.appendSwitch("enable-experimental-web-platform-features", "true");
app.commandLine.appendSwitch("enable-web-bluetooth", "true");
// Create bowser window once the electron app is initialized
app
.whenReady()
.then(() => {
createWindow()
.then((response) => {
win = response;
console.log(win);
})
.catch((err) => {
throw err as Error;
});
})
.catch((err) => {
throw err as Error;
});
// Quit the application when it no longer has any open windows
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
win = undefined;
}
});
// Create a new browser window only when the application has no visible windows being activated
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
.then((response) => {
win = response;
console.log(win);
})
.catch((err) => {
throw err;
});
}
});
}
setUpElectronApp();
And here is some code from the renderer
file:
function onDisconnected(event: Event) {
const device = event.target as BluetoothDevice;
console.log(`Device ${device.name} is disconnected.`);
}
export async function deviceConnect(): Promise<{ heartRate: any, batteryLevel: any, deviceID: string }> {
const device = await navigator.bluetooth.requestDevice({
filters: [
{
namePrefix: "Polar Sense",
manufacturerData: [{ companyIdentifier: 0x006b }],
},
],
acceptAllDevices: false,
optionalServices: [0x180d, 0x180f],
});
device.addEventListener("gattserverdisconnected", onDisconnected);
const server = await device.gatt?.connect();
const heartRateService = await server?.getPrimaryService(0x180d);
const heartRate = await heartRateService?.getCharacteristic(0x2a37);
const batteryLevelService = await server?.getPrimaryService(0x180f);
const batteryLevel = await batteryLevelService?.getCharacteristic(0x2a19);
return { heartRate, batteryLevel, deviceID: device.name };
}
I have a button on my front end that triggers the above function when clicked. Unfortunately, I keep receiving the error message:
Uncaught (in promise) DOMException: User cancelled the requestDevice() chooser.
I have tried different versions of Electron with no success. Any insights would be greatly appreciated.
Please advise if utilizing the Web Bluetooth API in Electron is feasible. I am using "electron": "^17.4.7"
on macOS Monterey (12.4).
If you notice any issues or have suggestions regarding the approach outlined above, please share your feedback.