1. Di cosa si tratta?

In questo codelab illuminante, imparerai a controllare una candela a LED PLAYBULB senza fiamma solo con JavaScript grazie all'API Web Bluetooth. Lungo il percorso, giocherai anche con le funzionalità JavaScript ES2015 come classi, funzioni freccia, mappe e promesse.
Cosa imparerai a fare
- Come interagire con un dispositivo Bluetooth nelle vicinanze in JavaScript
- Come utilizzare le classi ES2015, le funzioni freccia, Map e Promises
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 da micro USB a USB.
2. Play first
Ti consigliamo di dare un'occhiata alla versione finale dell'app che stai per creare all'indirizzo https://googlecodelabs.github.io/candle-bluetooth e di provare il dispositivo Bluetooth PLAYBULB Candle a tua disposizione prima di iniziare questo codelab.
Puoi anche vedermi cambiare colore all'indirizzo https://www.youtube.com/watch?v=fBCPA9gIxlU
3. Configurazione
Scaricare il codice campione
Puoi ottenere il codice campione per questo codice scaricando il file ZIP qui:
o clonando questo repository Git:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Se hai scaricato l'origine come file ZIP, decomprimendola dovresti ottenere una cartella principale candle-bluetooth-master.
Installare e verificare il server web
Sebbene tu possa utilizzare il tuo server web, questo codelab è progettato per funzionare bene con Chrome Web Server. Se non l'hai ancora installata, puoi farlo dal Chrome Web Store.
Dopo aver installato l'app Web Server for Chrome, fai clic sul collegamento alle app nella barra dei preferiti:

Nella finestra successiva, fai clic sull'icona del server web:

Successivamente, vedrai questa finestra di dialogo, che ti consente di configurare il server web locale:

Fai clic sul pulsante Scegli cartella e seleziona la radice del repository clonato (o decompresso). In questo modo potrai pubblicare il tuo lavoro in corso tramite l'URL evidenziato nella finestra di dialogo del server web (nella sezione URL server web).
Nella sezione 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) e dovresti visualizzare una pagina simile a questa:

Se vuoi vedere l'aspetto di questa app sul tuo smartphone Android, devi attivare il debug remoto su Android e configurare l'inoltro delle porte (il numero di porta predefinito è 8887). Dopodiché, puoi semplicemente aprire una nuova scheda di Chrome per http://localhost:8887 sul tuo smartphone Android.
Avanti
A questo punto, questa app web non fa molto. Iniziamo ad aggiungere il supporto Bluetooth.
4. Scopri la candela
Inizieremo scrivendo una libreria che utilizza una classe JavaScript ES2015 per il dispositivo Bluetooth PLAYBULB Candle.
Mantieni la calma. La sintassi della classe 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.
Innanzitutto, 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 annuncia continuamente (se non è già stato accoppiato) un UUID del servizio GATT Bluetooth costante noto nella sua forma abbreviata come 0xFF02, possiamo semplicemente definire una costante e aggiungerla al parametro dei servizi di filtri in un nuovo metodo pubblico connect della classe PlaybulbCandle.
Monitoreremo internamente anche l'oggetto BluetoothDevice in modo da potervi accedere in un secondo momento, se necessario. Poiché navigator.bluetooth.requestDevice restituisce una promessa JavaScript ES2015, 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, la scoperta di dispositivi Bluetooth nelle vicinanze con navigator.bluetooth.requestDevice deve essere chiamata tramite un gesto dell'utente, ad esempio un tocco o un clic del mouse. Per questo motivo, 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 del server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante verde "Connetti", scegli il dispositivo nel selettore e apri la tua console Strumenti per sviluppatori preferita con la scorciatoia da tastiera Ctrl+Maiusc+J e nota l'oggetto BluetoothDevice registrato.

