อ่านและเขียนไปยังพอร์ตอนุกรม

Web Serial API ช่วยให้เว็บไซต์สื่อสารกับอุปกรณ์แบบซีเรียลได้

François Beaufort
François Beaufort

Web Serial API คืออะไร

พอร์ตอนุกรมคืออินเทอร์เฟซการสื่อสารแบบ 2 ทิศทางที่ช่วยให้สามารถ การรับไบต์ข้อมูลไบต์ต่อไบต์

Web Serial API มีวิธีให้เว็บไซต์อ่านและเขียนไปยัง อุปกรณ์ซีเรียลด้วย JavaScript อุปกรณ์ซีเรียลจะเชื่อมต่อกันผ่าน พอร์ตอนุกรมบนระบบของผู้ใช้หรือผ่านอุปกรณ์ USB และบลูทูธแบบถอดได้ ที่จำลองพอร์ตอนุกรม

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

API นี้ยังเป็นส่วนเสริมที่ยอดเยี่ยมของ WebUSB เนื่องจากระบบปฏิบัติการต้องใช้ เพื่อสื่อสารกับพอร์ตอนุกรมบางพอร์ตโดยใช้ Serial API แทนที่จะเป็น USB API ระดับล่าง

Use Case ที่แนะนำ

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

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

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

สถานะปัจจุบัน

ขั้นตอน สถานะ
1. สร้างคำอธิบาย เสร็จสมบูรณ์
2. สร้างข้อกำหนดคร่าวๆ เบื้องต้น เสร็จสมบูรณ์
3. รวบรวมความคิดเห็นและ ทำซ้ำในการออกแบบ เสร็จสมบูรณ์
4. ช่วงทดลองใช้จากต้นทาง เสร็จสมบูรณ์
5. เปิดตัว เสร็จสมบูรณ์

การใช้ Web Serial API

การตรวจหาฟีเจอร์

หากต้องการตรวจสอบว่าระบบรองรับ Web Serial API หรือไม่ ให้ใช้รายการต่อไปนี้

if ("serial" in navigator) {
  // The Web Serial API is supported.
}

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

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

หากต้องการเปิดพอร์ตอนุกรม ให้เข้าถึงออบเจ็กต์ SerialPort ก่อน สำหรับขั้นตอนนี้ คุณสามารถ แจ้งให้ผู้ใช้เลือกพอร์ตอนุกรมเดียวโดยการเรียกใช้ navigator.serial.requestPort()เพื่อตอบสนองต่อท่าทางสัมผัสของผู้ใช้ เช่น การแตะ หรือคลิกเมาส์ หรือเลือกจาก navigator.serial.getPorts() ซึ่งแสดงผล รายการพอร์ตอนุกรมที่เว็บไซต์ได้รับสิทธิ์เข้าถึง

document.querySelector('button').addEventListener('click', async () => {
  // Prompt user to select any serial port.
  const port = await navigator.serial.requestPort();
});
// Get all serial ports the user has previously granted the website access to.
const ports = await navigator.serial.getPorts();

ฟังก์ชัน navigator.serial.requestPort() จะใช้ Object Literal ที่เป็นตัวเลือก ที่กำหนดตัวกรอง ใช้เพื่อจับคู่อุปกรณ์ซีเรียลที่เชื่อมต่อ USB พร้อมผู้ให้บริการ USB ที่จำเป็น (usbVendorId) และผลิตภัณฑ์ USB ที่ไม่บังคับ ตัวระบุ (usbProductId)

// Filter on devices with the Arduino Uno USB Vendor/Product IDs.
const filters = [
  { usbVendorId: 0x2341, usbProductId: 0x0043 },
  { usbVendorId: 0x2341, usbProductId: 0x0001 }
];

// Prompt user to select an Arduino Uno device.
const port = await navigator.serial.requestPort({ filters });

const { usbProductId, usbVendorId } = port.getInfo();
ภาพหน้าจอของข้อความแจ้งพอร์ตอนุกรมในเว็บไซต์
ข้อความแจ้งผู้ใช้ให้เลือก BBC micro:bit

