Memulai Web Serial API

1. Pengantar

Terakhir diperbarui: 19-09-2022

Yang akan Anda bangun

Dalam codelab ini, Anda akan membuat halaman web yang menggunakan Web Serial API untuk berinteraksi dengan board BBC micro:bit untuk menampilkan gambar pada matriks LED 5x5. Anda akan mempelajari Web Serial API dan cara menggunakan streaming yang dapat dibaca, ditulis, dan diubah untuk berkomunikasi dengan perangkat serial melalui browser.

67543f4caaaca5de.pngS

Yang akan Anda pelajari

  • Cara membuka dan menutup port Serial Web
  • Cara menggunakan loop baca untuk menangani data dari aliran input
  • Cara mengirim data melalui aliran tulis

Yang Anda butuhkan

Kami memilih untuk menggunakan micro:bit v1 untuk codelab ini karena harganya terjangkau, menawarkan beberapa input (tombol) dan output (layar LED 5x5), serta dapat memberikan input dan output tambahan. Lihat halaman BBC micro:bit di situs Espruino untuk mengetahui detail tentang kemampuan micro:bit.

2. Tentang Web Serial API

Web Serial API menyediakan cara bagi situs untuk membaca dan menulis ke perangkat serial dengan skrip. API menjembatani web dan dunia fisik dengan memungkinkan situs berkomunikasi dengan perangkat serial, seperti mikrokontroler dan printer 3D.

Ada banyak contoh perangkat lunak kontrol yang sedang dibangun menggunakan teknologi web. Contoh:

Dalam beberapa kasus, situs web ini berkomunikasi dengan perangkat melalui aplikasi agen bawaan yang diinstal secara manual oleh pengguna. Pada kasus lain, aplikasi dikirimkan dalam aplikasi native yang dipaketkan melalui framework seperti Electron. Pada kasus lain, pengguna diminta melakukan langkah tambahan, seperti menyalin aplikasi yang telah dikompilasi ke perangkat dengan flash drive USB.

Pengalaman pengguna dapat ditingkatkan dengan menyediakan komunikasi langsung antara situs dan perangkat yang dikontrolnya.

3. Mempersiapkan

Mendapatkan kode

Kami telah memasukkan semua yang Anda perlukan untuk codelab ini ke dalam project Glitch.

  1. Buka tab browser baru, lalu buka https://web-serial-codelab-start.glitch.me/.
  2. Klik link Remix Glitch untuk membuat project awal versi Anda sendiri.
  3. Klik tombol Show, lalu pilih In a New Window untuk melihat cara kerja kode.

4. Membuka koneksi serial

Memeriksa apakah Web Serial API didukung

Hal pertama yang harus dilakukan adalah memeriksa apakah Web Serial API didukung di browser saat ini. Untuk melakukannya, periksa apakah serial ada di navigator.

Di peristiwa DOMContentLoaded, tambahkan kode berikut ke project Anda:

script.js - DOMContentLoaded

// CODELAB: Add feature detection here.
const notSupported = document.getElementById('notSupported');
notSupported.classList.toggle('hidden', 'serial' in navigator);

Tindakan ini akan memeriksa apakah Seri Web didukung. Jika didukung, kode ini akan menyembunyikan banner yang menyatakan bahwa Serial Web tidak didukung.

Cobalah

  1. Muat halaman.
  2. Pastikan halaman tidak menampilkan banner merah yang menyatakan bahwa Seri Web tidak didukung.

Membuka port serial

Selanjutnya, kita perlu membuka port serial. Seperti kebanyakan API modern lainnya, Web Serial API asinkron. Hal ini mencegah UI memblokir saat menunggu input, tetapi juga penting karena data serial dapat diterima oleh halaman web kapan saja, dan kita memerlukan cara untuk memprosesnya.

Karena komputer mungkin memiliki beberapa perangkat serial, browser akan meminta pengguna untuk memilih perangkat yang akan dihubungkan saat mencoba meminta port.

Tambahkan kode berikut ke project Anda:

script.js - connect()

// CODELAB: Add code to request & open port here.
// - Request a port and open a connection.
port = await navigator.serial.requestPort();
// - Wait for the port to open.
await port.open({ baudRate: 9600 });

