সিরিয়াল পোর্ট থেকে পড়ুন এবং লিখুন

ওয়েব সিরিয়াল এপিআই ওয়েবসাইটগুলোকে সিরিয়াল ডিভাইসের সাথে যোগাযোগ করতে সক্ষম করে।

ফ্রাঁসোয়া বোফোর্ট
François Beaufort

What is the Web Serial API?

সিরিয়াল পোর্ট হলো একটি দ্বিমুখী যোগাযোগ ইন্টারফেস যা বাইট বাইট করে ডেটা পাঠানো এবং গ্রহণ করার সুযোগ দেয়।

ওয়েব সিরিয়াল এপিআই ওয়েবসাইটগুলোকে জাভাস্ক্রিপ্ট ব্যবহার করে কোনো সিরিয়াল ডিভাইস থেকে ডেটা পড়া এবং তাতে লেখার সুযোগ করে দেয়। সিরিয়াল ডিভাইসগুলো ব্যবহারকারীর সিস্টেমের সিরিয়াল পোর্টের মাধ্যমে অথবা সিরিয়াল পোর্টের অনুকরণকারী অপসারণযোগ্য ইউএসবি ও ব্লুটুথ ডিভাইসের মাধ্যমে সংযুক্ত করা হয়।

অন্য কথায়, ওয়েব সিরিয়াল এপিআই ওয়েবসাইটগুলোকে মাইক্রোকন্ট্রোলার এবং থ্রিডি প্রিন্টারের মতো সিরিয়াল ডিভাইসগুলোর সাথে যোগাযোগ করার সুযোগ দিয়ে ওয়েব এবং বাস্তব জগতের মধ্যে সংযোগ স্থাপন করে।

এই এপিআইটি ওয়েবইউএসবি -র একটি চমৎকার পরিপূরক, কারণ অপারেটিং সিস্টেমগুলো অ্যাপ্লিকেশনগুলোকে কিছু সিরিয়াল পোর্টের সাথে যোগাযোগের জন্য নিম্ন-স্তরের ইউএসবি এপিআই-এর পরিবর্তে তাদের উচ্চ-স্তরের সিরিয়াল এপিআই ব্যবহার করতে বলে।

Suggested use cases

শিক্ষা, শখ এবং শিল্প খাতে ব্যবহারকারীরা তাদের কম্পিউটারের সাথে পেরিফেরাল ডিভাইস সংযুক্ত করেন। এই ডিভাইসগুলো প্রায়শই কাস্টম সফটওয়্যার দ্বারা ব্যবহৃত সিরিয়াল সংযোগের মাধ্যমে মাইক্রোকন্ট্রোলার দ্বারা নিয়ন্ত্রিত হয়। এই ডিভাইসগুলো নিয়ন্ত্রণের জন্য কিছু কাস্টম সফটওয়্যার ওয়েব প্রযুক্তি ব্যবহার করে তৈরি করা হয়:

কিছু ক্ষেত্রে, ওয়েবসাইটগুলো একটি এজেন্ট অ্যাপ্লিকেশনের মাধ্যমে ডিভাইসের সাথে যোগাযোগ করে, যা ব্যবহারকারীরা ম্যানুয়ালি ইনস্টল করে। অন্য ক্ষেত্রে, অ্যাপ্লিকেশনটি ইলেকট্রনের মতো কোনো ফ্রেমওয়ার্কের মাধ্যমে একটি প্যাকেজড অ্যাপ্লিকেশন হিসেবে সরবরাহ করা হয়। আবার অন্য কিছু ক্ষেত্রে, ব্যবহারকারীকে একটি অতিরিক্ত পদক্ষেপ নিতে হয়, যেমন একটি ইউএসবি ফ্ল্যাশ ড্রাইভের মাধ্যমে কম্পাইল করা অ্যাপ্লিকেশনটি ডিভাইসে কপি করা।

