Signatur
Beschreibung
readValue() fordert den aktuellen Wert eines Deskriptors direkt vom entfernten Bluetooth-Low-Energy-Gerät an. Deskriptoren sind Metadaten zu einer Characteristic. Beispiele sind die Characteristic User Description (0x2901, ein lesbarer Name), die Client Characteristic Configuration (0x2902, der Status von Benachrichtigungen) oder das Presentation Format (0x2904).
Ist der Lesevorgang erfolgreich, wird das Promise mit einem DataView erfüllt. Gleichzeitig aktualisiert der Browser die Eigenschaft descriptor.value mit einer Kopie der gelesenen Daten. Wie die Bytes zu deuten sind, hängt vom Deskriptor ab: Texte liest man z. B. mit TextDecoder, Zahlen mit getUint16(0, true) (Little Endian, wie in der Bluetooth-Spezifikation üblich).
Die Methode funktioniert nur, wenn eine GATT-Verbindung besteht (device.gatt.connected === true) und der Deskriptor Lesezugriff erlaubt. Den Deskriptor bekommt man vorher über characteristic.getDescriptor() oder characteristic.getDescriptors().
Rückgabewert
DataView erfüllt wird. Der DataView enthält die Rohdaten des Deskriptors. Bei einem Fehler wird das Promise mit einer DOMException abgelehnt, z. B. NetworkError (keine Verbindung), NotSupportedError (Lesen nicht erlaubt), InvalidStateError (Deskriptor ungültig) oder SecurityError (Deskriptor steht auf der Sperrliste).Beispiele
Benutzerbeschreibung (0x2901) einer Characteristic lesen
// Muss durch eine Nutzeraktion ausgelöst werden, z. B. einen Klick
const button = document.querySelector('#connect');
button.addEventListener('click', async () => {
try {
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['battery_service'] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService('battery_service');
const characteristic = await service.getCharacteristic('battery_level');
const descriptor = await characteristic.getDescriptor(
'gatt.characteristic_user_description'
);
const dataView = await descriptor.readValue();
const text = new TextDecoder('utf-8').decode(dataView);
console.log(`Beschreibung: ${text}`);
} catch (error) {
console.error(`Fehler: ${error.name} – ${error.message}`);
}
});
Prüfen, ob Benachrichtigungen aktiv sind (CCCD 0x2902)
const isNotifying = async (characteristic) => {
const cccd = await characteristic.getDescriptor(
'gatt.client_characteristic_configuration'
);
const value = await cccd.readValue();
// Bit 0 = Notifications, Bit 1 = Indications (Little Endian)
const flags = value.getUint16(0, true);
return {
notifications: Boolean(flags & 0x01),
indications: Boolean(flags & 0x02)
};
};
// Aufruf, nachdem characteristic.startNotifications() gelaufen ist
const status = await isNotifying(characteristic);
console.log(status);
Alle Deskriptoren einer Characteristic auslesen
const dumpDescriptors = async (characteristic) => {
const descriptors = await characteristic.getDescriptors();
for (const descriptor of descriptors) {
try {
const view = await descriptor.readValue();
const bytes = [...new Uint8Array(view.buffer)]
.map((b) => b.toString(16).padStart(2, '0'))
.join(' ');
console.log(`${descriptor.uuid}: ${bytes}`);
} catch (error) {
// z. B. NotSupportedError, wenn Lesen nicht erlaubt ist
console.warn(`${descriptor.uuid}: ${error.name}`);
}
}
};
await dumpDescriptors(characteristic);
// Wichtig · Fallstricke
- Browserunterstützung: Die Web Bluetooth API ist experimentell. Unterstützt wird sie nur in Chromium-Browsern (Chrome, Edge, Opera) unter Windows, macOS, ChromeOS und Android. Linux braucht teils ein Flag. Firefox und Safari (auch iOS) unterstützen die API nicht. Deshalb vorher prüfen:
'bluetooth' in navigator. - Sicherer Kontext: Die API gibt es nur über HTTPS oder
localhost.requestDevice()braucht zusätzlich eine Nutzeraktion. In iframes ist die Permissions-Policybluetoothnötig. - Sperrliste: Manche Deskriptoren sind für Lesezugriffe gesperrt. Bei ihnen wirft
readValue()einenSecurityError. Ein Beispiel ist die Client Characteristic Configuration (0x2902) in manchen Implementierungen. - Verbindung: Bricht die GATT-Verbindung ab, schlagen laufende und neue Aufrufe mit
NetworkErrorfehl. Deshalb auf das Eventgattserverdisconnectedreagieren. - Parallele Zugriffe: Viele Geräte und Plattformen können nur eine GATT-Operation gleichzeitig ausführen. Parallele Aufrufe (z. B. mit
Promise.all) können mitNetworkError(„GATT operation already in progress“) fehlschlagen. Aufrufe deshalb nacheinander mitawaitausführen. - Der zurückgegebene
DataViewist eine Kopie. Ändert man ihn, ändert sich nichts auf dem Gerät. Zum Schreiben dientwriteValue().