การเริ่มต้นใช้งาน Web Serial API

1. บทนำ

อัปเดตล่าสุด: 2020-07-21

สิ่งที่คุณจะสร้าง

ในโค้ดแล็บนี้ คุณจะได้สร้างหน้าเว็บที่ใช้ Web Serial API เพื่อโต้ตอบกับบอร์ด BBC micro:bit เพื่อแสดงรูปภาพในเมทริกซ์ LED ขนาด 5x5 คุณจะได้เรียนรู้เกี่ยวกับ Web Serial API และวิธีใช้สตรีมที่อ่านได้ เขียนได้ และแปลงได้เพื่อสื่อสารกับอุปกรณ์แบบอนุกรมผ่านเบราว์เซอร์

81167ab7c01d353d.png

สิ่งที่คุณจะได้เรียนรู้

  • วิธีเปิดและปิดพอร์ตอนุกรมของเว็บ
  • วิธีใช้ Read Loop เพื่อจัดการข้อมูลจากสตรีมอินพุต
  • วิธีส่งข้อมูลออกผ่านสตรีมการเขียน

สิ่งที่คุณต้องมี

เราเลือกใช้ micro:bit สำหรับ Codelab นี้เนื่องจากมีราคาไม่แพง มีอินพุต (ปุ่ม) และเอาต์พุต (จอแสดงผล LED ขนาด 5x5) และสามารถให้อินพุตและเอาต์พุตเพิ่มเติมได้ ดูรายละเอียดเกี่ยวกับความสามารถของ micro:bit ได้ที่หน้า BBC micro:bit ในเว็บไซต์ Espruino

2. เกี่ยวกับ Web Serial API

Web Serial API ช่วยให้เว็บไซต์อ่านและเขียนไปยังอุปกรณ์แบบอนุกรมด้วยสคริปต์ได้ API จะเชื่อมต่อเว็บกับโลกจริงโดยอนุญาตให้เว็บไซต์สื่อสารกับอุปกรณ์ซีเรียล เช่น ไมโครคอนโทรลเลอร์และเครื่องพิมพ์ 3 มิติ

มีตัวอย่างมากมายของซอฟต์แวร์ควบคุมที่สร้างขึ้นโดยใช้เทคโนโลยีเว็บ เช่น

ในบางกรณี เว็บไซต์เหล่านี้จะสื่อสารกับอุปกรณ์ผ่านแอปพลิเคชันตัวแทนเนทีฟที่ผู้ใช้ติดตั้งด้วยตนเอง ในกรณีอื่นๆ แอปพลิเคชันจะแสดงในแอปพลิเคชันเนทีฟที่แพ็กเกจผ่านเฟรมเวิร์ก เช่น Electron ในกรณีอื่นๆ ผู้ใช้จะต้องทำตามขั้นตอนเพิ่มเติม เช่น คัดลอกแอปพลิเคชันที่คอมไพล์แล้วไปยังอุปกรณ์ด้วยแฟลชไดรฟ์ USB

คุณปรับปรุงประสบการณ์ของผู้ใช้ได้โดยการสื่อสารโดยตรงระหว่างเว็บไซต์กับอุปกรณ์ที่เว็บไซต์ควบคุม

3. การเริ่มตั้งค่า

รับรหัส

เราได้รวบรวมทุกสิ่งที่คุณต้องการสำหรับ Codelab นี้ไว้ในโปรเจ็กต์ Glitch

  1. เปิดแท็บใหม่ในเบราว์เซอร์แล้วไปที่ https://web-serial-codelab-start.glitch.me/
  2. คลิกลิงก์ Remix Glitch เพื่อสร้างโปรเจ็กต์เริ่มต้นเวอร์ชันของคุณเอง
  3. คลิกปุ่มแสดง แล้วเลือกในหน้าต่างใหม่เพื่อดูโค้ดของคุณทำงาน

4. เปิดการเชื่อมต่อแบบอนุกรม

ตรวจสอบว่าระบบรองรับ Web Serial API หรือไม่

สิ่งแรกที่ต้องทำคือตรวจสอบว่าเบราว์เซอร์ปัจจุบันรองรับ Web Serial API หรือไม่ โดยตรวจสอบว่า serial อยู่ใน navigator หรือไม่

ในDOMContentLoaded event ให้เพิ่มโค้ดต่อไปนี้ลงในโปรเจ็กต์