এই সমস্ত ক্ষেত্রে, ওয়েবসাইট এবং এটি দ্বারা নিয়ন্ত্রিত ডিভাইসটির মধ্যে সরাসরি যোগাযোগের ব্যবস্থা করলে ব্যবহারকারীর অভিজ্ঞতা উন্নত হবে।

Current status

ধাপ অবস্থা
1. Create explainer সম্পূর্ণ
2. Create initial draft of specification সম্পূর্ণ
3. Gather feedback & iterate on design সম্পূর্ণ
4. Origin trial সম্পূর্ণ
5. Launch সম্পূর্ণ

Using the Web Serial API

বৈশিষ্ট্য সনাক্তকরণ

ওয়েব সিরিয়াল এপিআই সমর্থিত কিনা তা পরীক্ষা করতে, ব্যবহার করুন:

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

Open a serial port

ওয়েব সিরিয়াল এপিআই স্বভাবতই অ্যাসিঙ্ক্রোনাস। এর ফলে ইনপুটের জন্য অপেক্ষা করার সময় ওয়েবসাইটের ইউজার ইন্টারফেস (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();

The navigator.serial.requestPort() function takes an optional object literal that defines filters. Those are used to match any serial device connected over USB with a mandatory USB vendor ( usbVendorId ) and optional USB product identifiers ( 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();
Screenshot of a serial port prompt on a website
User prompt for selecting a BBC micro:bit

requestPort() কল করলে ব্যবহারকারীকে একটি ডিভাইস বেছে নিতে বলা হয় এবং একটি SerialPort অবজেক্ট রিটার্ন করা হয়। একবার আপনার কাছে একটি SerialPort অবজেক্ট চলে এলে, কাঙ্ক্ষিত বড রেট (baud rate) সহ 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 : প্রতি ফ্রেমে ডেটা বিটের সংখ্যা (৭ অথবা ৮)।
  • stopBits : একটি ফ্রেমের শেষে স্টপ বিটের সংখ্যা (১ অথবা ২)।
  • parity : জোড়-বিজোড় মোড (হয় "none" , "even" অথবা "odd" )।
  • bufferSize : যে রিড এবং রাইট বাফারগুলো তৈরি করা হবে তার আকার (অবশ্যই ১৬ মেগাবাইটের কম হতে হবে)।
  • flowControl : প্রবাহ নিয়ন্ত্রণ মোড ( "none" অথবা "hardware" )।

Read from a serial port

ওয়েব সিরিয়াল এপিআই-এর ইনপুট ও আউটপুট স্ট্রিমগুলো স্ট্রিমস এপিআই দ্বারা পরিচালিত হয়।

After the serial port connection is established, the readable and writable properties from the SerialPort object return a ReadableStream and a WritableStream . Those will be used to receive data from and send data to the serial device. Both use Uint8Array instances for data transfer.

যখন সিরিয়াল ডিভাইস থেকে নতুন ডেটা আসে, তখন port.readable.getReader().read() অ্যাসিঙ্ক্রোনাসভাবে দুটি প্রোপার্টি রিটার্ন করে: value এবং একটি done বুলিয়ান। যদি done মান true হয়, তার মানে সিরিয়াল পোর্টটি বন্ধ হয়ে গেছে অথবা আর কোনো ডেটা আসছে না। 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 নাল (null) হয়ে যায়।

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

If the serial device sends text back, you can pipe port.readable through a TextDecoderStream as shown below. A TextDecoderStream is a transform stream that grabs all Uint8Array chunks and converts them to strings.

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 প্রদান করুন। উল্লেখ্য যে, ওয়েব সিরিয়াল এপিআই ক্রোম ১০৬ বা তার পরবর্তী সংস্করণগুলিতে এই বৈশিষ্ট্যটি সমর্থন করে।

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

Write to a serial port

সিরিয়াল ডিভাইসে ডেটা পাঠাতে, port.writable.getWriter().write() -এ ডেটা পাস করুন। পরবর্তীতে সিরিয়াল পোর্টটি বন্ধ করার জন্য port.writable.getWriter() -এ releaseLock() কল করা আবশ্যক।

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

নিচে দেখানো অনুযায়ী port.writable এ পাইপ করা একটি TextEncoderStream এর মাধ্যমে ডিভাইসে টেক্সট পাঠান।

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

const writer = textEncoder.writable.getWriter();

await writer.write("hello");

Close a serial port

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

Listen to connection and disconnection

যদি কোনো ইউএসবি ডিভাইসের মাধ্যমে সিরিয়াল পোর্ট সরবরাহ করা হয়, তবে সেই ডিভাইসটি সিস্টেমের সাথে সংযুক্ত বা বিচ্ছিন্ন হতে পারে। যখন কোনো ওয়েবসাইটকে সিরিয়াল পোর্ট অ্যাক্সেস করার অনুমতি দেওয়া হয়, তখন সেটির 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.
});

