Signatur
Beschreibung
navigator.bluetooth.requestDevice() ist der Einstieg in die Web Bluetooth API. Die Methode zeigt dem Nutzer einen vom Browser gesteuerten Auswahldialog mit allen Bluetooth-Low-Energy-Geräten in Reichweite, die zu den übergebenen Filtern passen. Wählt der Nutzer ein Gerät aus, wird das Promise mit einem BluetoothDevice-Objekt erfüllt. Über dessen gatt-Eigenschaft baut man dann die Verbindung zum GATT-Server auf und liest oder schreibt Characteristics.
Die Methode braucht eine Nutzeraktivierung (transiente Aktivierung): Sie darf nur als direkte Folge einer Nutzeraktion aufgerufen werden, etwa in einem click-Handler. Außerdem funktioniert sie nur in einem sicheren Kontext (HTTPS oder localhost).
In options gibt man entweder über filters an, welche Geräte angezeigt werden sollen (nach Service-UUID, Name, Namenspräfix, Hersteller- oder Servicedaten), oder man setzt acceptAllDevices: true. Wichtig: Auf primäre Services darf man später nur zugreifen, wenn sie in filters[].services oder in optionalServices angegeben wurden. Sonst wirft getPrimaryService() einen SecurityError.
Typische Anwendungsfälle sind Fitness-Sensoren (Herzfrequenz, Trittfrequenz), IoT-Geräte, smarte Lampen, Mikrocontroller wie ESP32 oder micro:bit und Messgeräte, die man direkt aus einer Web-App heraus ansprechen will.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options Pflicht | object | Konfigurationsobjekt. Man muss entweder filters oder acceptAllDevices: true angeben, beides zusammen ist nicht erlaubt. |
|
| $options.filters | Array<BluetoothLEScanFilter> | Liste von Filtern, die mit ODER verknüpft werden. Die Kriterien innerhalb eines Filters gelten mit UND. Mögliche Schlüssel: services (Array von UUIDs oder Namen wie 'heart_rate'), name, namePrefix, manufacturerData, serviceData. |
|
| $options.exclusionFilters | Array<BluetoothLEScanFilter> | Filter für Geräte, die trotz passender filters nicht angezeigt werden sollen. Erst in neueren Chrome-Versionen verfügbar (ab 114). |
|
| $options.optionalServices | Array<string|number> | [] | Zusätzliche Service-UUIDs, auf die man nach dem Verbinden zugreifen will, die aber nicht zum Filtern dienen. |
| $options.optionalManufacturerData | Array<number> | [] | Hersteller-IDs (Company Identifier), deren Herstellerdaten aus Advertisement-Paketen lesbar sein sollen. |
| $options.acceptAllDevices | boolean | false | Bei true werden alle Geräte in Reichweite angezeigt. Services muss man dann über optionalServices freigeben. Frisst Akku und macht den Dialog unübersichtlich, deshalb nur zum Debuggen empfohlen. |
Rückgabewert
BluetoothDevice erfüllt. Wird mit NotFoundError abgelehnt, wenn der Nutzer den Dialog abbricht oder kein Gerät passt. Mit SecurityError, wenn kein sicherer Kontext oder keine Nutzeraktivierung vorliegt oder eine UUID gesperrt ist. Mit TypeError bei ungültigen Optionen und mit NotAllowedError/NotSupportedError, wenn Bluetooth nicht verfügbar oder per Richtlinie gesperrt ist.Beispiele
Herzfrequenz-Sensor per Klick auswählen und verbinden
const button = document.querySelector('#connect');
button.addEventListener('click', async () => {
try {
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }]
});
console.log('Gewählt:', device.name);
const server = await device.gatt.connect();
const service = await server.getPrimaryService('heart_rate');
const characteristic = await service.getCharacteristic('heart_rate_measurement');
characteristic.addEventListener('characteristicvaluechanged', (event) => {
const value = event.target.value;
// Bit 0 der Flags: 0 = uint8, 1 = uint16
const is16Bit = value.getUint8(0) & 0x1;
const bpm = is16Bit ? value.getUint16(1, true) : value.getUint8(1);
console.log(`Puls: ${bpm} bpm`);
});
await characteristic.startNotifications();
} catch (error) {
console.error(`${error.name}: ${error.message}`);
}
});
Nach Namenspräfix filtern und zusätzliche Services freigeben
const connectToDevice = async () => {
const device = await navigator.bluetooth.requestDevice({
filters: [
{ namePrefix: 'ESP32' },
{ name: 'MeinSensor' }
],
optionalServices: ['battery_service', '0000ffe0-0000-1000-8000-00805f9b34fb']
});
const server = await device.gatt.connect();
const battery = await server.getPrimaryService('battery_service');
const level = await battery.getCharacteristic('battery_level');
const value = await level.readValue();
console.log(`Akkustand: ${value.getUint8(0)} %`);
};
document.querySelector('#scan').addEventListener('click', connectToDevice);
Unterstützung prüfen und Abbruch durch den Nutzer abfangen
const pickAnyDevice = async () => {
if (!('bluetooth' in navigator)) {
console.warn('Web Bluetooth wird von diesem Browser nicht unterstützt.');
return null;
}
const available = await navigator.bluetooth.getAvailability();
if (!available) {
console.warn('Kein Bluetooth-Adapter verfügbar.');
return null;
}
try {
// Nur zum Debuggen: alle Geräte anzeigen
return await navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['device_information']
});
} catch (error) {
if (error.name === 'NotFoundError') {
console.info('Auswahl abgebrochen.');
return null;
}
throw error;
}
};
document.querySelector('#debug').addEventListener('click', async () => {
const device = await pickAnyDevice();
if (device) console.log(device.id, device.name ?? '(ohne Namen)');
});