การโทรหา requestPort() จะแจ้งให้ผู้ใช้เลือกอุปกรณ์และส่งคืน SerialPort ออบเจ็กต์ เมื่อคุณมีออบเจ็กต์ SerialPort กำลังเรียกใช้ port.open() ด้วยอัตรารับส่งข้อมูลที่ต้องการจะเปิดพอร์ตอนุกรม พจนานุกรม baudRate สมาชิกจะระบุความเร็วในการส่งข้อมูลผ่านบรรทัดอนุกรม โดยจะแสดงในรูปแบบ หน่วยบิตต่อวินาที (bps) โปรดอ่านเอกสารประกอบของอุปกรณ์เพื่อดูข้อมูลเกี่ยวกับ ค่าที่ถูกต้อง เนื่องจากข้อมูลทั้งหมดที่คุณส่งและรับจะเป็นคำที่ไม่มีความหมายหากสิ่งนี้ ระบุไม่ถูกต้อง สำหรับอุปกรณ์ USB และบลูทูธบางรุ่นที่จำลองซีเรียล สามารถตั้งค่านี้เป็นค่าใดๆ ก็ได้ เนื่องจากจะถูกละเว้น และการจำลอง

// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();

// Wait for the serial port to open.
await port.open({ baudRate: 9600 });

คุณจะระบุตัวเลือกใดก็ได้ด้านล่างเมื่อเปิดพอร์ตอนุกรม เหล่านี้ เป็นตัวเลือกและมีค่าเริ่มต้นที่สะดวก

  • dataBits: จำนวนบิตข้อมูลต่อเฟรม (7 หรือ 8 บิต)
  • stopBits: จำนวนบิตหยุดที่จุดสิ้นสุดของเฟรม (1 หรือ 2)
  • parity: โหมดความเท่าเทียม ("none", "even" หรือ "odd")
  • bufferSize: ขนาดของบัฟเฟอร์การอ่านและเขียนที่ควรสร้าง (ต้องมีขนาดไม่เกิน 16 MB)
  • flowControl: โหมดควบคุมโฟลว์ ("none" หรือ "hardware")

อ่านจากพอร์ตอนุกรม

สตรีมอินพุตและเอาต์พุตใน Web Serial API จะได้รับการจัดการโดย Streams API

หลังจากสร้างการเชื่อมต่อพอร์ตอนุกรม readable และ writable คุณสมบัติจากออบเจ็กต์ SerialPort จะแสดงผล ReadableStream และ WritableStream สถานที่เหล่านั้นจะใช้เพื่อรับข้อมูลจากและส่งข้อมูลไปยัง อุปกรณ์ซีเรียล ทั้ง 2 อินสแตนซ์ใช้อินสแตนซ์ Uint8Array สำหรับการโอนข้อมูล

เมื่อมีข้อมูลใหม่จากอุปกรณ์ซีเรียล port.readable.getReader().read() จะแสดงผลพร็อพเพอร์ตี้ 2 รายการแบบไม่พร้อมกัน: value และบูลีน done ถ้า done เป็นจริง พอร์ตอนุกรมถูกปิดหรือไม่มีข้อมูลเพิ่มเติม นิ้ว การเรียกใช้ port.readable.getReader() จะสร้างเครื่องอ่านและล็อก readable เป็น ได้ ขณะล็อก readable อยู่ คุณจะปิดพอร์ตอนุกรมไม่ได้

const reader = port.readable.getReader();

// Listen to data coming from the serial device.
while (true) {
  const { value, done } = await reader.read();
  if (done) {
    // Allow the serial port to be closed later.
    reader.releaseLock();
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

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

while (port.readable) {
  const reader = port.readable.getReader();

  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) {
        // Allow the serial port to be closed later.
        reader.releaseLock();
        break;
      }
      if (value) {
        console.log(value);
      }
    }
  } catch (error) {
    // TODO: Handle non-fatal read error.
  }
}

หากอุปกรณ์ซีเรียลส่งข้อความกลับมา คุณสามารถเชื่อมต่อ port.readable ผ่าน TextDecoderStream ดังที่แสดงด้านล่าง TextDecoderStream เป็นสตรีมการเปลี่ยนรูปแบบ ที่จับกลุ่ม Uint8Array ทั้งหมดมาแปลงเป็นสตริง

const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();

