Signatur
Beschreibung
Die schreibgeschützte Eigenschaft value einer BluetoothRemoteGATTCharacteristic enthält den zwischengespeicherten Wert der Characteristic, also der Datenfelder, die ein Bluetooth-Low-Energy-Gerät (BLE) über GATT bereitstellt. Das kann zum Beispiel der Akkustand, die Herzfrequenz oder ein Sensormesswert sein. Der Wert liegt als DataView vor, damit du die Rohbytes gezielt als Uint8, Int16, Float32 usw. auslesen kannst.
Die Eigenschaft wird nur in drei Fällen aktualisiert: nach einem erfolgreichen readValue(), beim Eintreffen des Ereignisses characteristicvaluechanged (Benachrichtigungen oder Indications nach startNotifications()) und nach einem Schreibvorgang. Wenn du value abfragst, wird keine neue Kommunikation mit dem Gerät ausgelöst. Solange noch nichts gelesen oder empfangen wurde, ist der Wert null.
Typisch nutzt du value in einem Handler für characteristicvaluechanged, wo event.target.value den gerade empfangenen Wert enthält. Du kannst die Eigenschaft auch nach await characteristic.readValue() lesen, allerdings gibt readValue() denselben DataView ohnehin direkt zurück.
Rückgabewert
DataView mit den Rohbytes des zuletzt bekannten Werts. Solange noch kein Wert gelesen oder empfangen wurde, ist er null.Beispiele
Akkustand lesen und aus dem Cache abfragen
// Muss durch eine Benutzeraktion ausgelöst werden (z. B. Klick)
const button = document.querySelector('#connect');
button.addEventListener('click', async () => {
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');
console.log('Vor dem Lesen:', characteristic.value);
await characteristic.readValue();
// value enthält jetzt den zwischengespeicherten DataView
const level = characteristic.value.getUint8(0);
console.log(`Akkustand: ${level} %`);
});
Herzfrequenz per Benachrichtigung auswerten
const handleHeartRate = (event) => {
const value = event.target.value; // DataView
const flags = value.getUint8(0);
// Bit 0: Herzfrequenz als uint16 statt uint8
const bpm = (flags & 0x01)
? value.getUint16(1, true) // Little Endian laut GATT-Spezifikation
: value.getUint8(1);
console.log(`Puls: ${bpm} bpm`);
};
const startHeartRate = async () => {
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');
characteristic.addEventListener('characteristicvaluechanged', handleHeartRate);
await characteristic.startNotifications();
return characteristic;
};
document.querySelector('#start').addEventListener('click', startHeartRate);
Textwert (UTF-8) aus value dekodieren
const readDeviceName = async (characteristic) => {
await characteristic.readValue();
const { value } = characteristic;
if (!value) return null;
// DataView -> Text; Offset und Länge beachten
const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
return new TextDecoder('utf-8').decode(bytes);
};
// Aufruf z. B. mit der Characteristic 'gap.device_name'
// const name = await readDeviceName(nameCharacteristic);
// console.log(name);
// Wichtig · Fallstricke
- Browserunterstützung: Web Bluetooth ist experimentell und steht nur in Chromium-Browsern bereit (Chrome, Edge, Opera, teils Android). Firefox und Safari unterstützen die API nicht. Unter Linux kann ein Flag nötig sein. Prüfe die Verfügbarkeit mit
'bluetooth' in navigator. - Sicherer Kontext: Die API funktioniert nur über HTTPS oder
localhost.requestDevice()muss durch eine Benutzeraktion ausgelöst werden, und in iframes ist eine Permissions-Policy (bluetooth) erforderlich. - Kein Live-Wert:
valueist nur der Cache. Das Abfragen liest nichts vom Gerät. Den aktuellen Wert bekommst du mitreadValue()oder über Benachrichtigungen. - Anfangs
null: Prüfe vor dem Zugriff aufnull, sonst wirft zum BeispielgetUint8()einenTypeError. - Byte-Reihenfolge: GATT-Werte sind meist Little Endian. Übergib deshalb bei
getUint16(),getInt32()usw. als zweites Argumenttrue. - Offset: Bei der Umwandlung in ein
Uint8ArrayimmerbyteOffsetundbyteLengthberücksichtigen, statt nurvalue.bufferzu verwenden. - Der
DataViewkann bei der nächsten Benachrichtigung durch ein neues Objekt ersetzt werden. Werte, die du aufheben willst, solltest du deshalb sofort auslesen oder kopieren.