Mengontrol lilin PLAYBULB dengan Web Bluetooth

1. Tentang apa ini?

IMG_19700101_023537~2~2.jpg

Dalam codelab yang telah dijelaskan ini, Anda akan mempelajari cara mengontrol lilin tanpa api tanpa LED PLAYBULB tanpa menggunakan apa pun selain JavaScript berkat Web Bluetooth API. Dalam prosesnya, Anda juga akan menggunakan 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

2. Mainkan terlebih dahulu

Anda mungkin ingin melihat versi final aplikasi yang akan dibuat di https://googlecodelabs.github.io/candle-bluetooth dan bermain dengan perangkat Bluetooth Lilin PLAYBULB yang Anda miliki sebelum benar-benar mendalami codelab ini.

Anda juga bisa melihat 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 mengunduh zip di sini:

atau dengan meng-clone repo 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 Anda belum menginstal aplikasi tersebut, Anda dapat menginstalnya dari Chrome Web Store.

Setelah menginstal aplikasi Server Web untuk Chrome, klik pintasan Aplikasi pada kolom bookmark:

Screenshot 16-11-2016 pukul 16.10.42.png

Pada jendela berikutnya, klik ikon Web Server:

9f3c21b2cf6cbfb5.png

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

Screenshot 16-11-2016 pukul 15.40.47.png

Klik tombol choose folder, dan pilih root repositori yang di-clone (atau tidak diarsipkan). Dengan begitu, Anda dapat menayangkan pekerjaan yang sedang berlangsung melalui URL yang ditandai dalam dialog server web (di bagian URL Server Web).

Di bawah Options, centang kotak di samping "Otomatis tampilkan index.html", seperti yang ditunjukkan di bawah:

Screenshot 16-11-2016 pukul 15.40.56.png

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

Screenshot 16-11-2016 pukul 15.20.22.png

Jika ingin melihat tampilan aplikasi ini di ponsel Android, Anda harus mengaktifkan Proses debug 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.

Berikutnya

Pada tahap ini, aplikasi web ini belum melakukan banyak hal. Mari mulai menambahkan dukungan Bluetooth.

4. Temukan lilin

Kita akan mulai dengan menulis library yang menggunakan Class ES2015 JavaScript untuk perangkat Bluetooth Lilin PLAYBULB.

Tetap tenang. Sintaksis class tidak memperkenalkan model pewarisan berorientasi objek baru ke JavaScript. Ini hanya menyediakan sintaks yang jauh lebih jelas untuk membuat objek dan menangani pewarisan, seperti yang dapat Anda baca di bawah ini.

Pertama, mari 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 Lilin PLAYBULB terus beriklan (jika belum dipasangkan) UUID Layanan GATT Bluetooth konstan yang dikenal dalam bentuk singkatnya sebagai 0xFF02, kita dapat dengan mudah menentukan konstanta dan menambahkannya ke parameter layanan filter dalam metode connect publik baru dari class PlaybulbCandle.