// Listen to data coming from the serial device.
while (true) {
  const { value, done } = await reader.read();
  if (done) {
    // Allow the serial port to be closed later.
    reader.releaseLock();
    break;
  }
  // value is a string.
  console.log(value);
}

คุณสามารถควบคุมวิธีจัดสรรหน่วยความจำเมื่อคุณอ่านจากสตรีมโดยใช้ "Bring Your Own Buffer" ผู้อ่าน โทรหา port.readable.getReader({ mode: "byob" }) เพื่อรับอินเทอร์เฟซ ReadableStreamBYOBReader และส่ง ArrayBuffer ของคุณเองเมื่อโทรหา read() โปรดทราบว่า Web Serial API รองรับฟีเจอร์นี้ใน Chrome 106 ขึ้นไป

try {
  const reader = port.readable.getReader({ mode: "byob" });
  // Call reader.read() to read data into a buffer...
} catch (error) {
  if (error instanceof TypeError) {
    // BYOB readers are not supported.
    // Fallback to port.readable.getReader()...
  }
}

ต่อไปนี้คือตัวอย่างวิธีใช้บัฟเฟอร์จาก value.buffer ซ้ำ

const bufferSize = 1024; // 1kB
let buffer = new ArrayBuffer(bufferSize);

// Set `bufferSize` on open() to at least the size of the buffer.
await port.open({ baudRate: 9600, bufferSize });

const reader = port.readable.getReader({ mode: "byob" });
while (true) {
  const { value, done } = await reader.read(new Uint8Array(buffer));
  if (done) {
    break;
  }
  buffer = value.buffer;
  // Handle `value`.
}

อีกตัวอย่างหนึ่งของวิธีอ่านข้อมูลในจำนวนที่ต้องการจากพอร์ตอนุกรมมีดังนี้

async function readInto(reader, buffer) {
  let offset = 0;
  while (offset < buffer.byteLength) {
    const { value, done } = await reader.read(
      new Uint8Array(buffer, offset)
    );
    if (done) {
      break;
    }
    buffer = value.buffer;
    offset += value.byteLength;
  }
  return buffer;
}

const reader = port.readable.getReader({ mode: "byob" });
let buffer = new ArrayBuffer(512);
// Read the first 512 bytes.
buffer = await readInto(reader, buffer);
// Then read the next 512 bytes.
buffer = await readInto(reader, buffer);

เขียนไปยังพอร์ตอนุกรม

หากต้องการส่งข้อมูลไปยังอุปกรณ์ซีเรียล ให้ส่งข้อมูลไปยัง port.writable.getWriter().write() กำลังใช้โทรหา releaseLock() ต้องใช้ port.writable.getWriter() จึงจะปิดพอร์ตอนุกรมได้ในภายหลัง

const writer = port.writable.getWriter();

const data = new Uint8Array([104, 101, 108, 108, 111]); // hello
await writer.write(data);


// Allow the serial port to be closed later.
writer.releaseLock();

ส่งข้อความไปยังอุปกรณ์ผ่าน TextEncoderStream ที่เชื่อมไปยัง port.writable ดังที่แสดงด้านล่าง

const textEncoder = new TextEncoderStream();
const writableStreamClosed = textEncoder.readable.pipeTo(port.writable);

const writer = textEncoder.writable.getWriter();

await writer.write("hello");

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

port.close() ปิดพอร์ตอนุกรมหากมีสมาชิก readable และ writable ปลดล็อกแล้ว ซึ่งหมายความว่าได้โทรหา releaseLock() สำหรับ นักอ่านและนักเขียน

await port.close();

อย่างไรก็ตาม เมื่ออ่านข้อมูลจากอุปกรณ์ซีเรียลอย่างต่อเนื่องโดยใช้การวนซ้ำ port.readable จะล็อกเสมอจนกว่าจะพบข้อผิดพลาด ด้วยวิธีนี้ การโทรหา reader.cancel() จะบังคับให้ reader.read() แก้ไข ทันทีด้วย { value: undefined, done: true } ซึ่งทำให้ วนซ้ำเพื่อโทรหา reader.releaseLock()

// Without transform streams.

let keepReading = true;
let reader;

