1. Worum geht es?
In diesem Codelab erfahren Sie, wie Sie eine PLAYBULB LED-Kerze ohne Flammen mithilfe der Web Bluetooth API nur mit JavaScript steuern. Dabei können Sie auch mit JavaScript ES2015-Funktionen wie Klassen, Pfeilfunktionen, Map und Promise-Objekte experimentieren.
Aufgaben in diesem Lab
- Mit einem Bluetooth-Gerät in der Nähe in JavaScript interagieren
- So verwenden Sie ES2015-Klassen, Pfeilfunktionen, Karten und Promise-Objekte
Voraussetzungen
- Grundlegendes Verständnis der Webentwicklung
- Grundkenntnisse in Bluetooth Low Energy (BLE) und dem Generic Attribute Profile (GATT)
- Ein Texteditor Ihrer Wahl
- Ein Mac, ein Chromebook oder ein Android M-Gerät mit der Chrome-App und einem USB-Micro-auf-USB-Kabel
2. Zuerst spielen
Wir empfehlen Ihnen, sich unter https://googlecodelabs.github.io/candle-bluetooth die endgültige Version der App anzusehen, die Sie gerade erstellen, und mit dem PLAYBULB Candle-Bluetooth-Gerät zu experimentieren, bevor Sie mit diesem Codelab beginnen.
Unter https://www.youtube.com/watch?v=fBCPA9gIxlU kannst du mir 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, sollten Sie beim Entpacken den Stammordner candle-bluetooth-master
erhalten.
Webserver installieren und prüfen
Sie können zwar Ihren eigenen Webserver verwenden, dieses Codelab wurde jedoch speziell für den Chrome-Webserver entwickelt. Wenn Sie die App noch nicht installiert haben, können Sie sie über den Chrome Web Store installieren.
Klicken Sie nach der Installation der App "Webserver für Chrome" in der Lesezeichenleiste auf die Verknüpfung "Apps":
Klicken Sie im nächsten Fenster auf das Webserversymbol:
Als Nächstes wird das folgende 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 wieder aktivierten Repositorys aus. So können Sie Ihre laufenden Arbeiten über die im Webserverdialogfeld (im Bereich Webserver-URL(s)) hervorgehobene URL bereitstellen.
Klicken Sie unter „Optionen“ das Kästchen neben Index.html automatisch anzeigen an:
Rufen Sie nun Ihre Website in Ihrem Webbrowser auf, indem Sie auf die hervorgehobene Webserver-URL klicken. Daraufhin sollte eine Seite wie die folgende angezeigt werden:
Wenn Sie sehen möchten, wie diese App auf Ihrem Android-Smartphone aussieht, müssen Sie Remote-Debugging für Android aktivieren und die Portweiterleitung einrichten. Standardmäßig ist die Port-Nummer 8887. Danach können Sie einfach einen neuen Chrome-Tab mit http://localhost:8887 auf Ihrem Android-Smartphone öffnen.
Nächstes Thema
An dieser Stelle ist diese Web-App noch nicht erfolgreich. Fügen wir nun die Bluetooth-Unterstützung hinzu!
4. Entdecke die Kerze
Wir beginnen mit dem Schreiben einer Bibliothek, die eine JavaScript ES2015-Klasse für das Bluetooth-Gerät PLAYBULB Candle verwendet.
Bewahren Sie Ruhe. Mit der Klassensyntax wird kein neues objektorientiertes Vererbungsmodell in JavaScript eingeführt. Es bietet einfach eine viel klarere Syntax zum Erstellen von Objekten und zum Umgang mit Vererbung, wie Sie weiter unten lesen können.
Definieren wir zuerst eine PlaybulbCandle
-Klasse in playbulbCandle.js
und erstellen eine playbulbCandle
-Instanz, die später in der app.js
-Datei verfügbar ist.
playbulbCandle.js
(function() {
'use strict';
class PlaybulbCandle {
constructor() {
this.device = null;
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Wenn du Zugriff auf ein Bluetooth-Gerät in der Nähe anfordern möchtest, müssen wir navigator.bluetooth.requestDevice
anrufen. Da das PLAYBULB Candle-Gerät fortlaufend (falls nicht bereits gekoppelt) eine konstante Bluetooth-GATT-Dienst-UUID anbietet, die in seiner Kurzform als 0xFF02
bekannt ist, können wir einfach eine Konstante definieren und diese zum Filterdienst-Parameter in einer neuen öffentlichen connect
-Methode der PlaybulbCandle
-Klasse hinzufügen.
Wir verfolgen auch intern das BluetoothDevice
-Objekt, damit wir später bei Bedarf darauf zugreifen können. Da navigator.bluetooth.requestDevice
ein JavaScript ES2015 Promise zurückgibt, verwenden wir die then
-Methode.
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();
})();
Als Sicherheitsfunktion muss die Ermittlung von Bluetooth-Geräten in der Nähe mit navigator.bluetooth.requestDevice
durch eine Nutzergeste wie eine Berührung oder einen Mausklick aufgerufen werden. Deshalb wird die Methode connect
aufgerufen, wenn der Nutzer Schaltfläche in der Datei app.js
:
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 nun Ihre Website in Ihrem Webbrowser auf, indem Sie auf die in der Webserver-App hervorgehobene Webserver-URL klicken, oder aktualisieren Sie einfach die vorhandene Seite. Klicke auf die grüne Schaltfläche „Verbinden“ wählen Sie das Gerät in der Auswahl aus und öffnen Sie mit der Tastenkombination Strg + Umschalttaste + J die bevorzugte Entwicklertools-Konsole. Das BluetoothDevice
-Objekt wird protokolliert.
Möglicherweise erhalten Sie eine Fehlermeldung, wenn Bluetooth und/oder das Bluetooth-Gerät PLAYBULB Candle ausgeschaltet ist. Schalten Sie sie in diesem Fall wieder ein und fahren Sie noch einmal fort.
Obligatorischer Bonus
Ich weiß nicht, wie es Ihnen geht, aber ich sehe bereits zu viele function() {}
in diesem Code. Wechseln wir stattdessen zu () => {}
JavaScript ES2015 Arrow Functions. Sie sind wirklich lebensrettend: Und so schön: anonyme Funktionen.
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);
});
});
Nächstes Thema
- Okay... kann ich mit dieser Kerze sprechen oder was?
- Klar... weiter zum nächsten Schritt
FAQ
5. Etwas lesen
Was tun Sie jetzt, nachdem Sie ein BluetoothDevice
aus dem Versprechen von navigator.bluetooth.requestDevice
zurückerhalten haben? Stellen wir eine Verbindung zum Bluetooth-Remote-GATT-Server her, der den Bluetooth-Dienst und die Definitionen der Eigenschaften 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 lesen
Hier sind wir mit dem GATT-Server des Bluetooth-Geräts PLAYBULB Candle verbunden. Nun möchten wir den primären GATT-Dienst abrufen, der zuvor als 0xFF02
beworben wurde, und das Gerätenamen-Merkmal (0xFFFF
) lesen, das zu diesem Dienst gehört. Dazu fügen Sie der Klasse PlaybulbCandle
die neue Methode getDeviceName
hinzu und verwenden device.gatt.getPrimaryService
und service.getCharacteristic
. Die Methode characteristic.readValue
gibt tatsächlich ein DataView
zurück. Die Decodierung erfolgt einfach mit TextDecoder
.
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 dies zu app.js
hinzu, indem wir playbulbCandle.getDeviceName
aufrufen, sobald die Verbindung besteht und der Gerätename angezeigt wird.
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 nun Ihre Website in Ihrem Webbrowser auf, indem Sie auf die in der Webserver-App hervorgehobene Webserver-URL klicken, oder aktualisieren Sie einfach die vorhandene Seite. Aktiviere die PLAYBULB-Kerze und klicke auf „Verbinden“ auf der Seite klicken und der Gerätename unter der Farbauswahl angezeigt wird.
Akkustand ablesen
Im Bluetooth-Gerät PLAYBULB Candle ist auch eine standardmäßige Bluetooth-Eigenschaft für den Akkustand verfügbar, die den Akkustand des Geräts angibt. Das bedeutet, dass wir Standardnamen wie battery_service
für die UUID des Bluetooth GATT-Dienstes und battery_level
für die UUID des Bluetooth GATT-Charakters verwenden können.
Wir fügen der Klasse PlaybulbCandle
eine neue Methode getBatteryLevel
hinzu und lesen den Akkustand in Prozent.
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 JavaScript-Objekt options
so aktualisieren, dass der Akkudienst in den Schlüssel optionalServices
aufgenommen wird, da er nicht vom Bluetooth-Gerät PLAYBULB Candle beworben wird, aber trotzdem für den Zugriff erforderlich ist.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Verbinden wir es wie zuvor mit app.js
, indem wir playbulbCandle.getBatteryLevel
aufrufen, sobald wir den Gerätenamen haben und den Akkustand anzeigen können.
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 nun Ihre Website in Ihrem Webbrowser auf, indem Sie auf die in der Webserver-App hervorgehobene Webserver-URL klicken, oder aktualisieren Sie einfach die vorhandene Seite. Klicke auf „Verbinden“ auf der Seite klicken. Nun sollten sowohl der Gerätename als auch der Akkustand angezeigt werden.
Nächstes Thema
- Wie kann ich die Farbe der Lampe ändern? Deshalb bin ich hier!
- Du bist ganz nah dran...
FAQ
6. Farbe ändern
Das Ändern der Farbe ist so einfach wie das Schreiben eines bestimmten Befehls in eine Bluetooth-Eigenschaft (0xFFFC
) im primären GATT-Dienst, der als 0xFF02
beworben wird. Wenn Sie beispielsweise Ihre PLAYBULB-Kerze auf Rot umschalten, würden Sie ein Array von vorzeichenlosen 8-Bit-Ganzzahlen schreiben, die [0x00, 255, 0, 0]
entsprechen, wobei 0x00
die weiße Sättigung und 255, 0, 0
die roten, grünen und blauen Werte sind .
Wir verwenden characteristic.writeValue
, um einige Daten in die Bluetooth-Eigenschaft der neuen öffentlichen Methode setColor
der Klasse PlaybulbCandle
zu schreiben. Außerdem geben wir die tatsächlichen roten, grünen und blauen Werte zurück, wenn das Versprechen 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 „Kein Effekt“ aktiviert ist. Die globalen Farbvariablen r, g, b
sind bereits festgelegt, wenn der Nutzer auf den Canvas zur 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 nun Ihre Website in Ihrem Webbrowser auf, indem Sie auf die in der Webserver-App hervorgehobene Webserver-URL klicken, oder aktualisieren Sie einfach die vorhandene Seite. Klicke auf „Verbinden“ auf der Seite und klicken Sie auf die Farbauswahl, um die Farbe Ihrer PLAYBULB-Kerze beliebig oft zu ändern.
Kerzeneffekte
Wenn du schon einmal eine Kerze angezündet hast, weißt du, dass das Licht nicht statisch ist. Glücklicherweise gibt es im primären GATT-Dienst eine weitere Bluetooth-Eigenschaft (0xFFFB
), mit der Nutzer Kerzeneffekte einstellen können, die als 0xFF02
beworben werden.
„Kerzeneffekt“ festlegen durch Schreiben von [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]
erreichen. Außerdem können Sie den Blinkeffekt mit [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00]
.
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 nun die Funktion changeColor
in app.js
, um playbulbCandle.setCandleEffectColor
aufzurufen, wenn der „Kerzeneffekt“ aktiviert ist, und playbulbCandle.setFlashingColor
, wenn das Blinken aktiviert ist. Dieses Mal verwenden wir switch
, sofern du damit einverstanden bist.
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 nun Ihre Website in Ihrem Webbrowser auf, indem Sie auf die in der Webserver-App hervorgehobene Webserver-URL klicken, oder aktualisieren Sie einfach die vorhandene Seite. Klicke auf „Verbinden“ auf der Seite und spielen Sie mit Kerzen- und Blitzeffekten.
Nächstes Thema
- Das ist alles? Drei schlechte Kerzeneffekte? Ist das der Grund, warum ich hier bin?
- Es gibt noch mehr, aber diesmal bist du auf dich allein gestellt.
7. Streng dich an
Das sind wir! Vielleicht denken Sie, es ist fast das Ende der App, aber die App ist noch nicht fertig. Mal sehen, ob du wirklich verstanden hast, was du in diesem Codelab kopiert und eingefügt hast. Hier erfährst du, was du selbst tun solltest, um diese App optimal zu nutzen.
Fehlende Effekte hinzufügen
Hier die Daten für die fehlenden Effekte:
- Puls:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00]
(hier können Sie dier, g, b
-Werte anpassen) - Regenbogen:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00]
(Epileptische Menschen sollten diesen meiden.) - Farbwechsel mit Regenbogen:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Das bedeutet im Grunde, dass der PlaybulbCandle
-Klasse neue Methoden setPulseColor
, setRainbow
und setRainbowFade
hinzugefügt und in changeColor
aufgerufen werden.
Probleme mit „Kein Effekt“ beheben
Wie Sie vielleicht bemerkt haben, setzt die Option keinen laufenden Effekt zurück. Diese Option ist zwar geringfügig, aber trotzdem. Lassen Sie uns das ändern. In der setColor
-Methode müssen Sie zuerst prüfen, ob eine neue Klassenvariable _isEffectSet
verwendet wird. Deaktivieren Sie bei true
den Effekt, bevor Sie eine neue Farbe mit diesen Daten festlegen: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00]
.
Gerätename schreiben
Das ist ganz einfach! Die Eingabe eines benutzerdefinierten Gerätenamens ist so einfach wie das bisherige Merkmal des Bluetooth-Gerätenamens. Ich empfehle dir, die Methode TextEncoder
encode
zu verwenden, um eine Uint8Array
mit dem Gerätenamen zu erhalten.
Dann füge ich eine „Eingabe“ hinzu, eventListener
an document.querySelector('#deviceName')
und rufe playbulbCandle.setDeviceName
auf.
Mein Name ist mir PLAY💡 KANDLE!
8. Fertig!
Was Sie gelernt haben
- Mit einem Bluetooth-Gerät in der Nähe in JavaScript interagieren
- So verwenden Sie ES2015-Klassen, Pfeilfunktionen, Karten und Promise-Objekte
Nächste Schritte
- Weitere Informationen zur Web Bluetooth API
- Offizielle Web Bluetooth-Beispiele und Demos ansehen
- Sieh dir die fliegende mürrische Katze an