Handle signals

সিরিয়াল পোর্ট সংযোগ স্থাপন করার পর, আপনি ডিভাইস শনাক্তকরণ এবং প্রবাহ নিয়ন্ত্রণের জন্য সিরিয়াল পোর্ট দ্বারা উন্মুক্ত সিগন্যালগুলো স্পষ্টভাবে জিজ্ঞাসা ও সেট করতে পারেন। এই সিগন্যালগুলো বুলিয়ান মান হিসেবে সংজ্ঞায়িত করা হয়। উদাহরণস্বরূপ, আরডুইনোর মতো কিছু ডিভাইস প্রোগ্রামিং মোডে প্রবেশ করবে যদি ডেটা টার্মিনাল রেডি (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}`);

Transforming streams

যখন আপনি সিরিয়াল ডিভাইস থেকে ডেটা গ্রহণ করেন, তখন আপনি সব ডেটা একবারে নাও পেতে পারেন। এটি যথেচ্ছভাবে খণ্ডে বিভক্ত হতে পারে। আরও তথ্যের জন্য, স্ট্রিমস এপিআই কনসেপ্টস (Streams API concepts) দেখুন।

এর সমাধান করতে, আপনি TextDecoderStream এর মতো কিছু বিল্ট-ইন ট্রান্সফর্ম স্ট্রিম ব্যবহার করতে পারেন অথবা আপনার নিজস্ব ট্রান্সফর্ম স্ট্রিম তৈরি করতে পারেন, যা আপনাকে আগত স্ট্রিমটি পার্স করতে এবং পার্স করা ডেটা ফেরত দিতে সাহায্য করে। ট্রান্সফর্ম স্ট্রিমটি সিরিয়াল ডিভাইস এবং স্ট্রিমটি ব্যবহারকারী রিড লুপের মাঝে অবস্থান করে। ডেটা ব্যবহারের আগে এটি ইচ্ছামতো একটি ট্রান্সফর্ম প্রয়োগ করতে পারে। এটিকে একটি অ্যাসেম্বলি লাইনের মতো ভাবুন: যখন একটি উইজেট লাইন ধরে এগিয়ে আসে, লাইনের প্রতিটি ধাপ উইজেটটিকে পরিবর্তন করে, যাতে এটি তার চূড়ান্ত গন্তব্যে পৌঁছানোর সময় একটি সম্পূর্ণ কার্যকরী উইজেটে পরিণত হয়।

একটি বিমান কারখানার ছবি
World War II Castle Bromwich Aeroplane Factory

উদাহরণস্বরূপ, এমন একটি ট্রান্সফর্ম স্ট্রিম ক্লাস তৈরি করার কথা ভাবুন যা একটি স্ট্রিম গ্রহণ করে এবং লাইন ব্রেকের উপর ভিত্তি করে সেটিকে খণ্ডে খণ্ডে ভাগ করে। স্ট্রিমটিতে যখনই নতুন ডেটা আসে, তখনই এর transform() মেথডটি কল করা হয়। এটি ডেটাটিকে কিউ-তে যুক্ত করতে পারে অথবা পরবর্তী ব্যবহারের জন্য সংরক্ষণ করতে পারে। স্ট্রিমটি বন্ধ করার সময় flush() মেথডটি কল করা হয় এবং এটি এখনও প্রক্রিয়া করা হয়নি এমন যেকোনো ডেটা পরিচালনা করে।

To use the transform stream class, you need to pipe an incoming stream through it. In the third code example under Read from a serial port , the original input stream was only piped through a TextDecoderStream , so we need to call pipeThrough() to pipe it through our new 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();

সিরিয়াল ডিভাইসের যোগাযোগ সংক্রান্ত সমস্যা ডিবাগ করার জন্য, সিরিয়াল ডিভাইসে আসা বা সেখান থেকে যাওয়া স্ট্রিমগুলোকে বিভক্ত করতে 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.

Revoke access to a serial port

ওয়েবসাইটটি SerialPort ইনস্ট্যান্সে forget() কল করার মাধ্যমে কোনো সিরিয়াল পোর্টের অ্যাক্সেস পারমিশন মুছে ফেলতে পারে, যদি সেই পোর্টটি আর ধরে রাখতে আগ্রহী না হয়। উদাহরণস্বরূপ, অনেকগুলো ডিভাইসসহ একটি শেয়ার করা কম্পিউটারে ব্যবহৃত কোনো শিক্ষামূলক ওয়েব অ্যাপ্লিকেশনের ক্ষেত্রে, ব্যবহারকারীর তৈরি করা বিপুল সংখ্যক জমা হওয়া পারমিশন একটি খারাপ ব্যবহারকারী অভিজ্ঞতা তৈরি করে।

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

যেহেতু forget() Chrome 103 বা তার পরবর্তী সংস্করণগুলোতে উপলব্ধ, তাই নিম্নলিখিত উপায়ে এই ফিচারটি সমর্থিত কিনা তা যাচাই করুন:

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

Dev Tips

ক্রোমে ওয়েব সিরিয়াল এপিআই ডিবাগ করা সহজ, এর অভ্যন্তরীণ পেজ about://device-log মাধ্যমে যেখানে আপনি সিরিয়াল ডিভাইস সম্পর্কিত সমস্ত ইভেন্ট এক জায়গায় দেখতে পারেন।

ওয়েব সিরিয়াল এপিআই ডিবাগ করার অভ্যন্তরীণ পৃষ্ঠার স্ক্রিনশট।
ওয়েব সিরিয়াল এপিআই ডিবাগ করার জন্য ক্রোমের অভ্যন্তরীণ পেজ।

কোডল্যাব

গুগল ডেভেলপার কোডল্যাবে , আপনি একটি বিবিসি মাইক্রো:বিট বোর্ডের ৫x৫ এলইডি ম্যাট্রিক্সে ছবি দেখানোর জন্য ওয়েব সিরিয়াল এপিআই ব্যবহার করে সেটির সাথে যোগাযোগ করবেন।

ব্রাউজার সমর্থন

ক্রোম ৮৯-এ ওয়েব সিরিয়াল এপিআই সকল ডেস্কটপ প্ল্যাটফর্মে (ক্রোমওএস, লিনাক্স, ম্যাকওএস এবং উইন্ডোজ) উপলব্ধ।

Polyfill

অ্যান্ড্রয়েডে, WebUSB API এবং Serial API পলিফিল ব্যবহার করে USB-ভিত্তিক সিরিয়াল পোর্টের জন্য সমর্থন যোগ করা সম্ভব। এই পলিফিলটি সেইসব হার্ডওয়্যার এবং প্ল্যাটফর্মের জন্য সীমাবদ্ধ যেখানে ডিভাইসটি WebUSB API-এর মাধ্যমে অ্যাক্সেসযোগ্য, কারণ এটি কোনো বিল্ট-ইন ডিভাইস ড্রাইভার দ্বারা দাবি করা হয়নি।

নিরাপত্তা এবং গোপনীয়তা

স্পেক লেখকরা "Controlling Access to Powerful Web Platform Features "-এ সংজ্ঞায়িত মূল নীতিগুলি, যেমন—ব্যবহারকারীর নিয়ন্ত্রণ, স্বচ্ছতা এবং কর্মদক্ষতা—ব্যবহার করে ওয়েব সিরিয়াল এপিআই ডিজাইন ও বাস্তবায়ন করেছেন। এই এপিআই ব্যবহারের ক্ষমতা মূলত একটি পারমিশন মডেল দ্বারা নিয়ন্ত্রিত, যা একবারে শুধুমাত্র একটি সিরিয়াল ডিভাইসে অ্যাক্সেস প্রদান করে। ব্যবহারকারীর অনুরোধে, তাকে একটি নির্দিষ্ট সিরিয়াল ডিভাইস নির্বাচন করার জন্য সক্রিয় পদক্ষেপ নিতে হয়।

নিরাপত্তাজনিত সুবিধা-অসুবিধাগুলো বুঝতে, ওয়েব সিরিয়াল এপিআই এক্সপ্লেনার-এর নিরাপত্তা এবং গোপনীয়তা বিভাগগুলো দেখুন।

প্রতিক্রিয়া

ওয়েব সিরিয়াল এপিআই নিয়ে আপনার মতামত ও অভিজ্ঞতা সম্পর্কে ক্রোম টিম জানতে আগ্রহী।

Tell us about the API design

এপিআই-টিতে কি এমন কিছু আছে যা প্রত্যাশা অনুযায়ী কাজ করছে না? অথবা আপনার ধারণাটি বাস্তবায়নের জন্য প্রয়োজনীয় কোনো মেথড বা প্রপার্টি কি অনুপস্থিত?

ওয়েব সিরিয়াল এপিআই গিটহাব রিপোতে একটি স্পেক ইস্যু ফাইল করুন অথবা বিদ্যমান কোনো ইস্যুতে আপনার মতামত যোগ করুন।

বাস্তবায়নে একটি সমস্যা রিপোর্ট করুন

আপনি কি ক্রোমের বাস্তবায়নে কোনো বাগ খুঁজে পেয়েছেন? নাকি এর বাস্তবায়ন স্পেসিফিকেশন থেকে ভিন্ন?

https://new.crbug.com -এ একটি বাগ রিপোর্ট করুন। যতটা সম্ভব বিস্তারিত তথ্য অন্তর্ভুক্ত করতে ভুলবেন না, বাগটি পুনরায় ঘটানোর জন্য সহজ নির্দেশাবলী প্রদান করুন এবং Components-কে Blink>Serial -এ সেট করুন।

Show support

আপনি কি ওয়েব সিরিয়াল এপিআই (Web Serial API) ব্যবহার করার পরিকল্পনা করছেন? আপনার প্রকাশ্য সমর্থন ক্রোম টিমকে ফিচারগুলোকে অগ্রাধিকার দিতে সাহায্য করে এবং অন্যান্য ব্রাউজার নির্মাতাদের দেখায় যে এগুলোর সমর্থন করা কতটা জরুরি।

#SerialAPI হ্যাশট্যাগটি ব্যবহার করে @ChromiumDev- কে একটি টুইট পাঠান এবং আমাদের জানান যে আপনি এটি কোথায় ও কীভাবে ব্যবহার করছেন।

সহায়ক লিঙ্ক

ডেমো

কৃতজ্ঞতা স্বীকার

এই নথিটি পর্যালোচনা করার জন্য রেইলি গ্রান্ট এবং জো মেডলিকে ধন্যবাদ।