async function readUntilClosed() {
  while (port.readable && keepReading) {
    reader = port.readable.getReader();
    try {
      while (true) {
        const { value, done } = await reader.read();
        if (done) {
          // reader.cancel() has been called.
          break;
        }
        // value is a Uint8Array.
        console.log(value);
      }
    } catch (error) {
      // Handle error...
    } finally {
      // Allow the serial port to be closed later.
      reader.releaseLock();
    }
  }

  await port.close();
}

const closedPromise = readUntilClosed();

document.querySelector('button').addEventListener('click', async () => {
  // User clicked a button to close the serial port.
  keepReading = false;
  // Force reader.read() to resolve immediately and subsequently
  // call reader.releaseLock() in the loop example above.
  reader.cancel();
  await closedPromise;
});

การปิดพอร์ตอนุกรมจะซับซ้อนมากขึ้นเมื่อใช้การแปลงสตรีม โทรหา reader.cancel() ตามปกติ จากนั้นโทรหา writer.close() และ port.close() การดำเนินการนี้จะแสดงข้อผิดพลาดผ่าน ระบบจะเปลี่ยนรูปแบบสตรีมไปยังพอร์ตอนุกรมที่อยู่ด้านล่าง เนื่องจากการเผยแพร่ข้อผิดพลาด จะไม่เกิดขึ้นทันที คุณต้องใช้ readableStreamClosed และ สัญญา writableStreamClosed ที่สร้างขึ้นก่อนหน้านี้เพื่อตรวจจับเมื่อ port.readable และ port.writable ถูกปลดล็อกแล้ว การยกเลิก reader จะทำให้ สตรีมที่จะถูกล้มเลิก นี่คือสาเหตุที่คุณต้องตรวจจับและเพิกเฉยต่อข้อผิดพลาดที่เกิดขึ้น

// With transform streams.

const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();

// Listen to data coming from the serial device.
while (true) {
  const { value, done } = await reader.read();
  if (done) {
    reader.releaseLock();
    break;
  }
  // value is a string.
  console.log(value);
}

const textEncoder = new TextEncoderStream();
const writableStreamClosed = textEncoder.readable.pipeTo(port.writable);

reader.cancel();
await readableStreamClosed.catch(() => { /* Ignore the error */ });

writer.close();
await writableStreamClosed;

await port.close();

ฟังการเชื่อมต่อและการตัดการเชื่อมต่อ

หากอุปกรณ์ USB ได้รับพอร์ตอนุกรม อุปกรณ์นั้นก็อาจเชื่อมต่ออยู่ หรือยกเลิกการเชื่อมต่อจากระบบ เมื่อเว็บไซต์ได้รับสิทธิ์ให้ เข้าถึงพอร์ตอนุกรม ซึ่งควรตรวจสอบเหตุการณ์ connect และ disconnect

navigator.serial.addEventListener("connect", (event) => {
  // TODO: Automatically open event.target or warn user a port is available.
});

navigator.serial.addEventListener("disconnect", (event) => {
  // TODO: Remove |event.target| from the UI.
  // If the serial port was opened, a stream error would be observed as well.
});

จัดการสัญญาณ

หลังจากสร้างการเชื่อมต่อพอร์ตอนุกรม คุณจะค้นหาและตั้งค่า สัญญาณที่พอร์ตอนุกรมได้เปิดเผยสำหรับการตรวจหาอุปกรณ์และการควบคุมโฟลว์ เหล่านี้ คือค่าบูลีน ตัวอย่างเช่น อุปกรณ์บางรุ่นอย่าง Arduino จะเข้าสู่โหมดการเขียนโปรแกรม หากสัญญาณ Data Terminal Ready (DTR) คือ สลับแล้ว

การตั้งค่าสัญญาณเอาต์พุตและการรับสัญญาณอินพุตจะดำเนินการตามลำดับโดย กำลังโทรหา port.setSignals() และ port.getSignals() ดูตัวอย่างการใช้งานด้านล่าง

// Turn off Serial Break signal.
await port.setSignals({ break: false });

// Turn on Data Terminal Ready (DTR) signal.
await port.setSignals({ dataTerminalReady: true });

