किसी सीरियल पोर्ट से पढ़ें और उस पर लिखें

Web Serial API की मदद से, वेबसाइटें सीरियल डिवाइसों से संपर्क कर सकती हैं.

François Beaufort
François Beaufort

Web Serial API क्या है?

सीरियल पोर्ट, एक ऐसा इंटरफ़ेस है जो डेटा को एक से ज़्यादा डिवाइसों के बीच भेजने और पाने की सुविधा देता है.

Web Serial API की मदद से, वेबसाइटें JavaScript की मदद से सीरियल डिवाइस से डेटा पढ़ सकती हैं और उसमें डेटा लिख सकती हैं. सीरियल डिवाइसों को उपयोगकर्ता के सिस्टम पर मौजूद सीरियल पोर्ट से या फिर यूएसबी और ब्लूटूथ के ऐसे डिवाइसों से कनेक्ट किया जाता है जो सीरियल पोर्ट की तरह काम करते हैं.

दूसरे शब्दों में, Web Serial API, वेबसाइटों को माइक्रोकंट्रोलर और 3D प्रिंटर जैसे सीरियल डिवाइसों के साथ इंटरैक्ट करने की अनुमति देकर, वेब और फ़िज़िकल वर्ल्ड को जोड़ता है.

यह एपीआई, WebUSB के साथ भी बेहतर तरीके से काम करता है. ऐसा इसलिए है, क्योंकि ऑपरेटिंग सिस्टम के लिए ज़रूरी है कि ऐप्लिकेशन, कुछ सीरियल पोर्ट के साथ कम लेवल के यूएसबी एपीआई के बजाय, अपने हाई लेवल के सीरियल एपीआई का इस्तेमाल करके कम्यूनिकेट करें.

इस्तेमाल के सुझाए गए उदाहरण

शिक्षा, शौकिया, और औद्योगिक क्षेत्रों में उपयोगकर्ता, सहायक डिवाइस (जैसे, कीबोर्ड, माउस, मॉनिटर, वेबकैम वगैरह) को अपने कंप्यूटर से कनेक्ट करते हैं. आम तौर पर, इन डिवाइसों को कस्टम सॉफ़्टवेयर के ज़रिए इस्तेमाल किए जाने वाले सीरियल कनेक्शन के ज़रिए, माइक्रोकंट्रोलर से कंट्रोल किया जाता है. इन डिवाइसों को कंट्रोल करने के लिए, कुछ कस्टम सॉफ़्टवेयर वेब टेक्नोलॉजी के साथ बनाए गए हैं:

कुछ मामलों में, वेबसाइटें ऐसे एजेंट ऐप्लिकेशन के ज़रिए डिवाइस से संपर्क करती हैं जिसे उपयोगकर्ता मैन्युअल रूप से इंस्टॉल करते हैं. कुछ मामलों में, ऐप्लिकेशन को Electron जैसे फ़्रेमवर्क की मदद से, पैकेज किए गए ऐप्लिकेशन के तौर पर डिलीवर किया जाता है. अन्य मामलों में, उपयोगकर्ता को एक अतिरिक्त चरण पूरा करना पड़ता है, जैसे कि यूएसबी फ़्लैश ड्राइव के ज़रिए, कंपाइल किए गए ऐप्लिकेशन को डिवाइस पर कॉपी करना.

इन सभी मामलों में, वेबसाइट और उसके ज़रिए कंट्रोल किए जाने वाले डिवाइस के बीच सीधे कम्यूनिकेशन से उपयोगकर्ता अनुभव को बेहतर बनाया जाएगा.

मौजूदा स्थिति

चरण स्थिति
1. एक्सप्लेनर वीडियो बनाना पूरा हुआ
2. स्पेसिफ़िकेशन का शुरुआती ड्राफ़्ट बनाना पूरा हुआ
3. लोगों के सुझाव, राय या शिकायतें इकट्ठा करें और डिज़ाइन पर दोहराएं पूरा हुआ
4. ऑरिजिन ट्रायल पूरा हुआ
5. लॉन्च करें पूरा हो गया

Web Serial API का इस्तेमाल करना

फ़ीचर का पता लगाना

यह देखने के लिए कि Web Serial API काम करता है या नहीं, इनका इस्तेमाल करें:

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

सीरियल पोर्ट खोलना

