1. De quoi s'agit-il ?
Dans cet atelier de programmation éclairé, vous allez apprendre à contrôler une bougie LED PLAYBULB sans flamme avec uniquement JavaScript grâce à l'API Web Bluetooth. En cours de route, vous vous amuserez également avec les fonctionnalités JavaScript ES2015 telles que les classes, les fonctions fléchées, la carte et les promesses.
Points abordés
- Interagir avec un appareil Bluetooth à proximité en JavaScript
- Utiliser les classes ES2015, les fonctions fléchées, les cartes et les promesses
Prérequis
- Connaissances de base en développement Web
- Connaissances de base sur la technologie Bluetooth à basse consommation (BLE) et le profil d'attribut générique (GATT)
- Un éditeur de texte de votre choix
- Un Mac, un Chromebook ou un appareil Android M avec l'application du navigateur Chrome et un câble micro USB vers USB
2. À jouer en premier
Vous pouvez essayer la version finale de l'application que vous êtes sur le point de créer à l'adresse https://googlecodelabs.github.io/candle-bluetooth et jouer avec l'appareil Bluetooth PLAYBULB Candle dont vous disposez avant de vous plonger dans cet atelier de programmation.
Vous pouvez également me regarder changer de couleur sur https://www.youtube.com/watch?v=fBCPA9gIxlU.
3. Configuration
Télécharger l'exemple de code
Vous pouvez obtenir l'exemple de code pour ce code en téléchargeant le fichier ZIP ici:
ou en clonant ce dépôt Git:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Si vous avez téléchargé la source en tant que fichier ZIP, la décompression devrait vous donner un dossier racine candle-bluetooth-master
.
Installer et vérifier le serveur Web
Bien que vous soyez libre d'utiliser votre propre serveur Web, cet atelier de programmation est conçu pour fonctionner correctement avec le serveur Web Chrome. Si vous n'avez pas encore installé cette application, vous pouvez l'installer depuis le Chrome Web Store.
Après avoir installé l'application serveur Web pour Chrome, cliquez sur le raccourci des applications dans la barre de favoris:
Dans la fenêtre suivante, cliquez sur l'icône de serveur Web:
La boîte de dialogue suivante s'affiche. Elle vous permet de configurer votre serveur Web local:
Cliquez sur le bouton Choisir un dossier, puis sélectionnez la racine du dépôt cloné (ou désarchivé). Cela vous permettra de diffuser votre travail en cours via l'URL mise en surbrillance dans la boîte de dialogue du serveur Web (dans la section URL du ou des serveurs Web).
Sous "Options", cochez la case Afficher automatiquement index.html comme indiqué ci-dessous:
Accédez maintenant à votre site dans votre navigateur Web (en cliquant sur l'URL du serveur Web mise en surbrillance). Une page semblable à la suivante doit s'afficher:
Pour voir à quoi ressemble cette application sur votre téléphone Android, vous devez activer le débogage à distance sur Android et configurer le transfert de port (le numéro de port par défaut est 8887). Ensuite, il vous suffira d'ouvrir un nouvel onglet Chrome sur http://localhost:8887 sur votre téléphone Android.
Étape suivante
À ce stade, cette application Web ne fait pas grand-chose. Commençons à ajouter la compatibilité Bluetooth !
4. Découvrir la bougie
Nous allons commencer par écrire une bibliothèque qui utilise une classe ES2015 JavaScript pour l'appareil Bluetooth Candle PLAYBULB.
Restez calme. La syntaxe de la classe n'introduit pas un nouveau modèle d'héritage orienté objet dans JavaScript. Il fournit simplement une syntaxe beaucoup plus claire pour créer des objets et gérer l'héritage, comme vous pouvez le lire ci-dessous.
Tout d'abord, définissons une classe PlaybulbCandle
dans playbulbCandle.js
et créons une instance playbulbCandle
qui sera disponible ultérieurement dans le fichier app.js
.
playbulbCandle.js
(function() {
'use strict';
class PlaybulbCandle {
constructor() {
this.device = null;
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Pour demander l'accès à un appareil Bluetooth à proximité, nous devons appeler navigator.bluetooth.requestDevice
. Étant donné que l'appareil Candle PLAYBULB annonce en continu (s'il n'est pas déjà associé) un UUID constant du service GATT Bluetooth, connu sous sa forme abrégée 0xFF02
, nous pouvons simplement définir une constante et l'ajouter au paramètre des services de filtres dans une nouvelle méthode connect
publique de la classe PlaybulbCandle
.
Nous effectuerons également le suivi en interne de l'objet BluetoothDevice
afin de pouvoir y accéder ultérieurement si nécessaire. Comme navigator.bluetooth.requestDevice
renvoie une promesse JavaScript ES2015, nous le ferons dans la méthode 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();
})();
Pour des raisons de sécurité, la détection des appareils Bluetooth à proximité avec navigator.bluetooth.requestDevice
doit être appelée à l'aide d'un geste de l'utilisateur, comme une pression ou un clic de souris. C'est pourquoi nous appellerons la méthode connect
lorsque l'utilisateur clique sur le bouton "Connecter". dans le fichier 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);
});
});
Exécuter l'application
À ce stade, accédez à votre site dans votre navigateur Web (en cliquant sur l'URL du serveur Web mise en surbrillance dans l'application de serveur Web) ou actualisez simplement la page existante. Cliquez sur le bouton vert "Connecter" , choisissez l'appareil dans le sélecteur et ouvrez votre console d'outils de développement préférée à l'aide du raccourci clavier Ctrl+Maj+J. Vous remarquerez que l'objet BluetoothDevice
est enregistré.
Un message d'erreur peut s'afficher si le Bluetooth est désactivé et/ou si l'appareil Bluetooth Bougie PLAYBULB est désactivé. Dans ce cas, rallumez-la et réessayez.
Bonus obligatoire
Je ne sais pas pour vous, mais je vois déjà trop de function() {}
dans ce code. Passons plutôt aux fonctions fléchées JavaScript ES2015 () => {}
. Ils vous sauvegardaient toute la beauté des fonctions anonymes, sans la tristesse d'un lien.
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);
});
});
Étape suivante
- OK... puis-je parler à cette bougie ?
- Bien sûr... Passez à l'étape suivante.
Questions fréquentes
5. Lire quelque chose
Maintenant que vous avez obtenu un BluetoothDevice
renvoyé par la promesse de navigator.bluetooth.requestDevice
, que faire ? Connectez-vous au serveur GATT distant Bluetooth qui contient le service Bluetooth et les définitions des caractéristiques en appelant 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();
});
}
}
Lire le nom de l'appareil
Nous sommes connectés au serveur GATT de l'appareil Bluetooth Candle PLAYBULB. Nous voulons maintenant obtenir le service GATT principal (annoncé précédemment sous le nom 0xFF02
) et lire la caractéristique du nom de l'appareil (0xFFFF
) qui appartient à ce service. Pour ce faire, il vous suffit d'ajouter une nouvelle méthode getDeviceName
à la classe PlaybulbCandle
, et d'utiliser device.gatt.getPrimaryService
et service.getCharacteristic
. La méthode characteristic.readValue
renvoie un DataView
que nous allons simplement décoder avec 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);
});
}
Ajoutons cela à app.js
en appelant playbulbCandle.getDeviceName
une fois que nous sommes connectés et que nous avons affiché le nom de l'appareil.
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;
}
À ce stade, accédez à votre site dans votre navigateur Web (en cliquant sur l'URL du serveur Web mise en surbrillance dans l'application de serveur Web) ou actualisez simplement la page existante. Assurez-vous que la bougie PLAYBULB est allumée, puis cliquez sur le bouton sur la page. Vous devriez voir le nom de l'appareil sous le sélecteur de couleur.
Lire le niveau de la batterie
Une caractéristique Bluetooth de niveau de batterie standard est également disponible dans l'appareil Bluetooth PLAYBULB Candle. Elle indique le niveau de batterie de l'appareil. Cela signifie que nous pouvons utiliser des noms standards tels que battery_service
pour l'UUID du service GATT Bluetooth et battery_level
pour l'UUID caractéristique GATT Bluetooth.
Ajoutons une nouvelle méthode getBatteryLevel
à la classe PlaybulbCandle
et lisons le niveau de la batterie en pourcentage.
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));
}
Nous devons également mettre à jour l'objet JavaScript options
pour inclure le service de batterie sur la clé optionalServices
, car il n'est pas annoncé par l'appareil Bluetooth PLAYBULB Candle, mais il reste obligatoire pour y accéder.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Comme précédemment, connectons-le à app.js
en appelant playbulbCandle.getBatteryLevel
une fois que nous avons le nom de l'appareil et affiché le niveau de batterie.
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 + '%';
}
À ce stade, accédez à votre site dans votre navigateur Web (en cliquant sur l'URL du serveur Web mise en surbrillance dans l'application de serveur Web) ou actualisez simplement la page existante. Cliquez sur le bouton « Connecter » sur la page. Vous devriez voir le nom de l'appareil et le niveau de batterie.
Étape suivante
- Comment changer la couleur de cette ampoule ? C'est pour ça que je suis là !
- Vous y êtes presque, promis...
Questions fréquentes
6. Modifier la couleur
Pour modifier la couleur, il vous suffit d'écrire un ensemble spécifique de commandes pour une caractéristique Bluetooth (0xFFFC
) dans le service GATT principal annoncé comme 0xFF02
. Par exemple, si vous activez le rouge de votre bougie PLAYBULB, vous écrivez un tableau d'entiers non signés de 8 bits égaux à [0x00, 255, 0, 0]
, où 0x00
correspond à la saturation en blanc et 255, 0, 0
représentent respectivement les valeurs rouge, vert et bleu .
Nous utiliserons characteristic.writeValue
pour écrire des données dans la caractéristique Bluetooth dans la nouvelle méthode publique setColor
de la classe PlaybulbCandle
. Nous renvoyons également les valeurs rouge, verte et bleue réelles lorsque la promesse est remplie afin de pouvoir les utiliser ultérieurement dans 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]);
}
Mettons à jour la fonction changeColor
dans app.js
pour appeler playbulbCandle.setColor
lorsque "Aucun effet" est cochée. Les variables de couleur globales r, g, b
sont déjà définies lorsque l'utilisateur clique sur le canevas du sélecteur de couleur.
app.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
if (effect === 'noEffect') {
playbulbCandle.setColor(r, g, b).then(onColorChanged);
}
}
À ce stade, accédez à votre site dans votre navigateur Web (en cliquant sur l'URL du serveur Web mise en surbrillance dans l'application de serveur Web) ou actualisez simplement la page existante. Cliquez sur le bouton « Connecter » sur la page et cliquez sur le sélecteur de couleur pour changer la couleur de la bougie PLAYBULB autant de fois que vous le souhaitez.
Effets de bougie sur les bougies
Si vous avez déjà allumé une bougie, vous savez que la lumière n'est pas statique. Heureusement pour nous, il existe une autre caractéristique Bluetooth (0xFFFB
) dans le service GATT principal, annoncée en tant que 0xFF02
, qui permet à l'utilisateur de définir des effets bougie.
Régler un "effet bougie" par exemple, en écrivant [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]
. Vous pouvez aussi définir l'effet "clignotement" avec [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00]
.
Ajoutons les méthodes setCandleEffectColor
et setFlashingColor
à la 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]);
}
Mettons à jour la fonction changeColor
dans app.js
pour appeler playbulbCandle.setCandleEffectColor
lorsque l'effet Bougie est cochée et playbulbCandle.setFlashingColor
lorsque la case d'option "Clignotement" est cochée. Cette fois, nous utiliserons switch
si cela vous convient.
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;
}
}
À ce stade, accédez à votre site dans votre navigateur Web (en cliquant sur l'URL du serveur Web mise en surbrillance dans l'application de serveur Web) ou actualisez simplement la page existante. Cliquez sur le bouton « Connecter » sur la page et jouez avec les bougies et les effets de clignotement.
Étape suivante
- C'est tout ? 3 mauvais effets de bougies ? C'est pour ça que je suis ici ?
- Il y en a d'autres, mais vous serez tout seul cette fois-ci.
7. Allez plus loin
Nous y voilà ! Vous pensez peut-être qu'elle est presque terminée, mais l'application n'est pas encore terminée. Vérifions que vous avez bien compris ce que vous avez copié et collé au cours de cet atelier de programmation. Voici ce que vous souhaitez faire par vous-même pour mettre en valeur cette application.
Ajouter les effets manquants
Voici les données concernant les effets manquants:
- Pulsation:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00]
(vous voudrez peut-être régler les valeursr, g, b
à cet endroit) - Arc-en-ciel:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00]
(Les personnes épileptiques voudront peut-être éviter celui-ci.) - Fondu arc-en-ciel:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Cela signifie essentiellement ajouter de nouvelles méthodes setPulseColor
, setRainbow
et setRainbowFade
à la classe PlaybulbCandle
et les appeler dans changeColor
.
Corriger l'option "Aucun effet"
Comme vous l'avez peut-être remarqué, l'option "Aucun effet" ne réinitialise aucun effet en cours, c'est mineur, mais toujours. Résolvons à présent ce problème. Dans la méthode setColor
, vous devez d'abord vérifier si un effet est en cours via une nouvelle variable de classe _isEffectSet
et, si true
, désactiver l'effet avant de définir une nouvelle couleur avec les données suivantes: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00]
.
Saisir le nom de l'appareil
Celle-ci est facile ! Pour créer un nom d'appareil personnalisé, il vous suffit d'écrire la caractéristique précédente du nom de l'appareil Bluetooth. Je vous recommande d'utiliser la méthode encode
de TextEncoder
pour obtenir un Uint8Array
contenant le nom de l'appareil.
Ensuite, j'ajouterais
une « entrée » eventListener
à document.querySelector('#deviceName')
et appelez playbulbCandle.setDeviceName
pour simplifier les choses.
J'ai personnellement nommé ma BOUCHE PLAY💡 !
8. Et voilà !
Connaissances acquises
- Interagir avec un appareil Bluetooth à proximité en JavaScript
- Utiliser les classes ES2015, les fonctions fléchées, les cartes et les promesses
Étapes suivantes
- En savoir plus sur l'API Web Bluetooth
- Parcourez les exemples Web Bluetooth et les démonstrations officiels.
- Regardez le chat grincheux volant