Mengontrol lilin PLAYBULB dengan Web Bluetooth

1. Tentang apa ini?

IMG_19700101_023537~2~2.jpg

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

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:

Screen Shot 2016-11-16 at 4.10.42 PM.png

Di jendela berikutnya, klik ikon Server Web:

9f3c21b2cf6cbfb5.png

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

Screen Shot 2016-11-16 at 3.40.47 PM.png

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:

Screen Shot 2016-11-16 at 3.40.56 PM.png

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

Screen Shot 2016-11-16 at 3.20.22 PM.png

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.

Screen Shot 2016-11-16 at 3.27.12 PM.png

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.

Screen Shot 2016-11-16 at 3.29.21 PM.png

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.

Screen Shot 2016-11-16 at 3.29.21 PM.png

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.

Screen Shot 2016-11-16 at 3.31.37 PM.png

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.

Screen Shot 2016-11-16 at 3.33.23 PM.png

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 nilai r, g, b di 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