Bắt đầu sử dụng API Web Serial

Lần cập nhật gần đây nhất: Ngày 8 tháng 11 năm 2019

Sản phẩm bạn sẽ tạo ra

Trong lớp học lập trình này, bạn sẽ xây dựng một trang web sử dụng API Web Serial để tương tác với bảng BBC micro:bit để hiển thị hình ảnh trên ma trận LED 5x5. Bạn sẽ tìm hiểu về API Web Serial và cách sử dụng luồng có thể đọc, ghi và biến đổi để giao tiếp với các thiết bị nối tiếp thông qua trình duyệt.

Kiến thức bạn sẽ học được

  • Cách mở và đóng cổng nối tiếp web
  • Cách sử dụng vòng lặp đọc để xử lý dữ liệu từ một luồng đầu vào
  • Cách gửi dữ liệu qua luồng ghi

Bạn cần có

Chúng tôi đã chọn sử dụng micro:bit cho lớp học lập trình này vì lớp này có giá phải chăng, cung cấp một số đầu vào (nút) và đầu ra (màn hình LED 5x5), đồng thời có thể cung cấp thêm dữ liệu đầu vào và đầu ra. Hãy xem trang micro:bit trên trang web Espruino để biết thông tin chi tiết về khả năng của micrô:

API Web Serial cung cấp cho các trang web cách đọc và ghi vào thiết bị nối tiếp có tập lệnh. API kết nối web và thế giới thực bằng cách cho phép trang web giao tiếp với thiết bị nối tiếp, chẳng hạn như bộ vi điều khiển và máy in 3D.

Có nhiều ví dụ về phần mềm kiểm soát được xây dựng bằng công nghệ web. Ví dụ:

Trong một số trường hợp, các trang web này giao tiếp với thiết bị thông qua ứng dụng tác nhân gốc do người dùng cài đặt theo cách thủ công. Trong các trường hợp khác, ứng dụng được phân phối trong ứng dụng gốc được đóng gói thông qua một khung như Electron. Trong các trường hợp khác, người dùng bắt buộc phải thực hiện thêm một bước, chẳng hạn như sao chép một ứng dụng đã biên dịch vào thiết bị có ổ đĩa USB flash.

Bạn có thể cải thiện trải nghiệm người dùng bằng cách cung cấp giao tiếp trực tiếp giữa trang web và thiết bị mà trang web đang kiểm soát.

Bật API Web Serial

API Web Serial hiện đang trong quá trình phát triển và chỉ được hỗ trợ sau một cờ. Bạn phải bật cờ #enable-experimental-web-platform-features trong chrome://flags.

Lấy mã

Chúng tôi đã đặt mọi thứ bạn cần cho lớp học lập trình này vào một dự án Glrick.

  1. Mở một thẻ trình duyệt mới rồi truy cập https://web-serial-codelab-start.glcab.me/.
  2. Nhấp vào đường liên kết Remix Glcab (Tạo bản sao của dự án dành cho người mới bắt đầu).
  3. Nhấp vào nút Show (Hiển thị), rồi chọn Trong cửa sổ mới để xem mã của bạn trong thực tế.

Kiểm tra xem API Web Serial có được hỗ trợ hay không

Điều đầu tiên cần làm là kiểm tra xem API nối tiếp web có được hỗ trợ trong trình duyệt hiện tại hay không. Để làm việc đó, hãy kiểm tra xem serial có bằng navigator hay không.

Trong sự kiện DOMContentLoaded, hãy thêm mã sau vào dự án của bạn:

script.js - DOMContentLoaded

// CODELAB: Add feature detection here.
if ('serial' in navigator) {
  const notSupported = document.getElementById('notSupported');
  notSupported.classList.add('hidden');
}

Việc này sẽ kiểm tra xem Web Serial có được hỗ trợ hay không. Nếu có, mã này sẽ ẩn biểu ngữ có nội dung rằng Web Serial không được hỗ trợ.

Thử nào

  1. Tải trang.
  2. Xác minh rằng trang không hiển thị biểu ngữ màu đỏ cho biết rằng Web Serial không được hỗ trợ.

