PLAYBULB-Kerze mit Web Bluetooth steuern

1. Worum geht es?

IMG_19700101_023537~2~2.jpg

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

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":

Screen Shot 2016-11-16 um 16.10.42 PM.png

Klicken Sie im nächsten Fenster auf das Webserversymbol:

9f3c21b2cf6cbfb5.png

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

Screen Shot 2016-11-16 at 5.40.47 PM.png

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:

Screen Shot 2016-11-16 at 5.40.56 PM.png

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:

Screen Shot 2016-11-16 um 15.20.22 PM.png

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.

Screen Shot 2016-11-16 um 15.27.12 PM.png

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.

Screen Shot 2016-11-16 um 15.29.21 PM.png

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.

Screen Shot 2016-11-16 um 15.29.21 PM.png

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.

Screen Shot 2016-11-16 um 15.31.37 PM.png

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.

Screen Shot 2016-11-16 at 5.27.26 PM.png

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 die r, 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