1. Di cosa parla?
In questo codelab illuminato, imparerai a controllare una candela senza fiamma LED PLAYBULB solo con JavaScript grazie all'API Web Bluetooth. Lungo il percorso, imparerai anche a utilizzare le funzionalità di JavaScript ES2015 come Classi, Funzioni freccia, Mappa e Promesse.
Cosa imparerai a fare
- Come interagire con un dispositivo Bluetooth nelle vicinanze in JavaScript
- Come utilizzare le classi, le funzioni delle frecce, la mappa e le promesse di ES2015
Che cosa ti serve
- Conoscenza di base dello sviluppo web
- Conoscenza di base di Bluetooth Low Energy (BLE) e Generic Attribute Profile (GATT).
- Un editor di testo a tua scelta
- Un Mac, un Chromebook o un dispositivo Android M con l'app browser Chrome e un cavo USB da micro a USB.
2. Riproduci prima
Prima di iniziare questo codelab, ti consigliamo di dare un'occhiata alla versione finale dell'app che stai per creare all'indirizzo https://googlecodelabs.github.io/candle-bluetooth e provare a usare il dispositivo Bluetooth PLAYBULB Candle di cui disponi.
Puoi anche guardarmi mentre cambio colore all'indirizzo https://www.youtube.com/watch?v=fBCPA9gIxlU
3. Configurazione
Scarica il codice campione
Puoi ottenere il codice campione di questo codice scaricando il file ZIP qui:
o clonando questo repository Git:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Se hai scaricato il file di origine come file ZIP, decomprimilo dovrebbe restituire una cartella principale candle-bluetooth-master
.
Installare e verificare il server web
Anche se puoi utilizzare liberamente il tuo server web, questo codelab è stato progettato per funzionare bene con il server web Chrome. Se non hai ancora installato l'app, puoi installarla dal Chrome Web Store.
Dopo aver installato l'app server web per Chrome, fai clic sulla scorciatoia App nella barra dei preferiti:
Nella finestra che viene visualizzata, fai clic sull'icona del server web:
Verrà visualizzata la finestra di dialogo riportata di seguito, che ti consente di configurare il server web locale:
Fai clic sul pulsante Scegli cartella e seleziona la radice del repository clonato (o rimosso dall'archivio). In questo modo potrai pubblicare il job in corso tramite l'URL evidenziato nella finestra di dialogo del server web (nella sezione URL server web).
In Opzioni, seleziona la casella accanto a "Mostra automaticamente index.html", come mostrato di seguito:
Ora visita il tuo sito nel browser web (facendo clic sull'URL del server web evidenziato). Dovresti vedere una pagina simile alla seguente:
Per vedere come si presenta questa app sul tuo telefono Android, devi attivare il Debug remoto su Android e configurare l'inoltro alla porta (il numero di porta per impostazione predefinita è 8887). Dopodiché puoi semplicemente aprire una nuova scheda di Chrome all'indirizzo http://localhost:8887 sul tuo telefono Android.
A seguire
Al momento l'applicazione web non è molto utile. Iniziamo ad aggiungere il supporto Bluetooth!
4. Scopri la candela
Inizieremo scrivendo una libreria che utilizzi una classe JavaScript ES2015 per il dispositivo Bluetooth PLAYBULB Candle.
Mantieni la calma. La sintassi delle classi non introduce un nuovo modello di ereditarietà orientato agli oggetti in JavaScript. Fornisce semplicemente una sintassi molto più chiara per creare oggetti e gestire l'ereditarietà, come puoi leggere di seguito.
Per prima cosa, definiamo una classe PlaybulbCandle
in playbulbCandle.js
e creiamo un'istanza playbulbCandle
che sarà disponibile nel file app.js
in un secondo momento.
playbulbCandle.js
(function() {
'use strict';
class PlaybulbCandle {
constructor() {
this.device = null;
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Per richiedere l'accesso a un dispositivo Bluetooth nelle vicinanze, dobbiamo chiamare il numero navigator.bluetooth.requestDevice
. Poiché il dispositivo PLAYBULB Candle pubblicizza in modo continuo (se non è già accoppiato) un UUID Bluetooth GATT Service costante noto nel formato breve come 0xFF02
, possiamo semplicemente definire una costante e aggiungerla al parametro dei filtri per i servizi in un nuovo metodo connect
pubblico della classe PlaybulbCandle
.
Terremo anche traccia internamente all'oggetto BluetoothDevice
in modo da potervi accedere in un secondo momento, se necessario. Poiché navigator.bluetooth.requestDevice
restituisce una promessa JavaScript ES2015 Promise, lo faremo nel metodo 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();
})();
Come funzionalità di sicurezza, il rilevamento di dispositivi Bluetooth nelle vicinanze con navigator.bluetooth.requestDevice
deve essere chiamato tramite un gesto dell'utente, ad esempio un tocco o un clic del mouse. Ecco perché chiameremo il metodo connect
quando l'utente fa clic sul pulsante "Connetti" nel file 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);
});
});
Esegui l'app
A questo punto, visita il tuo sito nel browser web (facendo clic sull'URL del server web evidenziato nell'app server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante verde "Connetti". seleziona il dispositivo nel selettore e apri la tua console preferita di DevTools con la scorciatoia da tastiera Ctrl + Maiusc + J. Noterai che l'oggetto BluetoothDevice
viene registrato.
Potresti visualizzare un errore se il Bluetooth è disattivato e/o il dispositivo Bluetooth PLAYBULB Candle è spento. In tal caso, attivala e procedi di nuovo.
Bonus obbligatorio
Non so tu, ma vedo già troppi function() {}
in questo codice. Passiamo alle funzioni freccia di () => {}
JavaScript ES2015. Sono una salvezza assoluta: la bellezza delle funzioni anonime, nessuna della tristezza del legame.
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);
});
});
A seguire
- Ok... posso parlare con questa candela o cosa?
- Certo... vai al passaggio successivo
Domande frequenti
5. Leggi qualcosa
Che cosa fai ora che hai ricevuto un BluetoothDevice
restituito dalla promessa di navigator.bluetooth.requestDevice
? Connettiti al server GATT remoto Bluetooth che contiene il servizio Bluetooth e le definizioni delle caratteristiche chiamando 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();
});
}
}
Leggere il nome del dispositivo
Qui siamo collegati al server GATT del dispositivo Bluetooth PLAYBULB Candle. Ora vogliamo ottenere il servizio GATT principale (pubblicizzato in precedenza come 0xFF02
) e leggere la caratteristica del nome del dispositivo (0xFFFF
) che appartiene a questo servizio. Per farlo, puoi facilmente aggiungere un nuovo metodo getDeviceName
alla classe PlaybulbCandle
e utilizzare device.gatt.getPrimaryService
e service.getCharacteristic
. Il metodo characteristic.readValue
restituisce effettivamente un valore DataView
che decodificheremo semplicemente con 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);
});
}
Aggiungiamo questo elemento a app.js
chiamando il numero playbulbCandle.getDeviceName
quando siamo connessi e mostriamo il nome del dispositivo.
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;
}
A questo punto, visita il tuo sito nel browser web (facendo clic sull'URL del server web evidenziato nell'app server web) o aggiorna semplicemente la pagina esistente. Assicurati che la candela PLAYBULB sia accesa, quindi fai clic sul pulsante "Connetti" della pagina e dovresti vedere il nome del dispositivo sotto il selettore colori.
Leggere il livello della batteria
Nel dispositivo Bluetooth PLAYBULB Candle è disponibile anche una caratteristica Bluetooth standard del livello della batteria che contiene il livello della batteria del dispositivo. Ciò significa che possiamo utilizzare nomi standard come battery_service
per l'UUID del servizio GATT Bluetooth e battery_level
per l'UUID della caratteristica GATT Bluetooth.
Aggiungiamo un nuovo metodo getBatteryLevel
alla classe PlaybulbCandle
e leggiamo il livello della batteria in percentuale.
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));
}
Dobbiamo anche aggiornare l'oggetto JavaScript options
per includere il servizio per la batteria alla chiave optionalServices
, in quanto non è pubblicizzato dal dispositivo Bluetooth PLAYBULB Candle, ma è comunque obbligatorio per accedervi.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Come prima, colleghiamo questo dispositivo a app.js
chiamando il numero playbulbCandle.getBatteryLevel
una volta che abbiamo il nome del dispositivo e visualizzato il livello della batteria.
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 + '%';
}
A questo punto, visita il tuo sito nel browser web (facendo clic sull'URL del server web evidenziato nell'app server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante "Connetti" nella pagina, dovresti vedere sia il nome del dispositivo sia il livello della batteria.
A seguire
- Come faccio a cambiare il colore di questa lampadina? Ecco perché sono qui.
- Ci sei quasi, prometto...
Domande frequenti
6. Cambiare il colore
Cambiare colore è facile come scrivere un insieme specifico di comandi in una caratteristica Bluetooth (0xFFFC
) nel servizio GATT principale pubblicizzato come 0xFF02
. Ad esempio, se converti in rosso la candela PLAYBULB, scrivi un array di numeri interi senza segno a 8 bit uguali a [0x00, 255, 0, 0]
, dove 0x00
è la saturazione del bianco e 255, 0, 0
sono, rispettivamente, i valori rosso, verde e blu .
Utilizzeremo characteristic.writeValue
per scrivere alcuni dati nella caratteristica Bluetooth nel nuovo metodo pubblico setColor
della classe PlaybulbCandle
. Quando la promessa viene mantenuta, ti restituiremo anche i valori rosso, verde e blu effettivi, in modo da poterli utilizzare in app.js
in un secondo momento:
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]);
}
Aggiorniamo la funzione changeColor
in app.js
per chiamare playbulbCandle.setColor
quando viene visualizzato il messaggio "Nessun effetto" sia selezionata. Le variabili colore r, g, b
globali sono già impostate quando l'utente fa clic sul canvas del selettore colori.
app.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
if (effect === 'noEffect') {
playbulbCandle.setColor(r, g, b).then(onColorChanged);
}
}
A questo punto, visita il tuo sito nel browser web (facendo clic sull'URL del server web evidenziato nell'app server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante "Connetti" nella pagina e fai clic sul selettore colori per cambiare il colore della candela PLAYBULB tutte le volte che vuoi.
Effetti a candela moar
Se hai già acceso una candela, sai che la luce non è statica. Fortunatamente per noi, c'è un'altra caratteristica Bluetooth (0xFFFB
) nel servizio GATT principale pubblicizzato come 0xFF02
che consente all'utente di impostare alcuni effetti a candela.
Impostazione di un "effetto candela" ad esempio può essere ottenuta scrivendo [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]
. Puoi anche impostare l'"effetto lampeggiante" con [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00]
.
Aggiungiamo i metodi setCandleEffectColor
e setFlashingColor
alla classe PlaybulbCandle
.
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]);
}
Inoltre aggiorniamo la funzione changeColor
in app.js
per chiamare playbulbCandle.setCandleEffectColor
quando l'"Effetto candela" sia selezionato e playbulbCandle.setFlashingColor
quando la dicitura "lampeggiante" sia selezionata. Questa volta, se ti va bene, useremo 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;
}
}
A questo punto, visita il tuo sito nel browser web (facendo clic sull'URL del server web evidenziato nell'app server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante "Connetti" sulla pagina e divertiti con gli effetti a candela e lampeggianti.
A seguire
- È tutto? Tre effetti negativi sulle candele? È per questo che sono qui?
- Ce ne sono altri, ma questa volta sarai da solo.
7. Fai uno sforzo in più
Eccoci qui! Forse pensi che sia quasi la fine del gioco, ma che l'app non è ancora finita. Vediamo se hai davvero compreso cosa hai copiato e incollato durante questo codelab. Ecco cosa vuoi fare autonomamente per far risaltare questa app.
Aggiungere effetti mancanti
Ecco i dati relativi agli effetti mancanti:
- Pulse:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00]
(puoi modificare i valori dir, g, b
lì) - Arcobaleno:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00]
(le persone epilettiche potrebbero voler evitare questo) - Dissolvenza arcobaleno:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Ciò significa sostanzialmente aggiungere nuovi metodi setPulseColor
, setRainbow
e setRainbowFade
alla classe PlaybulbCandle
e chiamarli in changeColor
.
Correggere l'errore "Nessun effetto"
Come avrai notato, il "nessun effetto" non reimposta alcun effetto in corso, si tratta di un comportamento minimo, ma comunque. Risolviamo il problema. Nel metodo setColor
, dovrai prima verificare se è in corso un effetto tramite una nuova variabile di classe _isEffectSet
e, in caso di true
, disattivare l'effetto prima di impostare un nuovo colore con questi dati: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00]
.
Scrittura nome dispositivo
Questa è facile! Scrivere un nome di dispositivo personalizzato è semplice come scrivere nella precedente caratteristica del nome del dispositivo Bluetooth. Ti consiglio di utilizzare il metodo encode
TextEncoder
per ottenere un Uint8Array
contenente il nome del dispositivo.
Quindi, aggiungo un "input" eventListener
a document.querySelector('#deviceName')
e chiama playbulbCandle.setDeviceName
per semplificare le cose.
Ho chiamato personalmente il mio PLAY💡 CANDLE!
8. È tutto.
Cosa hai imparato
- Come interagire con un dispositivo Bluetooth nelle vicinanze in JavaScript
- Come utilizzare le classi, le funzioni delle frecce, la mappa e le promesse di ES2015
Passaggi successivi
- Scopri di più sull'API Web Bluetooth
- Sfoglia le dimostrazioni e le demo di Bluetooth web ufficiali
- Dai un'occhiata al gatto scontroso che vola