// Turn off Request To Send (RTS) signal.
await port.setSignals({ requestToSend: false });
const signals = await port.getSignals();
console.log(`Clear To Send:       ${signals.clearToSend}`);
console.log(`Data Carrier Detect: ${signals.dataCarrierDetect}`);
console.log(`Data Set Ready:      ${signals.dataSetReady}`);
console.log(`Ring Indicator:      ${signals.ringIndicator}`);

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

เมื่อคุณรับข้อมูลจากอุปกรณ์ซีเรียล คุณอาจไม่เห็นข้อมูลทั้งหมด ข้อมูลพร้อมกัน อาจมีการแบ่งเป็นส่วนๆ โดยกฎเกณฑ์ สำหรับข้อมูลเพิ่มเติม โปรดดู แนวคิดของ Streams API

ในการจัดการกับปัญหานี้ คุณสามารถใช้สตรีมการเปลี่ยนรูปแบบในตัว เช่น TextDecoderStreamหรือสร้างสตรีมการเปลี่ยนรูปแบบของคุณเองซึ่งช่วยให้คุณ แยกวิเคราะห์สตรีมขาเข้าและส่งคืนข้อมูลที่แยกวิเคราะห์แล้ว สตรีมการเปลี่ยนรูปแบบ ระหว่างอุปกรณ์ซีเรียลและ Read Loop ที่ใช้สตรีมอยู่ ช่วย ใช้การแปลงที่กำหนดเองก่อนจะใช้ข้อมูล คิดเสียว่า บรรทัดการประกอบ: เมื่อวิดเจ็ตเลื่อนลงมา แต่ละขั้นตอนในเส้นจะปรับเปลี่ยน วิดเจ็ต ดังนั้น เมื่อถึงจุดหมายสุดท้าย วิดเจ็ตที่ทำงานได้

วันที่ รูปภาพโรงงานเครื่องบิน
โรงงานเครื่องบิน Castle Bromwich จากสงครามโลกครั้งที่ 2

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

หากต้องการใช้คลาสสตรีมการเปลี่ยนรูปแบบ คุณต้องไปป์สตรีมขาเข้าผ่าน ได้ ในตัวอย่างโค้ดที่ 3 ในส่วนอ่านจากพอร์ตอนุกรม สตรีมอินพุตเดิมเชื่อมต่อผ่าน TextDecoderStream เท่านั้น เราจึง จำเป็นต้องเรียกใช้ pipeThrough() เพื่อเชื่อมต่อกับ LineBreakTransformer ใหม่ของเรา

class LineBreakTransformer {
  constructor() {
    // A container for holding stream data until a new line.
    this.chunks = "";
  }

  transform(chunk, controller) {
    // Append new chunks to existing chunks.
    this.chunks += chunk;
    // For each line breaks in chunks, send the parsed lines out.
    const lines = this.chunks.split("\r\n");
    this.chunks = lines.pop();
    lines.forEach((line) => controller.enqueue(line));
  }

  flush(controller) {
    // When the stream is closed, flush any remaining chunks out.
    controller.enqueue(this.chunks);
  }
}
const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable
  .pipeThrough(new TransformStream(new LineBreakTransformer()))
  .getReader();

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

const [appReadable, devReadable] = port.readable.tee();

// You may want to update UI with incoming data from appReadable
// and log incoming data in JS console for inspection from devReadable.

เพิกถอนสิทธิ์เข้าถึงพอร์ตอนุกรม

เว็บไซต์ล้างสิทธิ์เข้าถึงพอร์ตอนุกรมที่ไม่ได้ใช้งานแล้วได้ สนใจเก็บรักษาข้อมูลโดยเรียกใช้ forget() ในอินสแตนซ์ SerialPort สำหรับ ตัวอย่างเช่น สำหรับเว็บแอปพลิเคชันด้านการศึกษาที่ใช้ในคอมพิวเตอร์ที่ใช้ร่วมกันกับ อุปกรณ์ต่างๆ เป็นจำนวนมาก สิทธิ์ที่ผู้ใช้สร้างขึ้นจำนวนมาก ประสบการณ์ของผู้ใช้

// Voluntarily revoke access to this serial port.
await port.forget();

เนื่องจาก forget() พร้อมใช้งานใน Chrome 103 ขึ้นไป โปรดตรวจสอบว่าฟีเจอร์นี้ ที่รองรับรายการต่อไปนี้

