1. Worum geht es?

In diesem Codelab erfahren Sie, wie Sie eine PLAYBULB LED-Kerze ohne Flamme nur mit JavaScript über die Web Bluetooth API steuern können. Dabei werden auch JavaScript ES2015-Funktionen wie Klassen, Pfeilfunktionen, Map und Promises verwendet.
Lerninhalte
- Mit einem Bluetooth-Gerät in der Nähe in JavaScript interagieren
- ES2015-Klassen, Pfeilfunktionen, Map und Promises verwenden
Voraussetzungen
- Grundlegendes Verständnis der Webentwicklung
- Grundkenntnisse zu Bluetooth Low Energy (BLE) und Generic Attribute Profile (GATT)
- Ein Texteditor Ihrer Wahl
- Ein Mac, ein Chromebook oder ein Android M-Gerät mit der Chrome-Browser-App und einem USB-Micro-zu-USB-Kabel.
2. Zuerst abspielen
Die finale Version der App, die Sie erstellen werden, finden Sie unter https://googlecodelabs.github.io/candle-bluetooth. Bevor Sie mit diesem Codelab beginnen, sollten Sie sich das PLAYBULB Candle Bluetooth-Gerät ansehen, das Sie zur Verfügung haben.
Unter https://www.youtube.com/watch?v=fBCPA9gIxlU kannst du dir ansehen, wie ich die Farben ändere.
3. Einrichten
Beispielcode herunterladen
Sie können den Beispielcode für diesen Code abrufen, indem Sie die ZIP-Datei hier herunterladen:
oder durch Klonen dieses Git-Repositorys:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Wenn Sie die Quelle als ZIP-Datei heruntergeladen haben, sollte das Entpacken einen Stammordner candle-bluetooth-master ergeben.
Webserver installieren und überprüfen
Sie können zwar Ihren eigenen Webserver verwenden, dieses Codelab ist jedoch für die Verwendung mit dem Chrome-Webserver optimiert. Wenn Sie die App noch nicht installiert haben, können Sie sie im Chrome Web Store installieren.
Klicken Sie nach der Installation der Web Server for Chrome App in der Lesezeichenleiste auf die Verknüpfung „Apps“:

Klicken Sie im folgenden Fenster auf das Symbol für den Webserver:

Als Nächstes wird dieses Dialogfeld angezeigt, in dem Sie Ihren lokalen Webserver konfigurieren können:

Klicken Sie auf die Schaltfläche Ordner auswählen und wählen Sie das Stammverzeichnis des geklonten (oder entpackten) Repositorys aus. So können Sie Ihre laufende Arbeit über die URL bereitstellen, die im Webserver-Dialogfeld (im Abschnitt Webserver-URLs) hervorgehoben ist.
Klicken Sie unter „Optionen“ das Kästchen neben index.html automatisch anzeigen an, wie unten dargestellt:

Rufen Sie Ihre Website jetzt in Ihrem Webbrowser auf (indem Sie auf die hervorgehobene Webserver-URL klicken). Sie sollten eine Seite sehen, die so aussieht:

Wenn Sie sehen möchten, wie diese App auf Ihrem Android-Smartphone aussieht, müssen Sie Remote-Debugging auf Android aktivieren und die Portweiterleitung einrichten (die Portnummer ist standardmäßig 8887). Danach können Sie einfach einen neuen Chrome-Tab auf Ihrem Android-Smartphone öffnen und http://localhost:8887 eingeben.
Als Nächstes
Derzeit kann diese Web-App noch nicht viel. Fügen wir Bluetooth-Unterstützung hinzu.
4. Kerze entdecken
Zuerst schreiben wir eine Bibliothek, die eine JavaScript-ES2015-Klasse für das PLAYBULB Candle-Bluetooth-Gerät verwendet.
Bleiben Sie ruhig. Mit der Klassensyntax wird kein neues objektorientiertes Vererbungsmodell in JavaScript eingeführt. Sie bietet einfach eine viel übersichtlichere Syntax zum Erstellen von Objekten und zum Umgang mit der Vererbung, wie Sie unten lesen können.
Zuerst definieren wir eine PlaybulbCandle-Klasse in playbulbCandle.js und erstellen eine playbulbCandle-Instanz, die später in der Datei app.js verfügbar sein wird.
playbulbCandle.js
(function() {
'use strict';
class PlaybulbCandle {
constructor() {
this.device = null;
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Um Zugriff auf ein Bluetooth-Gerät in der Nähe anzufordern, müssen wir navigator.bluetooth.requestDevice aufrufen. Da das PLAYBULB Candle-Gerät kontinuierlich (sofern noch nicht gekoppelt) eine konstante Bluetooth GATT-Dienst-UUID bewirbt, die in ihrer Kurzform als 0xFF02 bekannt ist, können wir einfach eine Konstante definieren und sie dem Parameter „services“ der Filter in einer neuen öffentlichen connect-Methode der Klasse PlaybulbCandle hinzufügen.
Wir behalten das BluetoothDevice-Objekt auch intern im Blick, damit wir bei Bedarf später darauf zugreifen können. Da navigator.bluetooth.requestDevice ein JavaScript ES2015-Promise zurückgibt, führen wir dies in der Methode then aus.
playbulbCandle.js
(function() {
'use strict';
const CANDLE_SERVICE_UUID = 0xFF02;
class PlaybulbCandle {
constructor() {
this.device = null;
}
connect() {
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}]};
return navigator.bluetooth.requestDevice(options)
.then(function(device) {
this.device = device;
}.bind(this));
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Aus Sicherheitsgründen muss die Suche nach Bluetooth-Geräten in der Nähe mit navigator.bluetooth.requestDevice über eine Nutzeraktion wie eine Berührung oder einen Mausklick aufgerufen werden. Daher rufen wir die connect-Methode auf, wenn der Nutzer in der Datei app.js auf die Schaltfläche „Verbinden“ klickt:
app.js
document.querySelector('#connect').addEventListener('click', function(event) {
document.querySelector('#state').classList.add('connecting');
playbulbCandle.connect()
.then(function() {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
})
.catch(function(error) {
console.error('Argh!', error);
});
});
App ausführen
Rufen Sie Ihre Website jetzt in Ihrem Webbrowser auf. Klicken Sie dazu in der Webserver-App auf die Webserver-URL, die hervorgehoben ist, oder aktualisieren Sie einfach die vorhandene Seite. Klicken Sie auf die grüne Schaltfläche „Verbinden“, wählen Sie das Gerät in der Auswahl aus und öffnen Sie Ihre bevorzugte DevTools-Konsole mit der Tastenkombination Strg + Umschalt + J. Das BluetoothDevice-Objekt wird protokolliert.

Möglicherweise erhalten Sie eine Fehlermeldung, wenn Bluetooth deaktiviert ist und/oder das PLAYBULB Candle-Bluetooth-Gerät ausgeschaltet ist. Schalten Sie es in diesem Fall ein und fahren Sie fort.
Obligatorischer Bonus
Ich weiß nicht, wie es dir geht, aber ich sehe in diesem Code schon zu viele function() {}. Wir verwenden stattdessen () => {} JavaScript ES2015-Pfeilfunktionen. Sie sind absolut lebensrettend: Alle Vorteile anonymer Funktionen, ohne die Nachteile der Bindung.
playbulbCandle.js
(function() {
'use strict';
const CANDLE_SERVICE_UUID = 0xFF02;
class PlaybulbCandle {
constructor() {
this.device = null;
}
connect() {
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}]};
return navigator.bluetooth.requestDevice(options)
.then(device => {
this.device = device;
});
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
app.js
document.querySelector('#connect').addEventListener('click', event => {
playbulbCandle.connect()
.then(() => {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
})
.catch(error => {
console.error('Argh!', error);
});
});
Als Nächstes
– OK… kann ich jetzt mit dieser Kerze sprechen oder was?
– Ja, fahre mit dem nächsten Schritt fort.
FAQ
5. Etwas lesen
Was können Sie jetzt tun, nachdem Sie eine BluetoothDevice erhalten haben, die navigator.bluetooth.requestDevice versprochen hat? Wir stellen eine Verbindung zum GATT-Server der Bluetooth-Fernbedienung her, der die Bluetooth-Dienst- und ‑Charakteristikdefinitionen enthält, indem wir device.gatt.connect() aufrufen:
playbulbCandle.js
class PlaybulbCandle {
constructor() {
this.device = null;
}
connect() {
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}]};
return navigator.bluetooth.requestDevice(options)
.then(device => {
this.device = device;
return device.gatt.connect();
});
}
}
Gerätenamen vorlesen
Hier sind wir mit dem GATT-Server des PLAYBULB Candle-Bluetooth-Geräts verbunden. Als Nächstes möchten wir den primären GATT-Dienst (der zuvor als 0xFF02 beworben wurde) abrufen und das Merkmal für den Gerätenamen (0xFFFF) lesen, das zu diesem Dienst gehört. Das lässt sich ganz einfach erreichen, indem Sie der Klasse PlaybulbCandle eine neue Methode getDeviceName hinzufügen und device.gatt.getPrimaryService und service.getCharacteristic verwenden. Die characteristic.readValue-Methode gibt tatsächlich eine DataView zurück, die wir einfach mit TextDecoder decodieren.
playbulbCandle.js
const CANDLE_DEVICE_NAME_UUID = 0xFFFF;
...
getDeviceName() {
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_DEVICE_NAME_UUID))
.then(characteristic => characteristic.readValue())
.then(data => {
let decoder = new TextDecoder('utf-8');
return decoder.decode(data);
});
}
Wir fügen das in app.js ein, indem wir playbulbCandle.getDeviceName aufrufen, sobald wir verbunden sind, und den Gerätenamen anzeigen.
app.js
document.querySelector('#connect').addEventListener('click', event => {
playbulbCandle.connect()
.then(() => {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
return playbulbCandle.getDeviceName().then(handleDeviceName);
})
.catch(error => {
console.error('Argh!', error);
});
});
function handleDeviceName(deviceName) {
document.querySelector('#deviceName').value = deviceName;
}
Rufen Sie Ihre Website jetzt in Ihrem Webbrowser auf. Klicken Sie dazu in der Webserver-App auf die Webserver-URL, die hervorgehoben ist, oder aktualisieren Sie einfach die vorhandene Seite. Achten Sie darauf, dass die PLAYBULB Candle eingeschaltet ist. Klicken Sie dann auf der Seite auf die Schaltfläche „Verbinden“. Der Gerätename sollte unter der Farbauswahl angezeigt werden.

Akkustand ablesen
Das PLAYBULB Candle-Bluetooth-Gerät bietet auch ein standardmäßiges Bluetooth-Merkmal für den Akkustand, das den Akkustand des Geräts enthält. Das bedeutet, dass wir Standardnamen wie battery_service für die Bluetooth GATT Service UUID und battery_level für die Bluetooth GATT Characteristic UUID verwenden können.
Fügen wir der Klasse PlaybulbCandle eine neue getBatteryLevel-Methode hinzu und lesen wir den Akkustand in Prozent aus.
playbulbCandle.js
getBatteryLevel() {
return this.device.gatt.getPrimaryService('battery_service')
.then(service => service.getCharacteristic('battery_level'))
.then(characteristic => characteristic.readValue())
.then(data => data.getUint8(0));
}
Außerdem müssen wir das options-JavaScript-Objekt aktualisieren, um den Akku-Dienst in den optionalServices-Schlüssel aufzunehmen, da er vom PLAYBULB Candle-Bluetooth-Gerät nicht beworben wird, aber dennoch für den Zugriff erforderlich ist.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Wie zuvor fügen wir dies in app.js ein, indem wir playbulbCandle.getBatteryLevel aufrufen, sobald wir den Gerätenamen haben, und den Akkustand anzeigen.
app.js
document.querySelector('#connect').addEventListener('click', event => {
playbulbCandle.connect()
.then(() => {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
return playbulbCandle.getDeviceName().then(handleDeviceName)
.then(() => playbulbCandle.getBatteryLevel().then(handleBatteryLevel));
})
.catch(error => {
console.error('Argh!', error);
});
});
function handleDeviceName(deviceName) {
document.querySelector('#deviceName').value = deviceName;
}
function handleBatteryLevel(batteryLevel) {
document.querySelector('#batteryLevel').textContent = batteryLevel + '%';
}
Rufen Sie Ihre Website jetzt in Ihrem Webbrowser auf. Klicken Sie dazu auf die in der Webserver-App hervorgehobene Webserver-URL oder aktualisieren Sie einfach die vorhandene Seite. Klicken Sie auf der Seite auf die Schaltfläche „Verbinden“. Daraufhin sollten sowohl der Gerätename als auch der Akkustand angezeigt werden.
Als Nächstes
– Wie kann ich die Farbe dieser Glühbirne ändern? Deshalb bin ich hier!
– Du bist so nah dran, versprochen…
FAQ
6. Farbe ändern
Die Farbe lässt sich ganz einfach ändern, indem Sie eine bestimmte Reihe von Befehlen in eine Bluetooth-Eigenschaft (0xFFFC) im primären GATT-Dienst schreiben, der als 0xFF02 beworben wird. Wenn Sie beispielsweise Ihre PLAYBULB Candle auf Rot einstellen möchten, müssen Sie ein Array von 8-Bit-Ganzzahlen ohne Vorzeichen schreiben, das [0x00, 255, 0, 0] entspricht, wobei 0x00 die weiße Sättigung und 255, 0, 0 die Werte für Rot, Grün und Blau sind .
Wir verwenden characteristic.writeValue, um tatsächlich einige Daten in die Bluetooth-Charakteristik in der neuen öffentlichen Methode setColor der Klasse PlaybulbCandle zu schreiben. Außerdem geben wir die tatsächlichen Rot-, Grün- und Blauwerte zurück, wenn das Promise erfüllt ist, damit wir sie später in app.js verwenden können:
playbulbCandle.js
const CANDLE_COLOR_UUID = 0xFFFC;
...
setColor(r, g, b) {
let data = new Uint8Array([0x00, r, g, b]);
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_COLOR_UUID))
.then(characteristic => characteristic.writeValue(data))
.then(() => [r,g,b]);
}
Aktualisieren wir die Funktion changeColor in app.js so, dass playbulbCandle.setColor aufgerufen wird, wenn das Optionsfeld „Kein Effekt“ aktiviert ist. Die globalen Farbvariablen r, g, b sind bereits festgelegt, wenn der Nutzer auf die Farbauswahl klickt.
app.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
if (effect === 'noEffect') {
playbulbCandle.setColor(r, g, b).then(onColorChanged);
}
}
Rufen Sie Ihre Website jetzt in Ihrem Webbrowser auf. Klicken Sie dazu in der Webserver-App auf die Webserver-URL, die hervorgehoben ist, oder aktualisieren Sie einfach die vorhandene Seite. Klicken Sie auf der Seite auf die Schaltfläche „Verbinden“ und dann auf die Farbauswahl, um die Farbe Ihrer PLAYBULB Candle beliebig oft zu ändern.
Mehr Kerzeneffekte
Wenn Sie schon einmal eine Kerze angezündet haben, wissen Sie, dass das Licht nicht statisch ist. Glücklicherweise gibt es eine weitere Bluetooth-Eigenschaft (0xFFFB) im primären GATT-Dienst, die als 0xFF02 beworben wird und mit der der Nutzer einige Kerzeneffekte festlegen kann.
Wenn Sie beispielsweise einen Kerzeneffekt einstellen möchten, schreiben Sie [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]. Mit [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00] können Sie auch den „Blinkeffekt“ festlegen.
Fügen wir der Klasse PlaybulbCandle die Methoden setCandleEffectColor und setFlashingColor hinzu.
playbulbCandle.js
const CANDLE_EFFECT_UUID = 0xFFFB;
...
setCandleEffectColor(r, g, b) {
let data = new Uint8Array([0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]);
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_EFFECT_UUID))
.then(characteristic => characteristic.writeValue(data))
.then(() => [r,g,b]);
}
setFlashingColor(r, g, b) {
let data = new Uint8Array([0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00]);
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_EFFECT_UUID))
.then(characteristic => characteristic.writeValue(data))
.then(() => [r,g,b]);
}
Aktualisieren wir die Funktion changeColor in app.js, um playbulbCandle.setCandleEffectColor aufzurufen, wenn das Optionsfeld „Kerzeneffekt“ aktiviert ist, und playbulbCandle.setFlashingColor, wenn das Optionsfeld „Blinken“ aktiviert ist. Dieses Mal verwenden wir switch, wenn das für dich in Ordnung ist.
app.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
switch(effect) {
case 'noEffect':
playbulbCandle.setColor(r, g, b).then(onColorChanged);
break;
case 'candleEffect':
playbulbCandle.setCandleEffectColor(r, g, b).then(onColorChanged);
break;
case 'flashing':
playbulbCandle.setFlashingColor(r, g, b).then(onColorChanged);
break;
}
}
Rufen Sie Ihre Website jetzt in Ihrem Webbrowser auf. Klicken Sie dazu in der Webserver-App auf die Webserver-URL, die hervorgehoben ist, oder aktualisieren Sie einfach die vorhandene Seite. Klicken Sie auf der Seite auf die Schaltfläche „Verbinden“ und probieren Sie die Kerzen- und Blinkeffekte aus.
Als Nächstes
– Das ist alles? 3 Schlechte Kerzeneffekte? Ist das der Grund, warum ich hier bin?
– Es gibt noch mehr, aber dieses Mal musst du selbst herausfinden, welche.
7. Leg noch einen Zahn zu
Und hier sind wir! Sie denken vielleicht, dass es fast vorbei ist, aber die App ist noch nicht beendet. Sehen wir uns an, ob Sie wirklich verstanden haben, was Sie in diesem Codelab kopiert und eingefügt haben. Das kannst du jetzt selbst tun, um die App zu optimieren.
Fehlende Effekte hinzufügen
Hier sind die Daten für die fehlenden Effekte:
- Puls:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00](möglicherweise müssen Sie dort dier, g, b-Werte anpassen) - Regenbogen:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00](Personen mit Epilepsie sollten diese Option meiden) - Regenbogen-Fade:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Das bedeutet im Grunde, dass der Klasse PlaybulbCandle neue setPulseColor-, setRainbow- und setRainbowFade-Methoden hinzugefügt und in changeColor aufgerufen werden.
Problem „Kein Effekt“ beheben
Wie Sie vielleicht bemerkt haben, wird durch die Option „Kein Effekt“ kein laufender Effekt zurückgesetzt. Das ist zwar nur ein kleiner Fehler, aber er ist trotzdem vorhanden. Lass uns das beheben. Bei der setColor-Methode müssen Sie zuerst prüfen, ob ein Effekt über eine neue Klassenvariable _isEffectSet ausgeführt wird. Wenn true, deaktivieren Sie den Effekt, bevor Sie mit diesen Daten eine neue Farbe festlegen: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00].
Gerätename eingeben
Das ist ganz einfach. Das Schreiben eines benutzerdefinierten Gerätenamens ist so einfach wie das Schreiben in das Merkmal des vorherigen Bluetooth-Gerätenamens. Wir empfehlen, die Methode TextEncoder encode zu verwenden, um ein Uint8Array mit dem Gerätenamen abzurufen.
Dann würde ich eventListener als „input“ zu document.querySelector('#deviceName') hinzufügen und playbulbCandle.setDeviceName aufrufen, um es einfach zu halten.
Ich habe meine Playlist PLAY💡 CANDLE genannt.
8. Geschafft!
Lerninhalte
- Mit einem Bluetooth-Gerät in der Nähe in JavaScript interagieren
- ES2015-Klassen, Pfeilfunktionen, Map und Promises verwenden
Nächste Schritte
- Weitere Informationen zur Web Bluetooth API
- Sehen Sie sich die offiziellen Web Bluetooth-Beispiele und Demos an.
- Fliegende Grumpy Cat