Mở cổng nối tiếp

Tiếp theo, chúng ta cần mở cổng nối tiếp. Giống như hầu hết các API hiện đại khác, API Serial Web không đồng bộ. Điều này ngăn giao diện người dùng chặn khi chờ nhập, nhưng giao diện này cũng quan trọng vì trang web có thể nhận dữ liệu nối tiếp bất cứ lúc nào và chúng ta cần có cách để xử lý dữ liệu đó.

Vì máy tính có thể có nhiều thiết bị nối tiếp, nên khi trình duyệt cố gắng yêu cầu chuyển, trình duyệt sẽ nhắc người dùng chọn thiết bị để kết nối.

Thêm mã sau vào dự án của bạn:

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

Cuộc gọi requestPort nhắc người dùng về thiết bị mà họ muốn kết nối. Đang gọi port.open sẽ mở cổng. Chúng tôi cũng cần cung cấp tốc độ chúng tôi muốn kết nối với thiết bị nối tiếp. BBC micro:bit sử dụng kết nối 9600 baud giữa chip USB-to-serial và bộ xử lý chính.

Ngoài ra, hãy kết nối nút kết nối và yêu cầu nút gọi connect() khi người dùng nhấp vào nút đó.

Thêm mã sau vào dự án của bạn:

script.js - clickConnect()

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

Thử nào

Dự án của chúng tôi hiện đã có đủ số lượng tối thiểu để bắt đầu. Khi nhấp vào nút Kết nối, người dùng sẽ chọn thiết bị nối tiếp để kết nối, sau đó kết nối với micro:bit.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Trên thẻ này, bạn sẽ thấy một biểu tượng cho biết rằng bạn đã kết nối với một thiết bị nối tiếp:

Thiết lập luồng đầu vào để nghe dữ liệu từ cổng nối tiếp

Sau khi thiết lập kết nối, chúng ta cần thiết lập một luồng đầu vào và trình đọc để đọc dữ liệu từ thiết bị. Trước tiên, chúng tôi sẽ lấy luồng có thể đọc được từ cổng bằng cách gọi port.readable. Vì chúng tôi biết rằng chúng tôi sẽ nhận lại văn bản từ thiết bị, chúng tôi sẽ phân tích văn bản đó từ bộ giải mã văn bản. Tiếp theo, chúng ta sẽ lấy người đọc và bắt đầu vòng lặp đọc.

Thêm mã sau vào dự án của bạn:

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

Vòng lặp đọc là một hàm không đồng bộ chạy trong một vòng lặp và chờ nội dung mà không chặn chuỗi chính. Khi có dữ liệu mới, trình đọc sẽ trả về 2 thuộc tính: value và boolean done. Nếu đặt là done đúng thì cổng đã bị đóng hoặc không có thêm dữ liệu nào đến.

Thêm mã sau vào dự án của bạn:

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

Thử nào

Dự án của chúng ta hiện có thể kết nối với thiết bị và sẽ thêm mọi dữ liệu nhận được từ thiết bị vào phần tử nhật ký.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Bạn sẽ thấy biểu tượng Espruino:

Thiết lập một luồng đầu ra để gửi dữ liệu đến cổng nối tiếp

Giao tiếp nối tiếp thường có hai chiều. Ngoài việc nhận dữ liệu từ cổng nối tiếp, chúng tôi cũng muốn gửi dữ liệu đến cổng đó. Tương tự với luồng đầu vào, chúng tôi sẽ chỉ gửi văn bản qua luồng đầu ra đến vi:bit.

Trước tiên, hãy tạo một luồng mã hóa văn bản và tạo luồng cho 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;

Khi được kết nối qua quá trình nối tiếp với chương trình cơ sở Espruino, bảng micrô micro:bit hoạt động như một vòng lặp đọc-eval-print (REPL) JavaScript, tương tự như những gì bạn nhận được trong giao diện Node.js. Tiếp theo, chúng ta cần cung cấp phương thức để gửi dữ liệu đến luồng. Đoạn mã bên dưới lấy người viết từ luồng đầu ra rồi sử dụng write để gửi từng dòng. Mỗi dòng được gửi bao gồm một ký tự dòng mới (\n), để cho biết micro:bit để đánh giá lệnh đã gửi.

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