Kita juga akan melacak secara internal objek BluetoothDevice sehingga kita 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, menemukan perangkat Bluetooth di sekitar dengan navigator.bluetooth.requestDevice harus dipanggil melalui gestur pengguna seperti sentuhan atau klik mouse. Itulah mengapa kita akan memanggil metode connect saat pengguna mengklik "Hubungkan" tombol 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, kunjungi situs Anda di browser web (dengan mengklik URL Server Web yang disorot di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik tombol "Hubungkan" berwarna hijau pilih perangkat di pemilih dan buka konsol Dev Tools favorit dengan pintasan keyboard Ctrl + Shift + J dan perhatikan bahwa objek BluetoothDevice dicatat dalam log.

Screenshot 16-11-2016 pukul 15.27.12.png

Anda mungkin mengalami kesalahan jika Bluetooth nonaktif dan/atau perangkat bluetooth Lilin PLAYBULB nonaktif. Jika demikian, aktifkan dan lanjutkan lagi.

Bonus Wajib

Saya tidak tahu dengan Anda, tapi saya sudah melihat terlalu banyak function() {} dalam kode ini. Sebagai gantinya, mari kita beralih ke Fungsi Panah JavaScript ES2015 () => {}. Game ini sangat membantu: Semua kesenangan fungsi anonim, tanpa kesedihan yang mengikat.

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 bicara dengan lilin ini atau apa?

- Tentu... langsung ke langkah berikutnya

Pertanyaan Umum (FAQ)

5. Baca sesuatu

Jadi, apa yang Anda lakukan sekarang setelah memiliki BluetoothDevice yang ditampilkan dari promise navigator.bluetooth.requestDevice? Mari hubungkan ke Server GATT jarak jauh 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 Lilin PLAYBULB. Sekarang kita ingin mendapatkan Layanan GATT Utama (yang diiklankan sebagai 0xFF02 sebelumnya) dan membaca karakteristik nama perangkat (0xFFFF) yang dimiliki layanan ini. Hal ini dapat dilakukan dengan mudah dengan menambahkan metode baru getDeviceName ke class PlaybulbCandle serta menggunakan device.gatt.getPrimaryService dan service.getCharacteristic. Metode characteristic.readValue benar-benar akan menampilkan DataView yang cukup 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 tambahkan ke app.js dengan memanggil playbulbCandle.getDeviceName setelah 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, kunjungi situs Anda di browser web (dengan mengklik URL Server Web yang disorot di aplikasi server web) atau cukup muat ulang halaman yang ada. Pastikan Lilin PLAYBULB diaktifkan, lalu klik "Sambungkan" pada halaman dan Anda akan melihat nama perangkat di bawah pemilih warna.

Screenshot 16-11-2016 pukul 15.29.21.png

Membaca level baterai

Ada juga karakteristik Bluetooth tingkat baterai standar yang tersedia di perangkat Bluetooth Lilin PLAYBULB 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 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 tidak diiklankan oleh perangkat Bluetooth Lilin PLAYBULB 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 colokkan 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, kunjungi situs Anda di browser web (dengan mengklik URL Server Web yang ditandai di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik "Hubungkan" pada halaman dan Anda akan melihat nama perangkat dan level baterai.

Screenshot 16-11-2016 pukul 15.29.21.png

Berikutnya

- Bagaimana cara mengubah warna bohlam ini? Karena itulah aku di sini!

- Sedikit lagi, aku berjanji...

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 Lilin PLAYBULB menjadi merah akan menulis array yang terdiri dari 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 benar-benar menulis beberapa data ke karakteristik Bluetooth dalam metode publik setColor yang 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 "No Effect" tombol pilihan 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, kunjungi situs Anda di browser web (dengan mengklik URL Server Web yang disorot di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik "Hubungkan" pada halaman dan klik pemilih warna untuk mengubah warna Lilin PLAYBULB sebanyak yang Anda inginkan.

Screenshot 16-11-2016 pukul 15.31.37.png

Efek lilin bulan purnama

Jika Anda sudah menyalakan lilin sebelumnya, Anda tahu bahwa lampunya tidak statis. Untungnya, ada karakteristik Bluetooth lain (0xFFFB) di Layanan GATT Utama yang diiklankan sebagai 0xFF02 yang memungkinkan pengguna menetapkan beberapa efek lilin.

Menyetel "efek lilin" misalnya dapat dicapai dengan menulis [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]. Dan Anda juga bisa mengatur 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]);
    }

Dan mari kita update fungsi changeColor di app.js untuk memanggil playbulbCandle.setCandleEffectColor saat "Efek Lilin" tombol pilihan dicentang dan playbulbCandle.setFlashingColor bila "Berkedip" tombol pilihan 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, kunjungi situs Anda di browser web (dengan mengklik URL Server Web yang disorot di aplikasi server web) atau cukup muat ulang halaman yang ada. Klik "Hubungkan" di halaman dan bereksperimenlah dengan Efek Lilin dan Berkedip.

Screenshot 16-11-2016 pukul 15.33.23.png

Berikutnya

- Itu saja? 3 efek lilin yang buruk? Apakah karena itulah saya di sini?

- Ada lebih banyak lagi, tetapi Anda akan menentukan sendiri kali ini.

7. Lakukan upaya lebih

Jadi, inilah kita. Anda mungkin berpikir bahwa ini sudah hampir berakhir tetapi aplikasi ini belum berakhir. Mari kita lihat apakah Anda benar-benar memahami apa yang telah Anda salin-tempel selama codelab ini. Berikut yang ingin Anda lakukan sekarang untuk membuat aplikasi ini tampil menarik.

Menambahkan efek yang tidak ada

Berikut adalah data untuk efek yang hilang:

  • Pulse: [0x00, r, g, b, 0x01, 0x00, 0x09, 0x00] (Anda mungkin ingin menyesuaikan nilai r, g, b di sana)
  • Pelangi: [0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00] (Penderita epilepsi mungkin ingin menghindari pelangi ini)
  • Pudar Pelangi: [0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]

Ini pada dasarnya berarti menambahkan metode setPulseColor, setRainbow, dan setRainbowFade baru ke class PlaybulbCandle dan memanggilnya di changeColor.

Memperbaiki "tidak berpengaruh"

Anda mungkin telah memperhatikan, "tidak ada efek" opsi ini tidak mengatur ulang efek yang sedang berlangsung, ini kecil, namun tetap saja. Mari kita perbaiki. Dalam metode setColor, Anda harus memeriksa terlebih dahulu apakah suatu efek sedang berlangsung melalui variabel class baru _isEffectSet dan jika true, nonaktifkan efek tersebut sebelum menetapkan warna baru dengan data ini: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00].

Tulis nama perangkat

Yang ini mudah! Menulis nama perangkat khusus 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 panggil playbulbCandle.setDeviceName agar lebih praktis.

Saya sendiri menamainya 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