script.js - DOMContentLoaded

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

ซึ่งจะตรวจสอบว่ารองรับ Web Serial หรือไม่ หากเป็นเช่นนั้น โค้ดนี้จะซ่อนแบนเนอร์ที่ระบุว่าไม่รองรับ Web Serial

ลองใช้

  1. โหลดหน้าเว็บ
  2. ตรวจสอบว่าหน้าเว็บไม่แสดงแบนเนอร์สีแดงที่ระบุว่าไม่รองรับ Web Serial

เปิดพอร์ตอนุกรม

จากนั้นเราต้องเปิดพอร์ตอนุกรม Web Serial API เป็นแบบอะซิงโครนัสเช่นเดียวกับ API ที่ทันสมัยอื่นๆ ส่วนใหญ่ ซึ่งจะช่วยป้องกันไม่ให้ UI ถูกบล็อกเมื่อรอรับอินพุต แต่ก็มีความสำคัญด้วยเนื่องจากหน้าเว็บอาจได้รับข้อมูลแบบอนุกรมได้ทุกเมื่อ และเราจำเป็นต้องมีวิธีรับฟังข้อมูลดังกล่าว

เนื่องจากคอมพิวเตอร์อาจมีอุปกรณ์พอร์ตซีเรียลหลายเครื่อง เมื่อเบราว์เซอร์พยายามขอพอร์ต เบราว์เซอร์จะแจ้งให้ผู้ใช้เลือกอุปกรณ์ที่จะเชื่อมต่อ

เพิ่มโค้ดต่อไปนี้ลงในโปรเจ็กต์

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 });

การเรียกใช้ requestPort จะแจ้งให้ผู้ใช้เลือกอุปกรณ์ที่ต้องการเชื่อมต่อ การเรียกใช้ port.open จะเปิดพอร์ต นอกจากนี้ เรายังต้องระบุความเร็วที่ต้องการใช้ในการสื่อสารกับอุปกรณ์ซีเรียลด้วย BBC micro:bit ใช้การเชื่อมต่อ 9600 บอดระหว่างชิป USB-to-serial กับโปรเซสเซอร์หลัก

นอกจากนี้ เราจะเชื่อมต่อปุ่ม "เชื่อมต่อ" และกำหนดให้ปุ่มดังกล่าวเรียกใช้ connect() เมื่อผู้ใช้คลิกปุ่ม

เพิ่มโค้ดต่อไปนี้ลงในโปรเจ็กต์

script.js - clickConnect()

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

ลองใช้

ตอนนี้โปรเจ็กต์ของเรามีสิ่งจำเป็นขั้นต่ำในการเริ่มต้นแล้ว การคลิกปุ่มเชื่อมต่อจะแจ้งให้ผู้ใช้เลือกอุปกรณ์แบบอนุกรมที่จะเชื่อมต่อ แล้วเชื่อมต่อกับ micro:bit

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. ในแท็บ คุณควรเห็นไอคอนที่ระบุว่าคุณเชื่อมต่อกับอุปกรณ์แบบอนุกรมแล้ว

d9d0d3966960aeab.png

ตั้งค่าสตรีมอินพุตเพื่อฟังข้อมูลจากพอร์ตอนุกรม

หลังจากสร้างการเชื่อมต่อแล้ว เราต้องตั้งค่าสตรีมอินพุตและโปรแกรมอ่านเพื่ออ่านข้อมูลจากอุปกรณ์ ก่อนอื่น เราจะรับสตรีมที่อ่านได้จากพอร์ตโดยการเรียกใช้ port.readable เนื่องจากเรารู้ว่าเราจะได้รับข้อความจากอุปกรณ์ เราจึงจะส่งข้อความผ่านตัวถอดรหัสข้อความ จากนั้นเราจะรับผู้อ่านและเริ่มลูปการอ่าน

เพิ่มโค้ดต่อไปนี้ลงในโปรเจ็กต์

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();

Read Loop เป็นฟังก์ชันแบบอะซิงโครนัสที่ทำงานในลูปและรอเนื้อหาโดยไม่บล็อกเทรดหลัก เมื่อมีข้อมูลใหม่เข้ามา ผู้อ่านจะแสดงผลพร็อพเพอร์ตี้ 2 รายการ ได้แก่ value และบูลีน done หาก done เป็นจริง แสดงว่าพอร์ตปิดอยู่หรือไม่มีข้อมูลเข้ามาอีก