Để chuyển hệ thống sang trạng thái đã biết và ngăn hệ thống phát âm các ký tự mà chúng ta gửi, chúng ta cần gửi CTRL-C và tắt tiếng vọng.

script.js - connect()

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

Thử nào

Dự án của chúng ta hiện có thể gửi và nhận dữ liệu từ micro:bit. Hãy xác minh rằng chúng ta có thể gửi đúng lệnh:

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Mở thẻ Bảng điều khiển trong Công cụ của Chrome cho nhà phát triển và nhập
    writeToStream('console.log("yes")');

Bạn sẽ thấy nội dung như sau được in trên trang:

Tạo chuỗi lưới ma trận

Để điều khiển ma trận LED trên micro:bit, chúng ta cần gọi show(). Phương thức này hiển thị đồ họa trên màn hình LED 5x5 tích hợp. Thao tác này sẽ lấy số nhị phân hoặc một chuỗi.

Chúng tôi sẽ lặp lại các hộp kiểm và tạo một mảng gồm 1 giây và 0 cho biết hộp kiểm nào được đánh dấu và hộp kiểm nào không được chọn. Khi đó, chúng ta cần đảo ngược mảng, vì thứ tự của các hộp đánh dấu nằm ngược lại với thứ tự của các đèn LED trong ma trận. Tiếp theo, chúng ta chuyển đổi mảng thành một chuỗi và tạo lệnh để gửi đến 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('')})`);

Kết nối hộp đánh dấu để cập nhật ma trận

Tiếp theo, chúng tôi cần xử lý các thay đổi trên hộp đánh dấu và nếu chúng thay đổi, hãy gửi thông tin đó đến micrô:bit. Trong mã phát hiện tính năng (// CODELAB: Add feature detection here.), hãy thêm dòng sau:

script.js - DOMContentLoaded

initCheckboxes();

Hãy để chúng tôi đặt lại lưới khi micrô nhỏ:được kết nối lần đầu tiên để hiển thị khuôn mặt hạnh phúc. Hàm drawGrid() đã được cung cấp. Hàm này hoạt động tương tự như sendGrid(); nhận được một mảng gồm 1 giây và 0, cũng như đánh dấu các hộp đánh dấu để phù hợp.

script.js - clickConnect()

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

Thử nào

Bây giờ, khi trang mở một kết nối tới vi mô, trang sẽ gửi khuôn mặt vui vẻ. Khi bạn chọn hộp đánh dấu, màn hình trên ma trận LED sẽ cập nhật.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Bạn sẽ thấy một khuôn mặt cười xuất hiện trên ma trận LED micro:bit.
  5. Vẽ một mẫu khác trên ma trận LED bằng cách thay đổi hộp đánh dấu.

Thêm một sự kiện đồng hồ trên các nút micro:bit

Có hai nút trên micrô nhỏ:một ở hai phía của ma trận LED. Espruino cung cấp một hàm setWatch sẽ gửi một sự kiện/lệnh gọi lại khi nút được nhấn. Vì chúng ta muốn nghe cả hai nút, nên chúng ta sẽ tạo hàm của mình là chung chung và để hàm in các chi tiết của sự kiện.

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

Tiếp theo, chúng ta cần kết nối cả hai nút (có tên là BTN1 và BTN2 trên bảng micro:bit) mỗi khi cổng nối tiếp được kết nối với thiết bị.

script.js - clickConnect()

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

Thử nào

Ngoài việc hiển thị khuôn mặt hạnh phúc khi được kết nối, việc nhấn một trong các nút trên micrô nhỏ:sẽ thêm văn bản vào trang cho biết nút nào đã được nhấn. Rất có thể mỗi ký tự sẽ nằm trên một dòng riêng.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Bạn sẽ thấy một khuôn mặt cười xuất hiện trên ma trận LED micro:bit.
  5. Nhấn vào các nút trên micrô nhỏ:và xác minh rằng nút này sẽ nối văn bản mới vào trang, trong đó có thông tin chi tiết về nút được nhấn.

Xử lý luồng cơ bản

Khi một trong các nút micro:bit được đẩy, micrô:bit sẽ gửi dữ liệu đến cổng nối tiếp thông qua luồng. Các luồng rất hữu ích nhưng chúng cũng có thể là một thách thức vì bạn sẽ không nhất thiết phải nhận tất cả dữ liệu cùng một lúc và việc đó có thể bị chia nhỏ tùy ý.

Ứng dụng này hiện in luồng đến khi đến (trong readLoop). Trong hầu hết các trường hợp, mỗi ký tự nằm trên một dòng riêng, nhưng điều đó không hữu ích. Lý tưởng nhất là luồng được phân tích cú pháp thành các dòng riêng lẻ, và mỗi thông báo hiển thị dưới dạng một dòng riêng.

Chuyển đổi luồng bằng TransformStream

Để làm việc đó, chúng ta có thể dùng luồng biến đổi (TransformStream), để có thể phân tích cú pháp luồng đến và trả về dữ liệu phân tích cú pháp. Luồng chuyển đổi có thể nằm giữa nguồn luồng (trong trường hợp này là micro:bit) và bất kỳ giá trị nào đang sử dụng luồng (trong trường hợp này là readLoop) và có thể áp dụng một phép biến đổi tùy ý trước khi luồng được sử dụng cuối cùng. Hãy xem đây là một tiện ích lắp ráp: Khi một tiện ích hoạt động ở cuối dòng, mỗi bước trong dòng sẽ sửa đổi tiện ích, vì vậy, khi chuyển đến đích cuối cùng, bạn sẽ thấy tiện ích đó có đầy đủ chức năng.

Để biết thêm thông tin, hãy xem bài viết Các khái niệm về API Luồng của MDN\39.

Chuyển đổi luồng bằng LineBreakTransformer

Hãy tạo một lớp LineBreakTransformer, lớp này sẽ lấy dữ liệu vào một luồng và phân đoạn dựa trên dấu ngắt dòng (\r\n). Lớp này cần có hai phương thức là transformflush. Phương thức transform được gọi mỗi khi luồng dữ liệu nhận được dữ liệu mới. Tùy chọn này có thể đưa dữ liệu vào hàng đợi hoặc lưu dữ liệu để dùng sau này. Phương thức flush được gọi khi luồng được xử lý và xử lý bất kỳ dữ liệu nào chưa được xử lý.

Trong phương thức transform, chúng tôi sẽ thêm dữ liệu mới vào container, sau đó kiểm tra xem có bất kỳ dấu ngắt dòng nào trong container hay không. Nếu có, hãy tách dòng đó thành một mảng, sau đó lặp qua các dòng và gọi controller.enqueue() để gửi các dòng được phân tích cú pháp.

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

Khi luồng đã đóng, chúng ta sẽ chỉ xóa mọi dữ liệu còn lại trong vùng chứa bằng cách sử dụng enqueue.

script.js - LineBreakTransformer.flush()

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

Cuối cùng, chúng ta cần kết hợp luồng đến qua LineBreakTransformer mới. Luồng đầu vào ban đầu của chúng tôi chỉ được lấy qua TextDecoderStream, vì vậy, chúng tôi cần thêm pipeThrough để thu thập dữ liệu qua LineBreakTransformer mới.

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

Thử nào

Bây giờ, khi bạn nhấn vào một trong các nút micro:bit, dữ liệu in sẽ được trả về trên một dòng.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Bạn sẽ thấy một khuôn mặt cười xuất hiện trên ma trận LED micro:bit.
  5. Nhấn các nút trên micrô nhỏ:và xác minh rằng bạn nhìn thấy nội dung như sau:

Chuyển đổi luồng bằng JSONTransformer

Chúng ta có thể cố gắng phân tích cú pháp chuỗi thành JSON trong readLoop, nhưng thay vào đó, hãy tạo một trình biến đổi JSON rất đơn giản để biến dữ liệu đó thành một đối tượng JSON. Nếu dữ liệu không phải là JSON hợp lệ, thì bạn chỉ cần trả về nội dung đã nhập.

script.js - JSONTransformer.transform

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

Tiếp theo, hãy phát trực tiếp qua JSONTransformer, sau khi truyền trực tiếp qua LineBreakTransformer. Điều này giúp chúng tôi giữ cho JSONTransformer luôn đơn giản, vì chúng tôi biết rằng JSON sẽ chỉ được gửi trên một dòng.

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

Thử nào

Bây giờ, khi nhấn vào một trong các nút vi:bit, bạn sẽ thấy [object Object] được in trên trang.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Bạn sẽ thấy một khuôn mặt cười xuất hiện trên ma trận LED micro:bit.
  5. Nhấn vào các nút trên micrô nhỏ:và xác minh rằng bạn thấy một số chi tiết như sau:

Phản hồi thao tác nhấn nút

Để phản hồi các lượt nhấn nút micro:bit, hãy cập nhật readLoop để kiểm tra xem dữ liệu mà bộ lọc có nhận được là object có thuộc tính button hay không. Sau đó, hãy gọi buttonPushed để xử lý thao tác nhấn nút.

script.js - readLoop()

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

Khi nhấn vào nút micro:bit, màn hình trên ma trận LED sẽ thay đổi. Dùng mã sau để đặt ma trận:

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

Thử nào

Giờ đây, khi nhấn vào một trong các nút micro:bit, ma trận LED sẽ chuyển thành khuôn mặt hạnh phúc hoặc khuôn mặt buồn.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Bạn sẽ thấy một khuôn mặt cười xuất hiện trên ma trận LED micro:bit.
  5. Nhấn vào các nút trên micrô nhỏ:và xác minh rằng ma trận LED thay đổi.

Bước cuối cùng là kết nối chức năng ngắt kết nối để đóng cổng khi người dùng hoàn tất.

Đóng cổng khi người dùng nhấp vào nút Kết nối/Ngắt kết nối

Khi người dùng nhấp vào nút Kết nối/Ngắt kết nối, chúng ta cần phải đóng kết nối. Nếu cổng đã mở, hãy gọi disconnect() và cập nhật giao diện người dùng để cho biết rằng trang không còn kết nối với thiết bị nối tiếp.

script.js - clickConnect()

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

Đóng các luồng và cổng

Trong hàm disconnect, chúng ta cần đóng luồng đầu vào, đóng luồng đầu ra và đóng cổng. Để đóng luồng đầu vào, hãy gọi reader.cancel(). Lệnh gọi đến cancel không đồng bộ, do đó, chúng ta cần phải sử dụng await để đợi quá trình này hoàn tất:

script.js - disconnect()

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

Để đóng luồng đầu ra, hãy lấy writer, gọi close() và đợi để đóng đối tượng outputDone:

script.js - disconnect()

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

Cuối cùng, hãy đóng cổng nối tiếp và chờ cổng đóng:

script.js - disconnect()

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

Thử nào

Bây giờ, bạn có thể mở và đóng cổng nối tiếp theo ý muốn.

  1. Tải lại trang.
  2. Nhấp vào nút Kết nối.
  3. Trong hộp thoại trình chọn Cổng nối tiếp, hãy chọn thiết bị micro:bit rồi nhấp vào Kết nối.
  4. Bạn sẽ thấy một khuôn mặt cười xuất hiện trên ma trận LED micro:bit
  5. Nhấn vào nút Ngắt kết nối và xác minh rằng ma trận LED tắt và không có lỗi nào trong bảng điều khiển.

Xin chúc mừng! Bạn đã xây dựng thành công ứng dụng web đầu tiên sử dụng API Web Serial.

Theo dõi https://goo.gle/fugu-api-tracker để biết thông tin mới nhất về API Web Serial và tất cả tính năng mới thú vị khác mà nhóm Chrome đang phát triển.