1. O czym jest ta gra?
Dzięki tym ćwiczeniom z programowania dowiesz się, jak sterować płomieniową świecą LED PLAYBULB wyłącznie za pomocą JavaScriptu dzięki interfejsowi Web Bluetooth API. Podczas nauki będziesz też korzystać z funkcji języka JavaScript ES2015, takich jak klasy, funkcje strzałek, Mapa i Promises.
Czego się nauczysz
- Jak wchodzić w interakcję z urządzeniem Bluetooth w pobliżu w języku JavaScript
- Jak korzystać z klas, funkcji strzałek, map i obietnic ES2015
Czego potrzebujesz
- Podstawowa wiedza na temat programowania stron internetowych
- Podstawowa wiedza o Bluetooth Low Energy (BLE) i ogólnym profilu atrybutów (GATT).
- wybrany przez Ciebie edytor tekstu;
- Mac, Chromebook lub urządzenie z Androidem M z przeglądarką Chrome i kablem USB micro na USB.
2. Odtwórz jako pierwszy
Przed rozpoczęciem tego ćwiczenia z programowania warto zapoznać się z ostateczną wersją aplikacji, którą zamierzasz utworzyć, na stronie https://googlecodelabs.github.io/candle-bluetooth i pobawić się dostępnego urządzenia Bluetooth PLAYBULB Candle.
Możesz też zobaczyć, jak zmieniam kolory, na stronie https://www.youtube.com/watch?v=fBCPA9gIxlU
3. Konfiguracja
Pobierz przykładowy kod
Przykładowy kod dla tego kodu możesz pobrać, pobierając plik ZIP tutaj:
lub sklonując to repozytorium Git:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Jeśli źródło zostało pobrane w postaci pliku ZIP, po rozpakowaniu powinien pojawić się folder główny candle-bluetooth-master
.
Instalowanie i weryfikacja serwera WWW
Możesz wykorzystać własny serwer WWW, ale to ćwiczenie w Codelabs działa dobrze z serwerem Chrome Web Server. Jeśli nie masz jeszcze zainstalowanej tej aplikacji, możesz ją zainstalować ze sklepu Chrome Web Store.
Po zainstalowaniu aplikacji Serwer internetowy dla Chrome kliknij skrót Aplikacje na pasku zakładek:
W wyświetlonym oknie kliknij ikonę Serwer WWW:
Zostanie wyświetlone następujące okno dialogowe, które umożliwia skonfigurowanie lokalnego serwera WWW:
Kliknij przycisk Wybierz folder i wybierz katalog główny sklonowanego (lub przywróconego z archiwum) repozytorium. Umożliwi Ci to udostępnianie tworzonej pracy pod adresem URL wyróżnionym w oknie serwera WWW (w sekcji Adresy URL serwera WWW).
W sekcji Opcje zaznacz pole „Automatycznie pokazuj index.html”, jak pokazano poniżej:
Teraz otwórz swoją witrynę w przeglądarce (klikając wyróżniony adres URL serwera WWW). Wyświetli się strona podobna do tej:
Jeśli chcesz zobaczyć, jak ta aplikacja wygląda na Twoim telefonie z Androidem, włącz Zdalne debugowanie na Androidzie i skonfiguruj przekierowanie portów (domyślnie numer portu to 8887). Gdy to zrobisz, na telefonie z Androidem możesz po prostu otworzyć nową kartę Chrome na stronie http://localhost:8887.
Dalsze czynności
Obecnie aplikacja internetowa nie robi zbyt wielu zadań. Rozpocznijmy dodawanie obsługi Bluetooth!
4. Odkryj świecę
Zaczniemy od utworzenia biblioteki korzystającej z klasy JavaScript ES2015 na potrzeby urządzenia Bluetooth PLAYBULB Candle.
Zachowaj spokój. Składnia klas nie wprowadza do JavaScriptu nowego modelu dziedziczenia zorientowanego na obiekt. Zapewnia po prostu znacznie bardziej przejrzystą składnię umożliwiającą tworzenie obiektów i obsługę dziedziczenia, jak pokazano poniżej.
Najpierw zdefiniujmy klasę PlaybulbCandle
w narzędziu playbulbCandle.js
i utwórz instancję playbulbCandle
, która będzie dostępna później w pliku app.js
.
playbulbCandle.js
(function() {
'use strict';
class PlaybulbCandle {
constructor() {
this.device = null;
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Aby poprosić o dostęp do urządzenia Bluetooth w pobliżu, musimy zadzwonić pod numer navigator.bluetooth.requestDevice
. Urządzenie PLAYBULB Candle reklamuje stale (jeśli nie jest jeszcze sparowane) stały identyfikator UUID usługi Bluetooth GATT znany w skrócie 0xFF02
, możemy więc po prostu zdefiniować stałą i dodać ją do parametru usług filtrów w nowej publicznej metodzie connect
klasy PlaybulbCandle
.
Będziemy też monitorować obiekt BluetoothDevice
wewnętrznie, aby w razie potrzeby mieć do niego dostęp później. Ponieważ funkcja navigator.bluetooth.requestDevice
zwraca JavaScript ES2015 Promise, zrobimy to w metodzie then
.
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();
})();
W ramach funkcji zabezpieczeń wykrywanie urządzeń Bluetooth w pobliżu za pomocą funkcji navigator.bluetooth.requestDevice
musi być wywoływane gestem użytkownika, takim jak dotknięcie lub kliknięcie myszy. Dlatego po kliknięciu przycisku „Połącz” przez użytkownika będziemy nazywać metodę connect
. przycisk w pliku 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);
});
});
Uruchom aplikację
W tym momencie odwiedź swoją witrynę w przeglądarce (klikając adres URL serwera WWW zaznaczony w aplikacji serwera WWW) lub po prostu odśwież istniejącą stronę. Kliknij zielony przycisk „Połącz”, , wybierz urządzenie z selektora i otwórz ulubioną konsolę Narzędzi deweloperskich za pomocą skrótu klawiszowego Ctrl + Shift + J. Zauważ, że został zarejestrowany obiekt BluetoothDevice
.
Jeśli Bluetooth jest wyłączony lub urządzenie Bluetooth Świeca PLAYBULB jest wyłączone, może pojawić się błąd. W takim przypadku włącz je i kontynuuj jeszcze raz.
Obowiązkowy bonus
Nie wiem jak Ty, ale w tym kodzie widzę już za dużo elementów typu function() {}
. Przełączmy się na funkcje strzałek () => {}
JavaScript ES2015. To absolutnie ratowanie życia: wszystkie uroki funkcji anonimowych, zero smutku związanego z wiązaniem.
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);
});
});
Dalsze czynności
– OK... Mogę mówić do tej świecy czy co?
- Jasne... przejdź do następnego kroku
Najczęstsze pytania
5. Czytaj coś
Co zrobić teraz, gdy otrzymasz zwrot BluetoothDevice
z oferty, którą przygotował(a) navigator.bluetooth.requestDevice
? Połączmy się ze zdalnym serwerem GATT Bluetooth, który zawiera usługę Bluetooth i definicje cech, wywołując funkcję device.gatt.connect()
:
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();
});
}
}
Odczytywanie nazwy urządzenia
Nawiązaliśmy połączenie z serwerem GATT urządzenia Bluetooth PLAYBULB Candle. Teraz chcemy pobrać podstawową usługę GATT (reklamowaną wcześniej jako 0xFF02
) i odczytać cechę nazwy urządzenia (0xFFFF
), która należy do tej usługi. Można to łatwo osiągnąć, dodając nową metodę getDeviceName
do klasy PlaybulbCandle
oraz używając tagów device.gatt.getPrimaryService
i service.getCharacteristic
. Metoda characteristic.readValue
zwraca tak naprawdę obiekt DataView
, który po prostu zdekodujemy za pomocą funkcji 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);
});
}
Dodajmy to do urządzenia app.js
, dzwoniąc pod numer playbulbCandle.getDeviceName
, gdy już się połączysz i wyświetlimy nazwę urządzenia.
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;
}
W tym momencie odwiedź swoją witrynę w przeglądarce (klikając adres URL serwera WWW zaznaczony w aplikacji serwera WWW) lub po prostu odśwież istniejącą stronę. Upewnij się, że świeca PLAYBULB jest włączona, a następnie kliknij „Połącz”. na stronie. Pod selektorem kolorów powinna się pojawić nazwa urządzenia.
Odczytywanie poziomu baterii
Urządzenie Bluetooth PLAYBULB Candle zawiera standardową charakterystykę Bluetooth poziomu baterii, która określa poziom baterii urządzenia. Oznacza to, że możemy używać standardowych nazw, takich jak battery_service
dla identyfikatora UUID usługi Bluetooth GATT oraz battery_level
dla identyfikatora UUID o charakterze GATT Bluetooth.
Dodajmy nową metodę getBatteryLevel
do klasy PlaybulbCandle
i odczytujemy poziom baterii w procentach.
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));
}
Musimy również zaktualizować obiekt JavaScript options
, dodając do klucza optionalServices
usługę baterii, ponieważ nie jest on rozgłaszany przez urządzenie Bluetooth PLAYBULB Candle, ale i tak jest wymagany, aby uzyskać do niego dostęp.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Tak jak poprzednio, podłączmy to do urządzenia app.js
, dzwoniąc pod playbulbCandle.getBatteryLevel
, gdy otrzymamy nazwę urządzenia i wyświetlimy poziom baterii.
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 + '%';
}
W tym momencie odwiedź swoją witrynę w przeglądarce (klikając adres URL serwera WWW zaznaczony w aplikacji serwera WWW) lub po prostu odśwież istniejącą stronę. Kliknij przycisk „Połącz”. na stronie, zobaczysz nazwę urządzenia i poziom baterii.
Dalsze czynności
- Jak zmienić kolor tej żarówki? Dlatego tu jestem.
– Jesteś już tak blisko...
Najczęstsze pytania
6. Zmiana koloru
Aby zmienić kolor, wystarczy wpisać określony zestaw poleceń na cechę Bluetooth (0xFFFC
) w podstawowej usłudze GATT reklamowanej jako 0xFF02
. Na przykład zmiana koloru świecy PLAYBULB na czerwony spowoduje zapisanie tablicy 8-bitowych liczb całkowitych równą [0x00, 255, 0, 0]
, gdzie 0x00
to nasycenie białego, a 255, 0, 0
to odpowiednio wartości czerwone, zielone i niebieskie .
Wykorzystamy characteristic.writeValue
, aby zapisać część danych o charakterze Bluetooth w nowej metodzie publicznej setColor
klasy PlaybulbCandle
. Po spełnieniu obietnicy zwrócimy również rzeczywiste wartości czerwonego, zielonego i niebieskiego, aby można było ich później użyć w app.js
:
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]);
}
Zaktualizujmy funkcję changeColor
w narzędziu app.js
, tak aby wywoływała funkcję playbulbCandle.setColor
w przypadku parametru „Brak efektu” jest zaznaczony. Globalne zmienne kolorów r, g, b
są już ustawione, gdy użytkownik kliknie obszar roboczy selektora kolorów.
app.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
if (effect === 'noEffect') {
playbulbCandle.setColor(r, g, b).then(onColorChanged);
}
}
W tym momencie odwiedź swoją witrynę w przeglądarce (klikając adres URL serwera WWW zaznaczony w aplikacji serwera WWW) lub po prostu odśwież istniejącą stronę. Kliknij przycisk „Połącz”. na stronie. Kliknij selektor kolorów, by zmieniać kolor świecy PLAYBULB świeci tak często, jak tylko chcesz.
Efekty świec moarnych
Jeśli udało Ci się już zapalić świecę, oznacza to, że światło nie jest statyczne. Na szczęście w podstawowej usłudze GATT występuje jeszcze jedna cecha Bluetooth (0xFFFB
), która pozwala użytkownikowi ustawić niektóre efekty świec.0xFF02
Ustawianie „efektu świecy” na przykład przez wpisanie [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]
. Możesz też ustawić „efekt migania” dzięki [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00]
.
Dodajmy do klasy PlaybulbCandle
metody setCandleEffectColor
i setFlashingColor
.
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]);
}
Zaktualizujmy też funkcję changeColor
w app.js
, tak aby wywoływała funkcję playbulbCandle.setCandleEffectColor
, gdy „Efekt świecowy” jest zaznaczona opcja playbulbCandle.setFlashingColor
, a opcja „Migające” jest zaznaczony. Tym razem, jeśli nie masz na to zgody, użyjemy domeny switch
.
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;
}
}
W tym momencie odwiedź swoją witrynę w przeglądarce (klikając adres URL serwera WWW zaznaczony w aplikacji serwera WWW) lub po prostu odśwież istniejącą stronę. Kliknij przycisk „Połącz”. kliknij przycisk Świeca i Migające efekty.
Dalsze czynności
– To wszystko? 3 słabe efekty świec? Dlaczego tu jestem?
– Jest ich więcej, ale tym razem będziesz na swoim miejscu.
7. Dołóż dodatkowych starań
I o to chodzi! Może Ci się wydawać, że to już prawie koniec, a aplikacja jeszcze trwa. Sprawdźmy, czy rozumiesz treść skopiowaną i wklejoną podczas tego ćwiczenia z programowania. Oto, co chcesz zrobić teraz, aby ta aplikacja się wyróżniała.
Dodaj brakujące efekty
Oto dane dotyczące brakujących efektów:
- Puls:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00]
(tam warto dostosować wartościr, g, b
) - Tęcza:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00]
(osoby padaczkowe mogą lepiej jej unikać) - Tęczowe zanikanie:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Oznacza to dodanie nowych metod setPulseColor
, setRainbow
i setRainbowFade
do klasy PlaybulbCandle
i wywoływanie ich w changeColor
.
Rozwiązywanie problemu „Brak efektu”
Jak być może zauważyliście, opcja „Brak efektu” nie powoduje zresetowania żadnego trwającego efektu. Jest to mało istotne, ale nadal. Naprawmy to. W metodzie setColor
musisz najpierw sprawdzić, czy efekt jest generowany za pomocą nowej zmiennej klasy _isEffectSet
, a jeśli true
, wyłącz efekt, zanim ustawisz nowy kolor na podstawie tych danych: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00]
.
Zapisz nazwę urządzenia
To proste! Aby wpisać własną nazwę urządzenia, wystarczy wpisać poprzednią nazwę urządzenia Bluetooth. Zalecamy użycie metody TextEncoder
encode
, aby uzyskać Uint8Array
z nazwą urządzenia.
Następnie dodaj „wejściowe” eventListener
do usługi document.querySelector('#deviceName')
i wywołaj playbulbCandle.setDeviceName
.
Moja nazwa to PLAY💡 CANDLE!
8. Znakomicie.
Czego się dowiedziałeś(-aś)
- Jak wchodzić w interakcję z urządzeniem Bluetooth w pobliżu w języku JavaScript
- Jak korzystać z klas, funkcji strzałek, map i obietnic ES2015
Następne kroki
- Dowiedz się więcej o interfejsie Web Bluetooth API.
- Przejrzyj oficjalne przykłady Web Bluetooth i wersje demonstracyjne
- Zobacz latającego wstrętnego kota