1. Tentang apa ini?

Dalam codelab yang mencerahkan ini, Anda akan mempelajari cara mengontrol lilin tanpa api LED PLAYBULB hanya dengan JavaScript berkat Web Bluetooth API. Selama prosesnya, Anda juga akan mencoba fitur JavaScript ES2015 seperti Class, Fungsi panah, Peta, dan Promise.
Yang akan Anda pelajari
- Cara berinteraksi dengan perangkat Bluetooth di sekitar di JavaScript
- Cara menggunakan Class ES2015, Fungsi panah, 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 pertama
Anda mungkin ingin melihat versi final 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 melihat saya berubah warna di https://www.youtube.com/watch?v=fBCPA9gIxlU
3. Memulai persiapan
Mendownload kode contoh
Anda bisa mendapatkan kode contoh untuk kode ini dengan mendownload file ZIP di sini:
atau dengan meng-clone repositori git ini:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Jika Anda mendownload sumber sebagai file 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 Chrome Web Server. Jika aplikasi tersebut belum diinstal, Anda dapat menginstalnya dari Chrome Web Store.
Setelah menginstal aplikasi Web Server for 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 choose folder, lalu pilih root repo yang di-clone (atau diarsipkan). 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 Proses debug jarak jauh di Android dan menyiapkan Penerusan port (nomor port 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 belum melakukan banyak hal. Mari kita mulai menambahkan dukungan Bluetooth.
4. Temukan lilinnya
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. Class hanya menyediakan 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-menerus memberitahukan (jika belum disambungkan) UUID Layanan GATT Bluetooth konstan yang dikenal dalam bentuk singkatnya sebagai 0xFF02, kita cukup menentukan konstanta dan menambahkan ini ke parameter layanan filter dalam metode connect publik baru dari class PlaybulbCandle.
Kami juga akan melacak objek BluetoothDevice secara internal sehingga kami dapat mengaksesnya nanti jika diperlukan. Karena navigator.bluetooth.requestDevice menampilkan Promise JavaScript ES2015, 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. Oleh karena itu, 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, dan buka konsol Dev Tools favorit Anda dengan pintasan keyboard Ctrl + Shift + J, lalu perhatikan objek BluetoothDevice yang dicatat ke dalam log.

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 kita beralih ke Fungsi Panah JavaScript ES2015 () => {}. 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... apa aku bisa bicara 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 ditampilkan dari promise navigator.bluetooth.requestDevice? Mari kita hubungkan ke Server GATT remote Bluetooth yang menyimpan definisi karakteristik dan layanan 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 (yang sebelumnya diiklankan sebagai 0xFF02) dan membaca karakteristik nama perangkat (0xFFFF) yang termasuk dalam layanan ini. Hal ini dapat dilakukan dengan mudah dengan menambahkan metode baru getDeviceName 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 diaktifkan, lalu klik tombol "Hubungkan" 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 persen.
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 memperbarui objek JavaScript options untuk menyertakan layanan baterai ke kunci optionalServices karena layanan ini tidak diiklankan oleh perangkat Bluetooth PLAYBULB Candle, tetapi masih wajib untuk mengaksesnya.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Seperti sebelumnya, mari kita masukkan ini ke app.js dengan memanggil playbulbCandle.getBatteryLevel setelah kita memiliki 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 dan Anda akan melihat nama perangkat dan level baterai.
Berikutnya
- Bagaimana cara mengubah warna bohlam ini? Itulah sebabnya saya di sini.
- Anda hampir selesai, kami jamin...
Pertanyaan Umum (FAQ)
6. Mengubah warna
Mengubah warna semudah menulis kumpulan perintah tertentu ke Karakteristik Bluetooth (0xFFFC) di Layanan GATT Utama yang diiklankan sebagai 0xFF02. Misalnya, mengubah PLAYBULB Candle menjadi merah akan menulis array bilangan bulat tanpa tanda tangan 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 menulis beberapa data ke karakteristik Bluetooth dalam metode publik setColor baru dari class PlaybulbCandle. 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 update 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 "Connect" di halaman dan klik pemilih warna untuk mengubah warna PLAYBULB Candle sebanyak yang Anda inginkan.
Efek lilin lainnya
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, menyetel "efek lilin" dapat dilakukan dengan menulis [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]. Anda juga dapat menyetel "efek kedipan" dengan [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00].
Mari 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]);
}
Mari kita 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, kami akan menggunakan switch jika Anda tidak keberatan.
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 "Connect" di halaman dan mainkan Efek Lilin dan Berkedip.
Berikutnya
- Itu saja? 3 efek lilin yang buruk? Apakah ini alasan saya di sini?
- Masih ada lagi, tetapi kali ini Anda harus melakukannya sendiri.
7. Lakukan upaya tambahan
Jadi, inilah kita. 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 yang perlu Anda lakukan sendiri sekarang untuk membuat aplikasi ini menarik.
Menambahkan efek yang tidak ada
Berikut data untuk efek yang tidak ada:
- Pulse:
[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 mungkin ingin menghindari yang satu ini) - Pudar Pelangi:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
Hal ini pada dasarnya berarti menambahkan metode setPulseColor, setRainbow, dan setRainbowFade baru ke class PlaybulbCandle dan memanggilnya di changeColor.
Memperbaiki "tidak ada efek"
Seperti yang mungkin Anda perhatikan, opsi "tanpa efek" tidak mereset efek apa pun yang sedang berlangsung, ini adalah masalah 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
Ini mudah. Menulis nama perangkat kustom semudah menulis ke karakteristik nama perangkat Bluetooth sebelumnya. Sebaiknya gunakan metode TextEncoder encode untuk mendapatkan Uint8Array yang berisi nama perangkat.
Kemudian, saya akan menambahkan "input" eventListener ke document.querySelector('#deviceName') dan memanggil playbulbCandle.setDeviceName agar tetap sederhana.
Saya pribadi menamai lilin saya PLAY💡 CANDLE!
8. Selesai!
Yang telah Anda pelajari
- Cara berinteraksi dengan perangkat Bluetooth di sekitar di JavaScript
- Cara menggunakan Class ES2015, Fungsi panah, Map, dan Promise
Langkah Berikutnya
- Pelajari lebih lanjut Web Bluetooth API
- Jelajahi Contoh dan Demo Web Bluetooth resmi
- Lihat kucing pemarah terbang

