Signatur
Beschreibung
connect() baut eine Verbindung zum GATT-Server (Generic Attribute Profile) eines Bluetooth-Low-Energy-Geräts auf. Das Gerät muss vorher über navigator.bluetooth.requestDevice() ausgewählt worden sein. Man erreicht den Server über device.gatt. Erst wenn die Verbindung steht, kann man primäre Dienste (getPrimaryService()), Characteristics und Descriptors lesen, schreiben oder abonnieren.
Die Methode gibt ein Promise zurück. Es wird mit demselben BluetoothRemoteGATTServer-Objekt erfüllt, sobald die Verbindung aufgebaut ist. Danach ist server.connected gleich true. Besteht schon eine Verbindung, wird das Promise sofort erfüllt. Rufen mehrere Stellen im Skript connect() auf, zählt der Browser die Verbindung nur einmal. Ein einziges disconnect() trennt sie für alle.
Typische Einsatzfälle sind Fitness-Sensoren (Herzfrequenz), Smart-Home-Geräte, Mikrocontroller wie ESP32 oder micro:bit und medizinische Messgeräte. BLE-Verbindungen sind oft instabil. Man sollte daher auf das Event gattserverdisconnected am BluetoothDevice hören und bei Bedarf mit Backoff neu verbinden.
Rückgabewert
BluetoothRemoteGATTServer erfüllt wird. Es wird mit einer DOMException abgelehnt, zum Beispiel NetworkError, wenn das Gerät nicht erreichbar ist oder die Verbindung abbricht, oder SecurityError. Ein AbortError tritt auf, wenn während des Aufbaus disconnect() aufgerufen wird.Beispiele
Herzfrequenz-Sensor verbinden und Wert abonnieren
// Muss durch eine Nutzeraktion ausgelöst werden (z. B. Klick)
document.querySelector('#verbinden').addEventListener('click', async () => {
try {
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }]
});
const server = await device.gatt.connect();
console.log('Verbunden:', server.connected);
const service = await server.getPrimaryService('heart_rate');
const characteristic = await service.getCharacteristic('heart_rate_measurement');
characteristic.addEventListener('characteristicvaluechanged', (event) => {
const value = event.target.value;
const flags = value.getUint8(0);
// Bit 0 gibt an, ob der Wert 8 oder 16 Bit breit ist
const bpm = flags & 0x01 ? value.getUint16(1, true) : value.getUint8(1);
console.log(`Puls: ${bpm} bpm`);
});
await characteristic.startNotifications();
} catch (error) {
console.error(`Fehler: ${error.name} – ${error.message}`);
}
});
Batteriestand einmalig lesen und Verbindung trennen
const leseBatterie = async () => {
const device = await navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['battery_service']
});
const server = await device.gatt.connect();
try {
const service = await server.getPrimaryService('battery_service');
const level = await service.getCharacteristic('battery_level');
const value = await level.readValue();
console.log(`Batterie: ${value.getUint8(0)} %`);
} finally {
// Verbindung immer sauber freigeben
server.disconnect();
}
};
document.querySelector('#batterie').addEventListener('click', leseBatterie);
Automatisch neu verbinden mit exponentiellem Backoff
const verbindeMitRetry = async (device, maxVersuche = 5) => {
for (let versuch = 0; versuch < maxVersuche; versuch++) {
try {
const server = await device.gatt.connect();
console.log(`Verbunden nach ${versuch + 1} Versuch(en)`);
return server;
} catch (error) {
const wartezeit = 2 ** versuch * 500;
console.warn(`${error.name}: neuer Versuch in ${wartezeit} ms`);
await new Promise((resolve) => setTimeout(resolve, wartezeit));
}
}
throw new Error('Verbindung fehlgeschlagen');
};
document.querySelector('#start').addEventListener('click', async () => {
const device = await navigator.bluetooth.requestDevice({
filters: [{ namePrefix: 'ESP32' }]
});
device.addEventListener('gattserverdisconnected', () => {
console.log('Verbindung verloren – verbinde neu …');
verbindeMitRetry(device).catch(console.error);
});
await verbindeMitRetry(device);
});
// Wichtig · Fallstricke
- Browser-Unterstützung: Web Bluetooth ist experimentell und nur in Chromium-Browsern verfügbar (Chrome, Edge, Opera, auch Chrome für Android). Firefox und Safari unterstützen es nicht, auch nicht Safari auf iOS. Unter Linux muss es teils per Flag aktiviert werden. Vorher mit
'bluetooth' in navigatorprüfen, ob die API vorhanden ist. - Sicherer Kontext: Die API funktioniert nur über HTTPS oder
localhost.requestDevice()braucht eine Nutzeraktion, etwa einen Klick.connect()selbst braucht keine. In Iframes muss die Permissions Policybluetootherlaubt sein. - Zugriff auf Dienste: Nur Dienste, die in
filtersoderoptionalServicesvonrequestDevice()stehen, sind nach dem Verbinden erreichbar. Alle anderen führen zu einemSecurityError. - Instabile Verbindungen:
connect()kann mitNetworkErrorfehlschlagen, auch wenn das Gerät in Reichweite ist. Manche Geräte erlauben nur eine Verbindung gleichzeitig, sodass etwa eine offene Smartphone-App den Zugang blockiert. Deshalb Wiederholungsversuche einbauen undgattserverdisconnectedbehandeln. - Kein eingebauter Timeout: Das Promise kann lange offen bleiben. Bei Bedarf eine eigene Zeitgrenze mit
Promise.race()setzen und anschließenddisconnect()aufrufen. Dadurch wird das ausstehende Promise mitAbortErrorabgelehnt. - Verbindungen nicht offen lassen. Mit
disconnect()freigeben, wenn sie nicht mehr gebraucht werden. Das schont den Akku des Geräts.