Signatur
Beschreibung
startNotifications() weist ein verbundenes Bluetooth-Low-Energy-Gerät an, Wertänderungen einer Charakteristik von sich aus zu senden (Push). Dafür schreibt der Browser in den Client Characteristic Configuration Descriptor (CCCD, UUID 0x2902) das Bit für Notify oder Indicate. Indikationen werden vom Empfänger bestätigt, Benachrichtigungen nicht. Welches der beiden Verfahren zum Einsatz kommt, hängt davon ab, was die Charakteristik unterstützt.
Die Methode eignet sich für alle Messwerte, die sich laufend ändern, etwa Herzfrequenz, Akkustand, Sensordaten oder Tastendrücke. Ohne sie müsste man den Wert ständig mit readValue() abfragen. Jeder neu eintreffende Wert löst auf der Charakteristik das Event characteristicvaluechanged aus. Der aktuelle Wert steht danach als DataView in characteristic.value.
Voraussetzung ist eine aktive GATT-Verbindung (device.gatt.connect()). Außerdem muss die Charakteristik in properties.notify oder properties.indicate den Wert true haben. Am besten registrieren Sie den Event-Listener vor dem Aufruf, damit kein früher Wert verloren geht. Mit stopNotifications() beenden Sie das Abo wieder.
Rückgabewert
DOMException abgelehnt: NotSupportedError (weder Notify noch Indicate wird unterstützt), NetworkError (GATT-Server nicht verbunden), InvalidStateError (Charakteristik ungültig geworden) oder SecurityError (Zugriff auf eine gesperrte UUID).Beispiele
Herzfrequenz eines Brustgurts live empfangen
const button = document.querySelector('#connect');
button.addEventListener('click', async () => {
// requestDevice() nur nach einer Nutzeraktion aufrufen
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService('heart_rate');
const characteristic = await service.getCharacteristic('heart_rate_measurement');
// Listener VOR startNotifications() registrieren
characteristic.addEventListener('characteristicvaluechanged', (event) => {
const value = event.target.value; // DataView
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();
console.log('Benachrichtigungen aktiv');
});
Unterstützung vorab prüfen und Fehler abfangen
const subscribe = async (characteristic, onValue) => {
const { notify, indicate } = characteristic.properties;
if (!notify && !indicate) {
throw new Error('Charakteristik unterstützt keine Benachrichtigungen');
}
const handler = (event) => onValue(event.target.value);
characteristic.addEventListener('characteristicvaluechanged', handler);
try {
await characteristic.startNotifications();
} catch (err) {
characteristic.removeEventListener('characteristicvaluechanged', handler);
console.error(`${err.name}: ${err.message}`);
throw err;
}
// Funktion zum Abmelden zurückgeben
return async () => {
characteristic.removeEventListener('characteristicvaluechanged', handler);
if (characteristic.service.device.gatt.connected) {
await characteristic.stopNotifications();
}
};
};
// Nutzung:
// const unsubscribe = await subscribe(batteryLevel, (v) => console.log(v.getUint8(0) + ' %'));
// später: await unsubscribe();
Verkettung über den Rückgabewert und Wiederverbindung
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['battery_service'] }]
});
const connectAndSubscribe = async () => {
const server = await device.gatt.connect();
const service = await server.getPrimaryService('battery_service');
const characteristic = await service.getCharacteristic('battery_level');
// Das Promise wird mit der Charakteristik selbst erfüllt
const active = await characteristic.startNotifications();
active.oncharacteristicvaluechanged = (e) =>
console.log('Akku:', e.target.value.getUint8(0), '%');
};
// Nach einem Verbindungsabbruch ist das Abo verloren und muss neu angelegt werden
device.addEventListener('gattserverdisconnected', () => {
console.log('Getrennt – verbinde neu …');
connectAndSubscribe().catch(console.error);
});
await connectAndSubscribe();
// Wichtig · Fallstricke
- Browser-Unterstützung: Web Bluetooth gibt es nur in Chromium-Browsern (Chrome, Edge, Opera, teils Android). Firefox und Safari/iOS unterstützen die API nicht. Auf Linux kann ein Flag nötig sein. Prüfen Sie die Verfügbarkeit mit
'bluetooth' in navigator. - Sicherer Kontext: Die API funktioniert nur über HTTPS oder
localhost.requestDevice()braucht eine Nutzeraktion (z. B. einen Klick). In iframes muss die Permissions-Policybluetootherlaubt sein. - Reihenfolge: Registrieren Sie den Listener für
characteristicvaluechangedvor dem Aufruf. Manche Geräte senden sofort nach dem Abonnieren einen Wert. - Abo geht bei Trennung verloren: Bei
gattserverdisconnectedmüssen Sie neu verbinden undstartNotifications()erneut aufrufen. Alte Charakteristik-Objekte können danach ungültig sein. - Nicht parallel aufrufen: Laufen mehrere GATT-Operationen gleichzeitig, schlagen sie oft mit
NetworkError(„GATT operation already in progress“) fehl. Verketten Sie die Aufrufe deshalb nacheinander mitawait. - Datenformat:
valueist einDataView. Byte-Reihenfolge und Aufbau legt das jeweilige GATT-Profil fest; bei BLE ist das meist Little Endian. - Datenschutz: Einige UUIDs sind auf der Blockliste von Web Bluetooth gesperrt und lösen einen
SecurityErroraus. Dienste, die nicht infiltersstehen, müssen Sie inoptionalServicesangeben.