เพิ่มโค้ดต่อไปนี้ลงในโปรเจ็กต์

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;
  }
}

ลองใช้

ตอนนี้โปรเจ็กต์ของเราเชื่อมต่อกับอุปกรณ์ได้แล้ว และจะผนวกข้อมูลที่ได้รับจากอุปกรณ์เข้ากับองค์ประกอบบันทึก

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. คุณควรเห็นโลโก้ Espruino ดังนี้

93494fd58ea835eb.png

ตั้งค่าสตรีมเอาต์พุตเพื่อส่งข้อมูลไปยังพอร์ตอนุกรม

โดยปกติแล้ว การสื่อสารแบบอนุกรมจะเป็นแบบ 2 ทิศทาง นอกจากรับข้อมูลจากพอร์ตอนุกรมแล้ว เรายังต้องการส่งข้อมูลไปยังพอร์ตด้วย เช่นเดียวกับสตรีมอินพุต เราจะส่งข้อความผ่านสตรีมเอาต์พุตไปยัง micro:bit เท่านั้น

ก่อนอื่น ให้สร้างสตรีมของโปรแกรมเปลี่ยนไฟล์ข้อความ แล้วส่งสตรีมไปยัง 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;

เมื่อเชื่อมต่อผ่านอนุกรมกับเฟิร์มแวร์ Espruino บอร์ด BBC micro:bit จะทำหน้าที่เป็น read-eval-print loop (REPL) ของ JavaScript ซึ่งคล้ายกับที่คุณได้รับในเชลล์ Node.js จากนั้นเราต้องระบุวิธีการส่งข้อมูลไปยังสตรีม โค้ดด้านล่างจะรับ Writer จากสตรีมเอาต์พุต แล้วใช้ write เพื่อส่งแต่ละบรรทัด แต่ละบรรทัดที่ส่งจะมีอักขระขึ้นบรรทัดใหม่ (\n) เพื่อบอกให้ micro:bit ประเมินคำสั่งที่ส่ง

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();

หากต้องการให้ระบบอยู่ในสถานะที่ทราบและหยุดไม่ให้ระบบส่งอักขระที่เราส่งกลับมา เราต้องส่ง CTRL-C และปิดการแสดงผล

script.js - connect()

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

ลองใช้

ตอนนี้โปรเจ็กต์ของเราสามารถส่งและรับข้อมูลจาก micro:bit ได้แล้ว มาตรวจสอบว่าเราส่งคำสั่งได้อย่างถูกต้องกัน

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. เปิดแท็บคอนโซลในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome แล้วพิมพ์ writeToStream('console.log("yes")');

คุณควรเห็นข้อความต่อไปนี้พิมพ์อยู่ในหน้า

a13187e7e6260f7f.png

5. ควบคุมเมทริกซ์ LED

สร้างสตริงตารางเมทริกซ์

หากต้องการควบคุมเมทริกซ์ LED ใน micro:bit เราต้องเรียกใช้ show() วิธีนี้จะแสดงกราฟิกบนหน้าจอ LED ขนาด 5x5 ในตัว ฟังก์ชันนี้รับตัวเลขฐานสองหรือสตริง