Web Serial API, डिज़ाइन के हिसाब से असाइनोक्रोनस है. इससे, वेबसाइट के यूज़र इंटरफ़ेस (यूआई) को इनपुट मिलने का इंतज़ार करते समय ब्लॉक होने से रोका जाता है. यह ज़रूरी है, क्योंकि सीरियल डेटा कभी भी मिल सकता है. इसलिए, उसे सुनने का तरीका होना चाहिए.

सीरियल पोर्ट खोलने के लिए, पहले 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() फ़ंक्शन, फ़िल्टर को परिभाषित करने वाला वैकल्पिक ऑब्जेक्ट लिटरल लेता है. इनका इस्तेमाल, यूएसबी से कनेक्ट किए गए किसी भी सीरियल डिवाइस को ज़रूरी यूएसबी वेंडर (usbVendorId) और वैकल्पिक यूएसबी प्रॉडक्ट आइडेंटिफ़ायर (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 डिक्शनरी के सदस्य से पता चलता है कि सीरियल लाइन पर डेटा कितनी तेज़ी से भेजा जाता है. इसे बिट प्रति सेकंड (बीपीएस) की यूनिट में दिखाया जाता है. सही वैल्यू के लिए, अपने डिवाइस के दस्तावेज़ देखें. अगर यह वैल्यू गलत तरीके से दी गई है, तो भेजा और पाया गया सारा डेटा बेमतलब का होगा. सीरियल पोर्ट को एमुलेट करने वाले कुछ यूएसबी और ब्लूटूथ डिवाइसों के लिए, इस वैल्यू को किसी भी वैल्यू पर सेट किया जा सकता है. ऐसा इसलिए किया जा सकता है, क्योंकि एमुलेटर इस वैल्यू को अनदेखा कर देता है.

// 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 एमबी से कम होना चाहिए).
  • flowControl: फ़्लो कंट्रोल मोड ("none" या "hardware").

किसी सीरियल पोर्ट से पढ़ना

Web Serial API में इनपुट और आउटपुट स्ट्रीम को Streams API मैनेज करता है.

सीरियल पोर्ट कनेक्शन बन जाने के बाद, SerialPort ऑब्जेक्ट की readable और writable प्रॉपर्टी, ReadableStream और WritableStream दिखाती हैं. इनका इस्तेमाल, सीरियल डिवाइस से डेटा पाने और उसमें डेटा भेजने के लिए किया जाएगा. दोनों, डेटा ट्रांसफ़र के लिए Uint8Array इंस्टेंस का इस्तेमाल करते हैं.

जब सीरियल डिवाइस से नया डेटा आता है, तो port.readable.getReader().read() दो प्रॉपर्टी को अलग-अलग समय पर दिखाता है: 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);
}

"अपना बफ़र लाएं" रीडर का इस्तेमाल करके, स्ट्रीम से पढ़ते समय यह कंट्रोल किया जा सकता है कि मेमोरी कैसे असाइन की जाए. ReadableStreamBYOBReader इंटरफ़ेस पाने के लिए, port.readable.getReader({ mode: "byob" }) को कॉल करें. साथ ही, read() को कॉल करते समय अपना ArrayBuffer दें. ध्यान दें कि 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() को कॉल करें. इससे, ट्रांसफ़ॉर्म स्ट्रीम के ज़रिए, गड़बड़ियां सीरियल पोर्ट पर भेजी जाती हैं. गड़बड़ी का प्रसार तुरंत नहीं होता. इसलिए, port.readable और port.writable के अनलॉक होने का पता लगाने के लिए, आपको पहले से बनाए गए readableStreamClosed और writableStreamClosed प्रॉमिस का इस्तेमाल करना होगा. 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();

कनेक्ट और डिसकनेक्ट होने की जानकारी सुनना

अगर सीरियल पोर्ट को यूएसबी डिवाइस से मिला है, तो हो सकता है कि वह डिवाइस, सिस्टम से कनेक्ट या डिसकनेक्ट हो. जब वेबसाइट को किसी सीरियल पोर्ट को ऐक्सेस करने की अनुमति मिलती है, तो उसे 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 जैसे कुछ डिवाइस, डेटा टर्मिनल रेडी (डीटीआर) सिग्नल को टॉगल करने पर प्रोग्रामिंग मोड में चले जाएंगे.