Panggilan requestPort akan meminta pengguna memilih perangkat yang ingin mereka hubungkan. Memanggil port.open akan membuka port. Kita juga perlu memberikan kecepatan komunikasi yang diinginkan dengan perangkat serial. BBC micro:bit menggunakan koneksi 9600 baud antara chip USB-ke-serial dan prosesor utama.

Mari kita hubungkan juga tombol hubungkan dan minta tombol tersebut memanggil connect() saat pengguna mengkliknya.

Tambahkan kode berikut ke project Anda:

script.js - clickConnect()

// CODELAB: Add connect code here.
await connect();

Cobalah

Sekarang, project kita hanya memerlukan sedikit waktu untuk memulai. Mengklik tombol Connect akan meminta pengguna untuk memilih perangkat serial yang akan dihubungkan, lalu terhubung ke micro:bit.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Pada tab, Anda akan melihat ikon yang menunjukkan bahwa Anda telah terhubung ke perangkat serial:

e695daf2277cd3a2.png

Menyiapkan aliran data input untuk memproses data dari port serial

Setelah koneksi dibuat, kita perlu menyiapkan aliran input dan pembaca untuk membaca data dari perangkat. Pertama, kita akan mendapatkan streaming yang dapat dibaca dari port dengan memanggil port.readable. Karena kita tahu bahwa kita akan mendapatkan teks kembali dari perangkat, kita akan menyalurkannya melalui decoder teks. Selanjutnya, kita akan mendapatkan pembaca dan memulai loop baca.

Tambahkan kode berikut ke project Anda:

script.js - connect()

// CODELAB: Add code to read the stream here.
let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable;

reader = inputStream.getReader();
readLoop();

Loop baca adalah fungsi asinkron yang berjalan dalam loop dan menunggu konten tanpa memblokir thread utama. Saat data baru masuk, pembaca akan menampilkan dua properti: boolean value dan done. Jika done benar, berarti port telah ditutup atau tidak ada lagi data yang masuk.

Tambahkan kode berikut ke project Anda:

script.js - readLoop()

// CODELAB: Add read loop here.
while (true) {
  const { value, done } = await reader.read();
  if (value) {
    log.textContent += value + '\n';
  }
  if (done) {
    console.log('[readLoop] DONE', done);
    reader.releaseLock();
    break;
  }
}

Cobalah

Project kita sekarang dapat terhubung ke perangkat dan akan menambahkan data apa pun yang diterima dari perangkat ke elemen log.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Anda akan melihat logo Espruino:

dd52b5c37fc4b393.png

Menyiapkan streaming output untuk mengirim data ke port serial

Komunikasi serial biasanya dua arah. Selain menerima data dari port serial, kita juga ingin mengirim data ke port tersebut. Seperti streaming input, kita hanya akan mengirim teks melalui stream output ke micro:bit.

Pertama, buat streaming encoder teks dan transmisikan streaming ke port.writeable.

script.js - connect()

// CODELAB: Add code setup the output stream here.
const encoder = new TextEncoderStream();
outputDone = encoder.readable.pipeTo(port.writable);
outputStream = encoder.writable;

Saat terhubung melalui serial dengan firmware Espruino, board micro:bit BBC bertindak sebagai read-eval-print loop (REPL) JavaScript, mirip dengan yang Anda dapatkan di shell Node.js. Selanjutnya, kita perlu menyediakan metode untuk mengirimkan data ke aliran data. Kode di bawah mendapatkan penulis dari aliran output, lalu menggunakan write untuk mengirim setiap baris. Setiap baris yang dikirim berisi karakter baris baru (\n) untuk memberi tahu micro:bit agar mengevaluasi perintah yang dikirim.

script.js - writeToStream()

// CODELAB: Write to output stream
const writer = outputStream.getWriter();
lines.forEach((line) => {
  console.log('[SEND]', line);
  writer.write(line + '\n');
});
writer.releaseLock();

Untuk menempatkan sistem ke dalam status yang diketahui dan menghentikannya agar tidak menggemakan kembali karakter yang kita kirimkan, kita perlu mengirim CTRL-C dan menonaktifkan echo.

script.js - connect()

// CODELAB: Send CTRL-C and turn off echo on REPL
writeToStream('\x03', 'echo(false);');

Cobalah

