1. Tentang apa ini?

Dalam codelab ini, Anda akan mempelajari cara mengontrol lilin tanpa api LED PLAYBULB hanya dengan JavaScript berkat Web Bluetooth API. Selama proses ini, Anda juga akan menggunakan fitur JavaScript ES2015 seperti Classes, Arrow functions, Map, dan Promises.
Yang akan Anda pelajari
- Cara berinteraksi dengan perangkat Bluetooth di sekitar dalam JavaScript
- Cara menggunakan Class ES2015, fungsi Arrow, Map, dan Promise
Yang Anda butuhkan
- Pemahaman dasar tentang pengembangan web
- Pengetahuan dasar tentang Bluetooth Hemat Energi (BLE) dan Profil Atribut Generik (GATT)
- Editor teks pilihan Anda
- Mac, Chromebook, atau Perangkat Android M dengan Aplikasi Browser Chrome dan kabel USB mikro ke USB.
2. Putar terlebih dahulu
Anda dapat melihat versi akhir aplikasi yang akan Anda buat di https://googlecodelabs.github.io/candle-bluetooth dan mencoba perangkat Bluetooth PLAYBULB Candle yang Anda miliki sebelum benar-benar mempelajari codelab ini.
Anda juga dapat menonton saya mengubah warna di https://www.youtube.com/watch?v=fBCPA9gIxlU
3. Memulai persiapan
Download kode contoh
Anda bisa mendapatkan kode contoh untuk kode ini dengan mendownload zip di sini:
atau dengan meng-clone repositori git ini:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Jika Anda mendownload sumber sebagai zip, mengekstraknya akan memberi Anda folder root candle-bluetooth-master.
Menginstal dan memverifikasi server web
Meskipun Anda bebas menggunakan server web Anda sendiri, codelab ini dirancang agar berfungsi dengan baik dengan Server Web Chrome. Jika aplikasi tersebut belum diinstal, Anda dapat menginstalnya dari Chrome Web Store.
Setelah menginstal aplikasi Web Server untuk Chrome, klik pintasan Aplikasi di kolom bookmark:

Di jendela berikutnya, klik ikon Server Web:

Anda akan melihat dialog ini berikutnya, yang memungkinkan Anda mengonfigurasi server web lokal:

Klik tombol pilih folder, lalu pilih root repo yang di-clone (atau diekstrak). Tindakan ini memungkinkan Anda menyalurkan pekerjaan yang sedang berlangsung melalui URL yang ditandai dalam dialog server web (di bagian URL Server Web).
Di bagian Opsi, centang kotak di samping "Tampilkan index.html secara otomatis", seperti yang ditunjukkan di bawah:

Sekarang, buka situs Anda di browser web (dengan mengklik URL Server Web yang ditandai) dan Anda akan melihat halaman yang terlihat seperti ini:

Jika ingin melihat tampilan aplikasi ini di ponsel Android, Anda harus mengaktifkan Penelusuran bug jarak jauh di Android dan menyiapkan Penerusan port (nomor port secara default adalah 8887). Setelah itu, Anda cukup membuka tab Chrome baru ke http://localhost:8887 di ponsel Android Anda.
Berikutnya
Pada tahap ini, aplikasi web ini tidak melakukan banyak hal. Mari mulai menambahkan dukungan Bluetooth.
4. Temukan lilin
Kita akan mulai dengan menulis library yang menggunakan Class JavaScript ES2015 untuk perangkat Bluetooth PLAYBULB Candle.
Tetap tenang. Sintaksis class tidak memperkenalkan model pewarisan berorientasi objek baru ke JavaScript. Hal ini hanya memberikan sintaksis yang jauh lebih jelas untuk membuat objek dan menangani pewarisan, seperti yang dapat Anda baca di bawah.
Pertama, mari kita tentukan class PlaybulbCandle di playbulbCandle.js dan buat instance playbulbCandle yang akan tersedia di file app.js nanti.
playbulbCandle.js
(function() {
'use strict';
class PlaybulbCandle {
constructor() {
this.device = null;
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Untuk meminta akses ke perangkat Bluetooth di sekitar, kita perlu memanggil navigator.bluetooth.requestDevice. Karena perangkat PLAYBULB Candle terus mengiklankan (jika belum disambungkan) UUID Layanan GATT Bluetooth konstan yang dikenal dalam bentuk singkatnya sebagai 0xFF02, kita dapat menentukan konstanta dan menambahkannya ke parameter layanan filter dalam metode connect publik baru dari class PlaybulbCandle.
Kita juga akan melacak objek BluetoothDevice secara internal sehingga kita dapat mengaksesnya nanti jika diperlukan. Karena navigator.bluetooth.requestDevice menampilkan JavaScript ES2015 Promise, kita akan melakukannya dalam metode 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();
})();
Sebagai fitur keamanan, penemuan perangkat Bluetooth di sekitar dengan navigator.bluetooth.requestDevice harus dipanggil melalui gestur pengguna seperti sentuhan atau klik mouse. Itulah sebabnya kita akan memanggil metode connect saat pengguna mengklik tombol "Connect" di 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);
});
});
Menjalankan aplikasi
Pada tahap ini, buka situs Anda di browser web (dengan mengklik URL Server Web yang ditandai di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik tombol "Connect" berwarna hijau, pilih perangkat di pemilih, lalu buka konsol Alat Dev favorit Anda dengan pintasan keyboard Ctrl + Shift + J dan perhatikan objek BluetoothDevice yang dicatat.

Anda mungkin mendapatkan error jika Bluetooth nonaktif dan/atau perangkat Bluetooth PLAYBULB Candle nonaktif. Jika demikian, aktifkan dan lanjutkan lagi.
Bonus Wajib
Saya tidak tahu bagaimana dengan Anda, tetapi saya sudah melihat terlalu banyak function() {} dalam kode ini. Mari beralih ke () => {} JavaScript ES2015 Arrow Functions. Fungsi ini sangat membantu: Semua keindahan fungsi anonim, tanpa kesedihan pengikatan.
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);
});
});
Berikutnya
- Oke... bisakah saya berbicara dengan lilin ini atau bagaimana?
- Tentu... lanjutkan ke langkah berikutnya
Pertanyaan Umum (FAQ)
5. Membaca sesuatu
Jadi, apa yang harus Anda lakukan setelah mendapatkan BluetoothDevice yang dikembalikan dari janji navigator.bluetooth.requestDevice? Mari kita hubungkan ke Server GATT remote Bluetooth yang menyimpan definisi layanan dan karakteristik Bluetooth dengan memanggil 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();
});
}
}
Membaca nama perangkat
Di sini kita terhubung ke Server GATT perangkat Bluetooth PLAYBULB Candle. Sekarang kita ingin mendapatkan Layanan GATT Utama (sebelumnya diiklankan sebagai 0xFF02) dan membaca karakteristik nama perangkat (0xFFFF) yang termasuk dalam layanan ini. Hal ini dapat dilakukan dengan mudah dengan menambahkan metode getDeviceName baru ke class PlaybulbCandle dan menggunakan device.gatt.getPrimaryService dan service.getCharacteristic. Metode characteristic.readValue sebenarnya akan menampilkan DataView yang akan kita dekode dengan 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);
});
}
Mari kita tambahkan ini ke app.js dengan memanggil playbulbCandle.getDeviceName setelah kita terhubung dan menampilkan nama perangkat.
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;
}
Pada tahap ini, buka situs Anda di browser web (dengan mengklik URL Server Web yang ditandai di aplikasi server web) atau cukup muat ulang halaman yang ada. Pastikan PLAYBULB Candle dinyalakan, lalu klik tombol "Connect" di halaman dan Anda akan melihat nama perangkat di bawah pemilih warna.