आउटपुट सिग्नल सेट करने और इनपुट सिग्नल पाने के लिए, 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 जैसी कुछ पहले से मौजूद ट्रांसफ़ॉर्म स्ट्रीम का इस्तेमाल किया जा सकता है. इसके अलावा, अपनी ट्रांसफ़ॉर्म स्ट्रीम भी बनाई जा सकती है. इससे, आने वाली स्ट्रीम को पार्स करके, पार्स किया गया डेटा वापस पाया जा सकता है. ट्रांसफ़ॉर्म स्ट्रीम, सीरियल डिवाइस और रीड लूप के बीच होती है. यह डेटा इस्तेमाल किए जाने से पहले, अपनी पसंद के मुताबिक ट्रांसफ़ॉर्म लागू कर सकता है. इसे किसी असेंबली लाइन की तरह समझें: जैसे ही विजेट लाइन पर आता है, लाइन का हर चरण विजेट में बदलाव करता है, ताकि आखिरी डेस्टिनेशन तक पहुंचने से पहले, वह पूरी तरह से काम करने वाला विजेट हो.

हवाई जहाज़ की फ़ैक्ट्री की फ़ोटो
World War II Castle Bromwich Aeroplane Factory

उदाहरण के लिए, ट्रांसफ़ॉर्म स्ट्रीम क्लास बनाने का तरीका जानें. यह क्लास, स्ट्रीम का इस्तेमाल करती है और लाइन ब्रेक के आधार पर उसे अलग-अलग हिस्सों में बांटती है. जब भी स्ट्रीम को नया डेटा मिलता है, तब इसके transform() तरीके को कॉल किया जाता है. यह डेटा को सूची में जोड़ सकता है या बाद में इस्तेमाल करने के लिए सेव कर सकता है. flush() वाले तरीके को तब कॉल किया जाता है, जब स्ट्रीम बंद हो जाती है. साथ ही, यह ऐसे डेटा को हैंडल करता है जिसे अभी तक प्रोसेस नहीं किया गया है.

ट्रांसफ़ॉर्म स्ट्रीम क्लास का इस्तेमाल करने के लिए, आपको आने वाली स्ट्रीम को इसके ज़रिए भेजना होगा. सीरियल पोर्ट से पढ़ना में दिए गए तीसरे कोड के उदाहरण में, ओरिजनल इनपुट स्ट्रीम को सिर्फ़ TextDecoderStream के ज़रिए पाइप किया गया था. इसलिए, इसे अपने नए LineBreakTransformer के ज़रिए पाइप करने के लिए, हमें pipeThrough() को कॉल करना होगा.

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

सीरियल डिवाइस के कम्यूनिकेशन से जुड़ी समस्याओं को डीबग करने के लिए, port.readable के tee() तरीके का इस्तेमाल करके, सीरियल डिवाइस पर आने वाली या उससे अलग-अलग स्ट्रीम को अलग-अलग करें. बनाई गई दो स्ट्रीम को अलग-अलग इस्तेमाल किया जा सकता है. इसकी मदद से, जांच के लिए एक स्ट्रीम को कंसोल में प्रिंट किया जा सकता है.

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.

सीरियल पोर्ट का ऐक्सेस वापस लेना

वेबसाइट, SerialPort इंस्टेंस पर forget() को कॉल करके, उस सीरियल पोर्ट को ऐक्सेस करने की अनुमतियों को हटा सकती है जिसे अब उसे ऐक्सेस नहीं करना है. उदाहरण के लिए, कई डिवाइसों के साथ शेयर किए गए कंप्यूटर पर इस्तेमाल किए जाने वाले किसी शिक्षा से जुड़े वेब ऐप्लिकेशन के लिए, उपयोगकर्ता से मिली अनुमतियों की बड़ी संख्या से उपयोगकर्ता अनुभव खराब हो जाता है.

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

Chrome 103 या इसके बाद के वर्शन में forget() उपलब्ध है. इसलिए, देखें कि यह सुविधा इनके साथ काम करती है या नहीं:

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

डेवलपर के लिए सलाह

Chrome में वेब सीरियल एपीआई को डीबग करना आसान है. इसके लिए, इंटरनल पेज about://device-log का इस्तेमाल करें. यहां आपको सीरियल डिवाइस से जुड़े सभी इवेंट एक ही जगह पर दिखेंगे.

Web Serial API को डीबग करने के लिए, इंटरनल पेज का स्क्रीनशॉट.
Web Serial API को डीबग करने के लिए, Chrome का इंटरनल पेज.

कोडलैब (कोड बनाना सीखना)

Google Developer कोडलैब में, 5x5 एलईडी मैट्रिक्स पर इमेज दिखाने के लिए, आपको वेब सीरियल एपीआई का इस्तेमाल करना होगा. इससे BBC माइक्रो:बिट बोर्ड का इस्तेमाल करके, उसके साथ इंटरैक्ट किया जा सकता है.