Project kita sekarang dapat mengirim dan menerima data dari micro:bit. Mari pastikan kita dapat mengirim perintah dengan benar:

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Buka tab Konsol di Chrome DevTools, dan ketik writeToStream('console.log("yes")');

Anda akan melihat sesuatu seperti yang dicetak di halaman:

15e2df0064b5de28.pngS

5. Mengontrol matriks LED

Membuat string petak matriks

Untuk mengontrol matriks LED pada mikro:bit, kita perlu memanggil show(). Metode ini menampilkan grafis pada layar LED 5x5 bawaan. Operasi ini menggunakan bilangan biner atau {i>string<i}.

Kita akan mengiterasi kotak centang dan menghasilkan array 1 dan 0 yang menunjukkan mana yang dicentang dan mana yang tidak. Kemudian kita perlu membalikkan array, karena urutan kotak centang adalah kebalikan dari urutan LED dalam matriks. Selanjutnya, kita mengonversi array menjadi string dan membuat perintah untuk dikirim ke micro:bit.

script.js - sendGrid()

// CODELAB: Generate the grid
const arr = [];
ledCBs.forEach((cb) => {
  arr.push(cb.checked === true ? 1 : 0);
});
writeToStream(`show(0b${arr.reverse().join('')})`);

Hubungkan kotak centang untuk memperbarui matriks