Membaca level baterai
Ada juga karakteristik Bluetooth level baterai standar yang tersedia di perangkat Bluetooth PLAYBULB Candle yang berisi level baterai perangkat. Artinya, kita dapat menggunakan nama standar seperti battery_service untuk UUID Layanan GATT Bluetooth dan battery_level untuk UUID Karakteristik GATT Bluetooth.
Mari kita tambahkan metode getBatteryLevel baru ke class PlaybulbCandle dan baca level baterai dalam persentase.
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));
}
Kita juga perlu mengupdate objek JavaScript options untuk menyertakan layanan baterai ke kunci optionalServices karena tidak diiklankan oleh perangkat Bluetooth PLAYBULB Candle, tetapi tetap wajib diakses.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Seperti sebelumnya, mari kita hubungkan ini ke app.js dengan memanggil playbulbCandle.getBatteryLevel setelah kita mendapatkan nama perangkat dan menampilkan level baterai.
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 + '%';
}
Pada tahap ini, buka situs Anda di browser web (dengan mengklik URL Server Web yang ditandai di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik tombol "Hubungkan" di halaman tersebut dan Anda akan melihat nama perangkat dan level baterai.
Berikutnya
- Bagaimana cara mengubah warna bohlam ini? Itulah sebabnya saya di sini!
- Anda hampir selesai, saya jamin...
Pertanyaan Umum (FAQ)
6. Mengubah warna
Mengubah warna semudah menulis serangkaian perintah tertentu ke Karakteristik Bluetooth (0xFFFC) di Layanan GATT Utama yang diiklankan sebagai 0xFF02. Misalnya, mengubah PLAYBULB Candle Anda menjadi merah akan menulis array bilangan bulat tidak bertanda 8-bit yang sama dengan [0x00, 255, 0, 0] dengan 0x00 adalah saturasi putih dan 255, 0, 0 masing-masing adalah nilai merah, hijau, dan biru .
Kita akan menggunakan characteristic.writeValue untuk benar-benar menulis beberapa data ke karakteristik Bluetooth dalam metode publik setColor baru dari class PlaybulbCandle. Selain itu, kita juga akan menampilkan nilai merah, hijau, dan biru yang sebenarnya saat promise terpenuhi sehingga kita dapat menggunakannya di app.js nanti:
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]);
}
Mari kita perbarui fungsi changeColor di app.js untuk memanggil playbulbCandle.setColor saat tombol pilihan "No Effect" dicentang. Variabel warna r, g, b global sudah ditetapkan saat pengguna mengklik kanvas pemilih warna.
app.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
if (effect === 'noEffect') {
playbulbCandle.setColor(r, g, b).then(onColorChanged);
}
}
Pada tahap ini, buka situs Anda di browser web (dengan mengklik URL Server Web yang ditandai di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik tombol "Hubungkan" di halaman dan klik pemilih warna untuk mengubah warna PLAYBULB Candle sesering yang Anda inginkan.
Lebih banyak efek lilin
Jika Anda pernah menyalakan lilin sebelumnya, Anda tahu bahwa cahayanya tidak statis. Untungnya, ada karakteristik Bluetooth lain (0xFFFB) di Layanan GATT Utama yang diiklankan sebagai 0xFF02 yang memungkinkan pengguna menyetel beberapa efek lilin.
Misalnya, Anda dapat menyetel "efek lilin" dengan menulis [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]. Anda juga dapat menyetel "efek berkedip" dengan [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00].
Mari kita tambahkan metode setCandleEffectColor dan setFlashingColor ke class 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]);
}
Kemudian, perbarui fungsi changeColor di app.js untuk memanggil playbulbCandle.setCandleEffectColor saat tombol pilihan "Candle Effect" dicentang dan playbulbCandle.setFlashingColor saat tombol pilihan "Flashing" dicentang. Kali ini, kita akan menggunakan switch jika Anda setuju.
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;
}
}
Pada tahap ini, buka situs Anda di browser web (dengan mengklik URL Server Web yang ditandai di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik tombol "Hubungkan" di halaman dan mainkan Efek Lilin dan Berkedip.
Berikutnya
- Hanya itu? 3 efek lilin yang buruk? Apakah ini alasan saya berada di sini?
- Ada lebih banyak lagi, tetapi kali ini Anda harus mencari sendiri.
7. Lakukan upaya lebih
Jadi, inilah kami! Anda mungkin mengira ini hampir berakhir, tetapi aplikasi belum selesai. Mari kita lihat apakah Anda benar-benar memahami apa yang telah Anda salin dan tempel selama codelab ini. Berikut hal-hal yang dapat Anda lakukan sendiri sekarang untuk membuat aplikasi ini lebih menarik.
Menambahkan efek yang tidak ada
Berikut data untuk efek yang tidak ada:
- Pulsa:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00](Anda mungkin ingin menyesuaikan nilair, g, bdi sana) - Pelangi:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00](Penderita epilepsi sebaiknya menghindari yang ini) - Pudar Pelangi:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Pada dasarnya, ini berarti menambahkan metode setPulseColor, setRainbow, dan setRainbowFade baru ke class PlaybulbCandle dan memanggilnya di changeColor.
Memperbaiki "tidak ada efek"
Seperti yang mungkin telah Anda perhatikan, opsi "tidak ada efek" tidak mereset efek yang sedang berlangsung, ini memang kecil, tetapi tetap saja. Mari kita perbaiki. Dalam metode setColor, Anda harus memeriksa terlebih dahulu apakah efek sedang berlangsung melalui variabel class baru _isEffectSet dan jika true, nonaktifkan efek sebelum menyetel warna baru dengan data ini: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00].
Tulis nama perangkat
Yang ini mudah! Menulis nama perangkat kustom sama sederhananya dengan menulis ke karakteristik nama perangkat Bluetooth sebelumnya. Sebaiknya gunakan metode TextEncoder encode untuk mendapatkan Uint8Array yang berisi nama perangkat.
Kemudian, saya akan menambahkan eventListener "input" ke document.querySelector('#deviceName') dan memanggil playbulbCandle.setDeviceName agar tetap sederhana.
Saya sendiri menamai milik saya PLAY💡 CANDLE!
8. Selesai!
Yang telah Anda pelajari
- Cara berinteraksi dengan perangkat Bluetooth di sekitar dalam JavaScript
- Cara menggunakan Class ES2015, fungsi Arrow, Map, dan Promise
Langkah Berikutnya
- Pelajari lebih lanjut Web Bluetooth API
- Jelajahi Sampel Web Bluetooth dan Demo resmi
- Lihat kucing pemarah yang terbang