ब्राउज़र समर्थन

वेब सीरियल एपीआई, Chrome 89 में सभी डेस्कटॉप प्लैटफ़ॉर्म (ChromeOS, Linux, macOS, और Windows) पर उपलब्ध है.

Polyfill

Android पर, यूएसबी पर आधारित सीरियल पोर्ट के लिए, WebUSB API और Serial API polyfill का इस्तेमाल किया जा सकता है. यह पॉलीफ़िल सिर्फ़ उन हार्डवेयर और प्लैटफ़ॉर्म तक सीमित है जहां डिवाइस को WebUSB API की मदद से ऐक्सेस किया जा सकता है. ऐसा इसलिए, क्योंकि डिवाइस के ड्राइवर ने इस पर दावा नहीं किया है.

सुरक्षा और निजता

स्पेसिफ़िकेशन के लेखकों ने Web Serial API को डिज़ाइन और लागू किया है. इसके लिए, उन्होंने वेब प्लैटफ़ॉर्म की बेहतर सुविधाओं के ऐक्सेस को कंट्रोल करना में बताए गए मुख्य सिद्धांतों का इस्तेमाल किया है. इनमें उपयोगकर्ता कंट्रोल, पारदर्शिता, और काम करने के तरीके से जुड़े सिद्धांत शामिल हैं. इस एपीआई का इस्तेमाल करने की अनुमति, मुख्य रूप से एक अनुमति मॉडल के हिसाब से दी जाती है. यह मॉडल, एक बार में सिर्फ़ एक सीरियल डिवाइस का ऐक्सेस देता है. उपयोगकर्ता के प्रॉम्प्ट के जवाब में, उपयोगकर्ता को किसी खास सीरियल डिवाइस को चुनने के लिए, सक्रिय कार्रवाई करनी होगी.

सुरक्षा से जुड़े समझौते को समझने के लिए, Web Serial API के बारे में जानकारी देने वाले पेज पर मौजूद सुरक्षा और निजता सेक्शन देखें.

सुझाव/राय दें या शिकायत करें

Chrome की टीम को Web Serial API के बारे में आपके विचार और अनुभव जानने में दिलचस्पी होगी.

हमें एपीआई के डिज़ाइन के बारे में बताएं

क्या एपीआई में कोई ऐसी चीज़ है जो उम्मीद के मुताबिक काम नहीं करती? क्या आपके आइडिया को लागू करने के लिए, कोई ऐसा तरीका या प्रॉपर्टी मौजूद नहीं है?

Web Serial API GitHub के रेपो पर, शर्त से जुड़ी कोई समस्या दर्ज करें या किसी मौजूदा समस्या में अपने विचार जोड़ें.

लागू करने से जुड़ी समस्या की शिकायत करना

क्या आपको Chrome में इस सुविधा को लागू करने में कोई गड़बड़ी मिली? या क्या इसे लागू करने का तरीका, स्पेसिफ़िकेशन से अलग है?

https://new.crbug.com पर जाकर, गड़बड़ी की शिकायत करें. इसमें ज़्यादा से ज़्यादा जानकारी शामिल करें. साथ ही, गड़बड़ी को दोहराने के लिए आसान निर्देश दें. साथ ही, Components को Blink>Serial पर सेट करें. Glitch, कॉन्टेंट को तुरंत और आसानी से शेयर करने के लिए शानदार काम करता है.

क्रिएटर के लिए अपना सपोर्ट दिखाना

क्या आपको Web Serial API इस्तेमाल करना है? सार्वजनिक तौर पर सहायता पाने से, Chrome टीम को सुविधाओं को प्राथमिकता देने में मदद मिलती है. साथ ही, इससे ब्राउज़र के अन्य वेंडर को यह पता चलता है कि इन सुविधाओं को उपलब्ध कराना कितना ज़रूरी है.

#SerialAPI हैशटैग का इस्तेमाल करके, @ChromiumDev को ट्वीट करें और हमें बताएं कि इसका इस्तेमाल कहां और कैसे किया जा रहा है.

मदद के लिए लिंक

डेमो

धन्यवाद

इस लेख की समीक्षा करने के लिए, रेली ग्रांट और जो मेडली का धन्यवाद. अनस्प्लैश पर बर्मिंघम म्यूज़ियम्स ट्रस्ट की ओर से हवाई जहाज़ फ़ैक्ट्री की फ़ोटो.