Selanjutnya, kita perlu mendengarkan perubahan pada kotak centang dan, jika berubah, kirim informasi itu ke micro:bit. Dalam kode deteksi fitur (// CODELAB: Add feature detection here.), tambahkan baris berikut:

script.js - DOMContentLoaded

initCheckboxes();

Mari kita reset juga grid saat micro:bit pertama kali terhubung, sehingga akan menampilkan wajah senang. Fungsi drawGrid() sudah disediakan. Fungsi ini berfungsi mirip dengan sendGrid(); dibutuhkan susunan 1 dan 0, dan memeriksa kotak centang yang sesuai.

script.js - clickConnect()

// CODELAB: Reset the grid on connect here.
drawGrid(GRID_HAPPY);
sendGrid();

Cobalah

Sekarang, ketika halaman membuka koneksi ke micro:bit, halaman akan mengirim wajah senang. Mengklik kotak centang akan memperbarui tampilan pada matriks LED.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Anda akan melihat senyuman yang ditunjukkan pada matriks LED mikro:bit.
  5. Gambar pola yang berbeda pada matriks LED dengan mengubah kotak centang.

6. Kaitkan tombol mikro:bit

Menambahkan peristiwa smartwatch di tombol micro:bit

Ada dua tombol di micro:bit, satu di kedua sisi matriks LED. Espruino menyediakan fungsi setWatch yang mengirimkan peristiwa/callback saat tombol ditekan. Karena kita ingin memproses kedua tombol, kita akan membuat fungsi generik dan memintanya mencetak detail peristiwa.

script.js - watchButton()

// CODELAB: Hook up the micro:bit buttons to print a string.
const cmd = `
  setWatch(function(e) {
    print('{"button": "${btnId}", "pressed": ' + e.state + '}');
  }, ${btnId}, {repeat:true, debounce:20, edge:"both"});
`;
writeToStream(cmd);

Selanjutnya, kita perlu menghubungkan kedua tombol (bernama BTN1 dan BTN2 pada papan mikro:bit) setiap kali port serial terhubung ke perangkat.

script.js - clickConnect()

// CODELAB: Initialize micro:bit buttons.
watchButton('BTN1');
watchButton('BTN2');

Cobalah

Selain menampilkan wajah senang saat terhubung, menekan salah satu tombol pada micro:bit akan menambahkan teks ke halaman yang menunjukkan tombol apa yang ditekan. Kemungkinan besar, setiap karakter akan berada di barisnya sendiri.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Anda akan melihat senyuman yang ditunjukkan pada matriks LED micro:bits.
  5. Tekan tombol pada micro:bit dan pastikan bahwa tombol tersebut menambahkan teks baru ke halaman dengan detail tombol yang ditekan.

7. Menggunakan aliran data transformasi untuk mengurai data yang masuk

Penanganan streaming dasar

Saat salah satu tombol mikro:bit ditekan, micro:bit akan mengirimkan data ke port serial melalui stream. Aliran data sangat berguna, tetapi juga dapat menjadi tantangan karena Anda tidak harus mendapatkan semua data sekaligus, dan dapat dipecah secara acak.

Aplikasi saat ini mencetak streaming yang masuk saat tiba (dalam readLoop). Dalam sebagian besar kasus, setiap karakter berada pada barisnya sendiri, tetapi itu tidak terlalu membantu. Idealnya, aliran data harus diurai menjadi baris individual, dan tiap pesan ditampilkan sebagai barisnya sendiri.

Mengubah feed dengan TransformStream

Untuk melakukannya, kita dapat menggunakan aliran transformasi ( TransformStream), yang memungkinkan untuk mengurai aliran yang masuk dan menampilkan data yang diuraikan. Stream transformasi dapat berada di antara sumber stream (dalam hal ini, micro:bit), dan apa pun yang menggunakan stream tersebut (dalam hal ini readLoop), serta dapat menerapkan transformasi arbitrer sebelum akhirnya digunakan. Anggap saja seperti jalur perakitan: Saat widget memasuki garis akhir, setiap langkah dalam baris tersebut akan memodifikasi widget, sehingga pada saat widget mencapai tujuan akhirnya, widget tersebut berfungsi sepenuhnya.

Untuk informasi selengkapnya, lihat Konsep Streams API MDN.

Mentransformasi aliran data dengan LineBreakTransformer

Mari kita buat class LineBreakTransformer, yang akan mengambil streaming dan memotongnya berdasarkan jeda baris (\r\n). Class ini memerlukan dua metode, transform dan flush. Metode transform dipanggil setiap kali data baru diterima oleh aliran data. Fitur ini dapat mengantrekan data atau menyimpannya untuk nanti. Metode flush dipanggil saat aliran data ditutup, dan menangani data yang belum diproses.

Dalam metode transform, kita akan menambahkan data baru ke container, lalu memeriksa apakah ada jeda baris di container. Jika ada, bagi menjadi array, lalu lakukan iterasi melalui baris, dengan memanggil controller.enqueue() untuk mengirim baris yang diuraikan.

script.js - LineBreakTransformer.transform()

// CODELAB: Handle incoming chunk
this.container += chunk;
const lines = this.container.split('\r\n');
this.container = lines.pop();
lines.forEach(line => controller.enqueue(line));

Saat aliran data ditutup, kami hanya akan membuang data yang tersisa dalam penampung menggunakan enqueue.

script.js - LineBreakTransformer.flush()

// CODELAB: Flush the stream.
controller.enqueue(this.container);

Terakhir, kita perlu menyalurkan aliran masuk melalui LineBreakTransformer yang baru. Aliran input asli hanya disalurkan melalui TextDecoderStream, jadi kita perlu menambahkan pipeThrough tambahan untuk menyalurkannya melalui LineBreakTransformer baru.

script.js - connect()

// CODELAB: Add code to read the stream here.
let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable
  .pipeThrough(new TransformStream(new LineBreakTransformer()));

Cobalah

Sekarang, ketika Anda menekan salah satu tombol micro:bit, data yang dicetak akan ditampilkan dalam satu baris.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Anda akan melihat senyuman yang ditunjukkan pada matriks LED mikro:bit.
  5. Tekan tombol pada micro:bit dan pastikan Anda melihat sesuatu seperti berikut:

eead3553d29ee581.png

Mentransformasi aliran data dengan JSONTransformer

Kita dapat mencoba mengurai string menjadi JSON di readLoop, tetapi sebagai gantinya, mari kita buat transformator JSON yang sangat sederhana yang akan mengubah data menjadi objek JSON. Jika datanya bukan JSON yang valid, cukup tampilkan data yang masuk.

script.js - JSONTransformer.transform

// CODELAB: Attempt to parse JSON content
try {
  controller.enqueue(JSON.parse(chunk));
} catch (e) {
  controller.enqueue(chunk);
}

Selanjutnya, kirim aliran data melalui JSONTransformer, setelah aliran tersebut melalui LineBreakTransformer. Hal ini memungkinkan kita untuk menjaga JSONTransformer tetap sederhana, karena kita tahu bahwa JSON hanya akan dikirim pada satu baris.

script.js - connect

// CODELAB: Add code to read the stream here.
let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable
  .pipeThrough(new TransformStream(new LineBreakTransformer()))
  .pipeThrough(new TransformStream(new JSONTransformer()));

Cobalah

Sekarang, saat menekan salah satu tombol micro:bit, Anda akan melihat [object Object] yang dicetak di halaman.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Anda akan melihat senyuman yang ditunjukkan pada matriks LED mikro:bit.
  5. Tekan tombol pada micro:bit, dan pastikan Anda melihat sesuatu seperti berikut:

Merespons penekanan tombol

Untuk merespons penekanan tombol micro:bit, update readLoop untuk memeriksa apakah data yang diterima adalah object dengan properti button. Lalu, panggil buttonPushed untuk menangani penekanan tombol.

script.js - readLoop()

const { value, done } = await reader.read();
if (value && value.button) {
  buttonPushed(value);
} else {
  log.textContent += value + '\n';
}

Saat tombol mikro:bit ditekan, tampilan pada matriks LED akan berubah. Gunakan kode berikut untuk menetapkan matriks:

script.js - buttonPushed()

// CODELAB: micro:bit button press handler
if (butEvt.button === 'BTN1') {
  divLeftBut.classList.toggle('pressed', butEvt.pressed);
  if (butEvt.pressed) {
    drawGrid(GRID_HAPPY);
    sendGrid();
  }
  return;
}
if (butEvt.button === 'BTN2') {
  divRightBut.classList.toggle('pressed', butEvt.pressed);
  if (butEvt.pressed) {
    drawGrid(GRID_SAD);
    sendGrid();
  }
}

Cobalah

Sekarang, ketika Anda menekan salah satu tombol micro:bit, matriks LED akan berubah menjadi wajah senang atau wajah sedih.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit dan klik Hubungkan.
  4. Anda akan melihat senyuman yang ditunjukkan pada matriks LED micro:bits.
  5. Tekan tombol pada micro:bit, dan pastikan matriks LED berubah.

8. Menutup port serial

Langkah terakhir adalah menghubungkan fungsi pemutusan koneksi untuk menutup port saat pengguna selesai.

Menutup port saat pengguna mengklik tombol Hubungkan/Putuskan Koneksi

Saat pengguna mengklik tombol Connect/Putuskan, kita perlu menutup koneksi. Jika port sudah terbuka, panggil disconnect() dan update UI untuk menunjukkan bahwa halaman tidak lagi terhubung ke perangkat serial.

script.js - clickConnect()

// CODELAB: Add disconnect code here.
if (port) {
  await disconnect();
  toggleUIConnected(false);
  return;
}

Menutup aliran data dan port

Pada fungsi disconnect, kita harus menutup stream input, menutup stream output, dan menutup port. Untuk menutup aliran input, panggil reader.cancel(). Panggilan ke cancel bersifat asinkron, sehingga kita perlu menggunakan await untuk menunggunya selesai:

script.js - disconnect()

// CODELAB: Close the input stream (reader).
if (reader) {
  await reader.cancel();
  await inputDone.catch(() => {});
  reader = null;
  inputDone = null;
}

Untuk menutup aliran output, dapatkan writer, panggil close(), dan tunggu hingga objek outputDone ditutup:

script.js - disconnect()

// CODELAB: Close the output stream.
if (outputStream) {
  await outputStream.getWriter().close();
  await outputDone;
  outputStream = null;
  outputDone = null;
}

Terakhir, tutup port serial dan tunggu hingga tertutup:

script.js - disconnect()

// CODELAB: Close the port.
await port.close();
port = null;

Cobalah

Sekarang, Anda dapat membuka dan menutup port serial kapan saja.

  1. Muat ulang halaman.
  2. Klik tombol Connect.
  3. Pada dialog pemilih Serial Port, pilih perangkat BBC micro:bit, lalu klik Hubungkan.
  4. Anda akan melihat senyuman yang ditunjukkan pada matriks LED mikro:bit
  5. Tekan tombol Putuskan koneksi dan pastikan matriks LED nonaktif dan tidak ada error di konsol.

9. Selamat

Selamat! Anda telah berhasil membangun aplikasi web pertama Anda yang menggunakan Web Serial API.

Pantau terus https://goo.gle/fugu-api-tracker untuk mengetahui informasi terbaru tentang Web Serial API dan semua kemampuan web baru menarik lainnya yang sedang dikerjakan oleh tim Chrome.