Potresti ricevere un messaggio di errore se il Bluetooth è disattivato e/o il dispositivo Bluetooth PLAYBULB Candle è spento. In questo caso, accendilo e procedi di nuovo.
Bonus obbligatorio
Non so tu, ma io vedo già troppi function() {} in questo codice. Passiamo invece alle () => {}funzioni freccia JavaScript ES2015. Sono un vero toccasana: tutta la bellezza delle funzioni anonime, nessuna tristezza del binding.
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);
});
});
Avanti
- Ok… posso parlare con questa candela o cosa?
- Certo… vai al passaggio successivo
Domande frequenti
5. Leggi qualcosa
Cosa fai ora che hai ricevuto un BluetoothDevice dalla promessa di navigator.bluetooth.requestDevice? Connettiamoci al server GATT del telecomando Bluetooth che contiene le definizioni di servizio e caratteristiche Bluetooth 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 connessi al server GATT del dispositivo Bluetooth PLAYBULB Candle. Ora vogliamo ottenere il servizio GATT principale (precedentemente pubblicizzato come 0xFF02) e leggere la caratteristica del nome del dispositivo (0xFFFF) che appartiene a questo servizio. Puoi farlo facilmente aggiungendo un nuovo metodo getDeviceName alla classe PlaybulbCandle e utilizzando device.gatt.getPrimaryService e service.getCharacteristic. Il metodo characteristic.readValue restituirà in realtà un 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 numero a app.js chiamando il numero playbulbCandle.getDeviceName una volta connessi e visualizziamo 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 del server web) o aggiorna semplicemente la pagina esistente. Assicurati che PLAYBULB Candle sia accesa, quindi fai clic sul pulsante "Connetti" nella pagina e dovresti vedere il nome del dispositivo sotto il selettore di 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 batteria nella chiave optionalServices, in quanto non viene 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, inseriamo questo valore in app.js chiamando playbulbCandle.getBatteryLevel una volta ottenuto 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 del server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante "Connetti" nella pagina e dovresti visualizzare sia il nome del dispositivo che il livello della batteria.
Avanti
- Come faccio a cambiare il colore di questa lampadina? Ecco perché sono qui.
- Ci sei quasi, te lo prometto...
Domande frequenti
6. Cambiare il colore
Cambiare colore è semplice come scrivere una serie specifica di comandi in una caratteristica Bluetooth (0xFFFC) nel servizio GATT principale pubblicizzato come 0xFF02. Ad esempio, per impostare la candela PLAYBULB sul colore rosso, devi scrivere un array di numeri interi senza segno a 8 bit uguale a [0x00, 255, 0, 0], dove 0x00 è la saturazione del bianco e 255, 0, 0 sono rispettivamente i valori di rosso, verde e blu .
Utilizzeremo characteristic.writeValue per scrivere effettivamente alcuni dati nella caratteristica Bluetooth nel nuovo metodo pubblico setColor della classe PlaybulbCandle. Restituiremo anche i valori effettivi di rosso, verde e blu quando la promessa viene soddisfatta, 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 è selezionato il pulsante di opzione "Nessun effetto". Le variabili di colore globali r, g, b 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 del server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante "Connetti" nella pagina e sul selettore di colori per cambiare il colore della candela PLAYBULB tutte le volte che vuoi.
Moar candle effects
Se hai già acceso una candela, sai che la luce non è statica. Fortunatamente per noi, esiste un'altra caratteristica Bluetooth (0xFFFB) nel servizio GATT principale pubblicizzato come 0xFF02 che consente all'utente di impostare alcuni effetti candela.
L'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]);
}
Aggiorniamo la funzione changeColor in app.js per chiamare playbulbCandle.setCandleEffectColor quando il pulsante di opzione "Effetto candela" è selezionato e playbulbCandle.setFlashingColor quando il pulsante di opzione "Lampeggiante" è selezionato. Questa volta utilizzeremo switch, se per te va bene.
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 del server web) o aggiorna semplicemente la pagina esistente. Fai clic sul pulsante "Connetti" nella pagina e prova gli effetti candela e lampeggiante.
Avanti
- È tutto? 3 effetti candela scadenti? È per questo che sono qui?
- Ce ne sono altri, ma questa volta dovrai cavartela da solo.
7. Fai un ultimo sforzo
Ed eccoci qui. Potresti pensare che sia quasi la fine, ma l'app non è ancora finita. Vediamo se hai capito davvero cosa hai copiato e incollato durante questo codelab. Ecco cosa devi fare ora per far brillare questa app.
Aggiungere effetti mancanti
Ecco i dati relativi agli effetti mancanti:
- Battito:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00](potresti voler regolare i valori dir, g, b) - Arcobaleno:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00](le persone con epilessia potrebbero voler evitare questo filtro) - Dissolvenza arcobaleno:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Ciò significa essenzialmente aggiungere nuovi metodi setPulseColor, setRainbow e setRainbowFade alla classe PlaybulbCandle e chiamarli in changeColor.
Risolvere il problema "Nessun effetto"
Come avrai notato, l'opzione"Nessun effetto" non reimposta alcun effetto in corso. Si tratta di un problema minore, ma comunque presente. Risolviamo il problema. Nel metodo setColor, devi prima verificare se è in corso un effetto tramite una nuova variabile di classe _isEffectSet e, se true, disattivare l'effetto prima di impostare un nuovo colore con questi dati: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00].
Scrivi il nome del dispositivo
Questa è facile. Scrivere un nome personalizzato per il dispositivo è semplice come scrivere nella caratteristica del nome del dispositivo Bluetooth precedente. Ti consiglio di utilizzare il metodo TextEncoder encode per ottenere un Uint8Array contenente il nome del dispositivo.
Poi, aggiungerei un "input" eventListener a document.querySelector('#deviceName') e chiamerei playbulbCandle.setDeviceName per semplificare.
Io l'ho chiamata PLAY💡 CANDLE.
8. È tutto.
Che cosa hai imparato
- Come interagire con un dispositivo Bluetooth nelle vicinanze in JavaScript
- Come utilizzare le classi ES2015, le funzioni freccia, Map e Promises
Passaggi successivi
- Scopri di più sull'API Web Bluetooth.
- Sfoglia gli esempi di Web Bluetooth e le demo ufficiali.
- Dai un'occhiata al gatto scontroso volante