เราจะวนซ้ำช่องทำเครื่องหมายและสร้างอาร์เรย์ของ 1 และ 0 เพื่อระบุว่าช่องใดมีการเลือกและช่องใดไม่มีการเลือก จากนั้นเราต้องกลับด้านอาร์เรย์ เนื่องจากลำดับของช่องทำเครื่องหมายจะตรงกันข้ามกับลำดับของ LED ในเมทริกซ์ จากนั้นเราจะแปลงอาร์เรย์เป็นสตริงและสร้างคำสั่งเพื่อส่งไปยัง 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('')})`);

เชื่อมต่อช่องทำเครื่องหมายเพื่ออัปเดตเมทริกซ์

จากนั้นเราต้องรอฟังการเปลี่ยนแปลงในช่องทำเครื่องหมาย และหากมีการเปลี่ยนแปลง ให้ส่งข้อมูลนั้นไปยัง micro:bit ในโค้ดตรวจหาฟีเจอร์ (// CODELAB: Add feature detection here.) ให้เพิ่มบรรทัดต่อไปนี้

script.js - DOMContentLoaded

initCheckboxes();

นอกจากนี้ เราจะรีเซ็ตกริดเมื่อเชื่อมต่อ micro:bit เป็นครั้งแรกเพื่อให้แสดงหน้ายิ้ม มีฟังก์ชัน drawGrid() อยู่แล้ว ฟังก์ชันนี้ทำงานคล้ายกับ sendGrid() โดยจะรับอาร์เรย์ของ 1 และ 0 แล้วเลือกช่องทำเครื่องหมายตามความเหมาะสม

script.js - clickConnect()

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

ลองใช้

ตอนนี้เมื่อหน้าเว็บเปิดการเชื่อมต่อกับ micro:bit หน้าเว็บจะส่งหน้ายิ้ม การคลิกช่องทําเครื่องหมายจะอัปเดตการแสดงผลบนเมทริกซ์ LED

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. คุณควรเห็นรอยยิ้มแสดงบนเมทริกซ์ LED ของ micro:bit
  5. วาดลวดลายอื่นบนเมทริกซ์ LED โดยการเปลี่ยนช่องทำเครื่องหมาย

6. ต่อปุ่ม micro:bit

เพิ่มเหตุการณ์นาฬิกาในปุ่ม micro:bit

micro:bit มีปุ่ม 2 ปุ่ม โดยปุ่มหนึ่งอยู่ด้านใดด้านหนึ่งของเมทริกซ์ LED Espruino มีsetWatchฟังก์ชันที่ส่งเหตุการณ์/Callback เมื่อมีการกดปุ่ม เนื่องจากเราต้องการฟังทั้ง 2 ปุ่ม เราจึงจะสร้างฟังก์ชันทั่วไปและให้ฟังก์ชันดังกล่าวพิมพ์รายละเอียดของเหตุการณ์

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);

จากนั้นเราต้องเชื่อมต่อปุ่มทั้ง 2 ปุ่ม (ชื่อ BTN1 และ BTN2 บนบอร์ด micro:bit) ทุกครั้งที่เชื่อมต่อพอร์ตอนุกรมกับอุปกรณ์

script.js - clickConnect()

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

ลองใช้

นอกเหนือจากการแสดงหน้ายิ้มเมื่อเชื่อมต่อแล้ว การกดปุ่มใดปุ่มหนึ่งบน micro:bit จะเพิ่มข้อความลงในหน้าเว็บเพื่อระบุว่ามีการกดปุ่มใด โดยส่วนใหญ่แล้ว ตัวอักษรแต่ละตัวจะอยู่ในบรรทัดของตัวเอง

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. คุณควรเห็นรอยยิ้มแสดงบนเมทริกซ์ LED ของ micro:bit
  5. กดปุ่มบน micro:bit และตรวจสอบว่าปุ่มดังกล่าวจะเพิ่มข้อความใหม่ลงในหน้าเว็บพร้อมรายละเอียดของปุ่มที่กด

7. ใช้สตรีมการเปลี่ยนรูปแบบเพื่อแยกวิเคราะห์ข้อมูลขาเข้า

การจัดการสตรีมพื้นฐาน

เมื่อกดปุ่มใดปุ่มหนึ่งของ micro:bit อุปกรณ์จะส่งข้อมูลไปยังพอร์ตอนุกรมผ่านสตรีม สตรีมมีประโยชน์มาก แต่ก็อาจเป็นความท้าทายได้เช่นกัน เนื่องจากคุณอาจไม่ได้รับข้อมูลทั้งหมดในครั้งเดียว และข้อมูลอาจถูกแบ่งออกเป็นกลุ่มๆ โดยพลการ

ปัจจุบันแอปจะพิมพ์สตรีมที่เข้ามาเมื่อมาถึง (ใน readLoop) ในกรณีส่วนใหญ่ อักขระแต่ละตัวจะอยู่ในบรรทัดของตัวเอง แต่ก็ไม่ได้มีประโยชน์มากนัก โดยควรแยกวิเคราะห์สตรีมเป็นบรรทัดต่างๆ และแสดงข้อความแต่ละรายการเป็นบรรทัดของตัวเอง

การเปลี่ยนรูปแบบสตรีมด้วย TransformStream

เราสามารถใช้สตรีมการแปลง ( TransformStream) เพื่อแยกวิเคราะห์สตรีมขาเข้าและส่งคืนข้อมูลที่แยกวิเคราะห์แล้ว สตรีมการแปลงสามารถอยู่ระหว่างแหล่งที่มาของสตรีม (ในกรณีนี้คือ micro:bit) กับสิ่งที่ใช้สตรีม (ในกรณีนี้คือ readLoop) และสามารถใช้การแปลงที่กำหนดเองก่อนที่จะมีการใช้สตรีมในที่สุด ลองนึกถึงสายการประกอบ เมื่อวิดเจ็ตเคลื่อนที่ไปตามสายการประกอบ แต่ละขั้นตอนในสายการประกอบจะแก้ไขวิดเจ็ต ดังนั้นเมื่อวิดเจ็ตไปถึงปลายทางสุดท้าย วิดเจ็ตนั้นจะทำงานได้อย่างเต็มที่

ดูข้อมูลเพิ่มเติมได้ที่แนวคิดเกี่ยวกับ Streams API ของ MDN

เปลี่ยนโฉมไลฟ์สดด้วย LineBreakTransformer

มาสร้างLineBreakTransformerคลาสกัน ซึ่งจะรับสตรีมและแบ่งออกเป็นส่วนๆ ตามการขึ้นบรรทัดใหม่ (\r\n) คลาสนี้ต้องมี 2 เมธอด ได้แก่ transform และ flush ระบบจะเรียกใช้เมธอด transform ทุกครั้งที่สตรีมได้รับข้อมูลใหม่ โดยจะจัดคิวข้อมูลหรือบันทึกไว้ใช้ในภายหลังก็ได้ ระบบจะเรียกใช้เมธอด flush เมื่อปิดสตรีม และจะจัดการข้อมูลที่ยังไม่ได้ประมวลผล

ในtransformวิธีนี้ เราจะเพิ่มข้อมูลใหม่ลงใน container แล้วตรวจสอบว่ามีบรรทัดใหม่ใน container หรือไม่ หากมี ให้แยกเป็นอาร์เรย์ จากนั้นวนซ้ำผ่านบรรทัดต่างๆ โดยเรียกใช้ controller.enqueue() เพื่อส่งบรรทัดที่แยกวิเคราะห์แล้วออกไป

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));

เมื่อปิดสตรีม เราจะล้างข้อมูลที่เหลือในคอนเทนเนอร์โดยใช้ enqueue

script.js - LineBreakTransformer.flush()

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

สุดท้าย เราต้องส่งสตรีมที่เข้ามาผ่าน LineBreakTransformer ใหม่ สตรีมอินพุตเดิมของเราส่งผ่าน TextDecoderStream เท่านั้น ดังนั้นเราจึงต้องเพิ่ม pipeThrough อีกรายการเพื่อส่งผ่าน LineBreakTransformer ใหม่

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()));

ลองใช้

ตอนนี้เมื่อคุณกดปุ่มใดปุ่มหนึ่งของ micro:bit ระบบควรแสดงข้อมูลที่พิมพ์ในบรรทัดเดียว

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. คุณควรเห็นรอยยิ้มแสดงบนเมทริกซ์ LED ของ micro:bit
  5. กดปุ่มบน micro:bit และตรวจสอบว่าคุณเห็นข้อความคล้ายกับข้อความต่อไปนี้

6c2193880c748412.png

เปลี่ยนโฉมไลฟ์สดด้วย JSONTransformer

เราอาจลองแยกวิเคราะห์สตริงเป็น JSON ใน readLoop แต่เราจะสร้างตัวแปลง JSON แบบง่ายๆ ที่จะแปลงข้อมูลเป็นออบเจ็กต์ JSON แทน หากข้อมูลไม่ใช่ JSON ที่ถูกต้อง ให้ส่งคืนข้อมูลที่ได้รับ

script.js - JSONTransformer.transform

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

จากนั้นส่งสตรีมผ่าน JSONTransformer หลังจากที่ผ่าน LineBreakTransformer แล้ว ซึ่งช่วยให้เราสามารถรักษาJSONTransformerให้เรียบง่ายได้ เนื่องจากเราทราบว่าระบบจะส่ง JSON ในบรรทัดเดียวเท่านั้น

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()));

ลองใช้

ตอนนี้เมื่อกดปุ่มใดปุ่มหนึ่งของ micro:bit คุณควรเห็น [object Object] พิมพ์บนหน้าเว็บ

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. คุณควรเห็นรอยยิ้มแสดงบนเมทริกซ์ LED ของ micro:bit
  5. กดปุ่มบน micro:bit แล้วตรวจสอบว่าคุณเห็นข้อความคล้ายกับข้อความต่อไปนี้

การตอบสนองต่อการกดปุ่ม

หากต้องการตอบสนองต่อการกดปุ่ม micro:bit ให้อัปเดต readLoop เพื่อตรวจสอบว่าข้อมูลที่ได้รับเป็น object ที่มีพร็อพเพอร์ตี้ button หรือไม่ จากนั้นเรียกใช้ buttonPushed เพื่อจัดการการกดปุ่ม

script.js - readLoop()

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

เมื่อกดปุ่ม micro:bit จอแสดงผลบนเมทริกซ์ LED ควรเปลี่ยน ใช้โค้ดต่อไปนี้เพื่อตั้งค่าเมทริกซ์

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();
  }
}

ลองใช้

ตอนนี้เมื่อคุณกดปุ่มใดปุ่มหนึ่งของ micro:bit เมทริกซ์ LED ควรเปลี่ยนเป็นหน้ายิ้มหรือหน้าเศร้า

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. คุณควรเห็นรอยยิ้มแสดงบนเมทริกซ์ LED ของ micro:bit
  5. กดปุ่มบน micro:bit แล้วตรวจสอบว่าเมทริกซ์ LED เปลี่ยนไป

8. ปิดพอร์ตอนุกรม

ขั้นตอนสุดท้ายคือการเชื่อมต่อฟังก์ชันการยกเลิกการเชื่อมต่อเพื่อปิดพอร์ตเมื่อผู้ใช้ดำเนินการเสร็จแล้ว

ปิดพอร์ตเมื่อผู้ใช้คลิกปุ่มเชื่อมต่อ/ยกเลิกการเชื่อมต่อ

เมื่อผู้ใช้คลิกปุ่มเชื่อมต่อ/ยกเลิกการเชื่อมต่อ เราจะต้องปิดการเชื่อมต่อ หากพอร์ตเปิดอยู่แล้ว ให้เรียกใช้ disconnect() และอัปเดต UI เพื่อระบุว่าหน้าเว็บไม่ได้เชื่อมต่อกับอุปกรณ์แบบอนุกรมอีกต่อไป

script.js - clickConnect()

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

ปิดสตรีมและพอร์ต

ในdisconnectฟังก์ชัน เราต้องปิดสตรีมอินพุต ปิดสตรีมเอาต์พุต และปิดพอร์ต หากต้องการปิดสตรีมอินพุต ให้เรียกใช้ reader.cancel() การเรียกใช้ cancel เป็นแบบอะซิงโครนัส ดังนั้นเราจึงต้องใช้ await เพื่อรอให้การเรียกใช้เสร็จสมบูรณ์

script.js - disconnect()

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

หากต้องการปิดสตรีมเอาต์พุต ให้รับ writer เรียกใช้ close() และรอให้ปิดออบเจ็กต์ outputDone

script.js - disconnect()

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

สุดท้าย ให้ปิดพอร์ตอนุกรมและรอให้ปิด

script.js - disconnect()

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

ลองใช้

ตอนนี้คุณสามารถเปิดและปิดพอร์ตอนุกรมได้ตามต้องการ

  1. โหลดหน้าซ้ำ
  2. คลิกปุ่มเชื่อมต่อ
  3. ในกล่องโต้ตอบตัวเลือกพอร์ตอนุกรม ให้เลือกอุปกรณ์ BBC micro:bit แล้วคลิกเชื่อมต่อ
  4. คุณควรเห็นรอยยิ้มแสดงบนเมทริกซ์ LED ของ micro:bit
  5. กดปุ่มยกเลิกการเชื่อมต่อ และตรวจสอบว่าเมทริกซ์ LED ปิดอยู่และไม่มีข้อผิดพลาดในคอนโซล

9. ขอแสดงความยินดี

ยินดีด้วย คุณสร้างเว็บแอปแรกที่ใช้ Web Serial API ได้สำเร็จแล้ว

โปรดติดตาม https://goo.gle/fugu-api-tracker เพื่อดูข้อมูลล่าสุดเกี่ยวกับ Web Serial API และความสามารถใหม่ๆ ที่น่าตื่นเต้นอื่นๆ บนเว็บที่ทีม Chrome กำลังดำเนินการ