if ("serial" in navigator && "forget" in SerialPort.prototype) {
  // forget() is supported.
}

เคล็ดลับสำหรับนักพัฒนาซอฟต์แวร์

การแก้ไขข้อบกพร่องของ Web Serial API ใน Chrome นั้นทำได้ง่ายๆ ด้วยหน้าเว็บภายใน about://device-log ซึ่งคุณจะดูเหตุการณ์ทั้งหมดที่เกี่ยวข้องกับอุปกรณ์แบบอนุกรมได้จากแพลตฟอร์มเดียว ที่เดียว

วันที่ ภาพหน้าจอของหน้าเว็บภายในสำหรับแก้ไขข้อบกพร่องของ Web Serial API
หน้าภายในใน Chrome สำหรับแก้ไขข้อบกพร่องของ Web Serial API

Codelab

ใน Google Developer Codelab คุณจะใช้ Web Serial API เพื่อโต้ตอบ ด้วยบอร์ด BBC micro:bit เพื่อแสดงภาพบนเมทริกซ์ LED 5x5

การสนับสนุนเบราว์เซอร์

Web Serial API พร้อมใช้งานบนแพลตฟอร์มเดสก์ท็อปทั้งหมด (ChromeOS, Linux, macOS, และ Windows) ใน Chrome 89

ใยโพลีเอสเตอร์

ใน Android คุณจะรองรับพอร์ตอนุกรมแบบ USB ได้โดยใช้ WebUSB API และ Serial API polyfill โพลีฟิลล์นี้จำกัดเฉพาะฮาร์ดแวร์และ แพลตฟอร์มที่อุปกรณ์สามารถเข้าถึงได้ผ่าน WebUSB API เนื่องจากอุปกรณ์ไม่ได้ ถูกอ้างสิทธิ์โดยไดรเวอร์อุปกรณ์ในตัว

ความปลอดภัยและความเป็นส่วนตัว

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

หากต้องการทำความเข้าใจเกี่ยวกับข้อดีและข้อเสียของความปลอดภัย โปรดดูที่ความปลอดภัยและความเป็นส่วนตัว บางส่วนของ Web Serial API Explainer

ความคิดเห็น

ทีม Chrome อยากทราบความคิดเห็นและประสบการณ์ของคุณเกี่ยวกับ Web Serial API

บอกเราเกี่ยวกับการออกแบบ API

มีบางอย่างเกี่ยวกับ API ที่ไม่ทำงานตามที่คาดไว้หรือไม่ หรือมี วิธีการหรือคุณสมบัติที่จำเป็นไม่ครบที่คุณต้องการนำไอเดียไปปฏิบัติ

ส่งปัญหาด้านข้อมูลจำเพาะในที่เก็บ GitHub ของ Web Serial API หรือเพิ่ม ความคิดเกี่ยวกับปัญหาที่มีอยู่

รายงานปัญหาเกี่ยวกับการติดตั้งใช้งาน

คุณพบข้อบกพร่องในการติดตั้งใช้งาน Chrome ไหม หรือเป็นการติดตั้งใช้งาน แตกต่างจากข้อกำหนด

รายงานข้อบกพร่องที่ https://new.crbug.com ตรวจสอบว่าได้ใส่ ให้ละเอียดที่สุด บอกวิธีการง่ายๆ ในการจำลองข้อผิดพลาดซ้ำ ตั้งค่าคอมโพเนนต์เป็น Blink>Serial Glitch เหมาะสำหรับ แชร์ตัวอย่างผลงานที่ง่ายและรวดเร็ว

แสดงการสนับสนุน

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

ส่งทวีตไปยัง @ChromiumDev โดยใช้แฮชแท็ก #SerialAPI และแจ้งให้เราทราบถึงตำแหน่งและวิธีที่คุณใช้งาน

ลิงก์ที่มีประโยชน์

เดโม

กิตติกรรมประกาศ

ขอขอบคุณ Reilly Grant และ Joe Medley สำหรับการรีวิวบทความนี้ รูปภาพโรงงานเครื่องบินโดย Birmingham Museums Trust ใน Unsplash