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

ওয়েব সিরিয়াল API ওয়েবসাইটগুলিকে সিরিয়াল ডিভাইসগুলির সাথে যোগাযোগ করার অনুমতি দেয়৷

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

ওয়েব সিরিয়াল API কি?

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

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

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

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

প্রস্তাবিত ব্যবহারের ক্ষেত্রে

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

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

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

এখনকার অবস্থা

ধাপ স্ট্যাটাস
1. ব্যাখ্যাকারী তৈরি করুন সম্পূর্ণ
2. স্পেসিফিকেশনের প্রাথমিক খসড়া তৈরি করুন সম্পূর্ণ
3. প্রতিক্রিয়া সংগ্রহ করুন এবং ডিজাইনের উপর পুনরাবৃত্তি করুন সম্পূর্ণ
4. মূল বিচার সম্পূর্ণ
5. লঞ্চ করুন সম্পূর্ণ

ওয়েব সিরিয়াল API ব্যবহার করে

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

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

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

একটি সিরিয়াল পোর্ট খুলুন

ওয়েব সিরিয়াল 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() ফাংশন একটি ঐচ্ছিক বস্তু আক্ষরিক নেয় যা ফিল্টার সংজ্ঞায়িত করে। এগুলি একটি বাধ্যতামূলক USB বিক্রেতা ( usbVendorId ) এবং ঐচ্ছিক USB পণ্য শনাক্তকারী ( usbProductId ) এর সাথে USB-এর মাধ্যমে সংযুক্ত যেকোনো সিরিয়াল ডিভাইসের সাথে মেলানোর জন্য ব্যবহৃত হয়৷

// 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();
একটি ওয়েবসাইটে সিরিয়াল পোর্ট প্রম্পটের স্ক্রিনশট
একটি বিবিসি মাইক্রো:বিট নির্বাচন করার জন্য ব্যবহারকারীর প্রম্পট

requestPort() কল করা ব্যবহারকারীকে একটি ডিভাইস নির্বাচন করতে অনুরোধ করে এবং একটি SerialPort অবজেক্ট ফেরত দেয়। একবার আপনার কাছে একটি SerialPort অবজেক্ট থাকলে, port.open() কে কাঙ্খিত বড রেট সহ কল ​​করলে সিরিয়াল পোর্ট খুলবে। baudRate অভিধানের সদস্য একটি সিরিয়াল লাইনে কত দ্রুত ডেটা পাঠানো হয় তা নির্দিষ্ট করে। এটি বিট-প্রতি-সেকেন্ড (bps) এর এককে প্রকাশ করা হয়। সঠিক মানের জন্য আপনার ডিভাইসের ডকুমেন্টেশন পরীক্ষা করুন কারণ আপনার পাঠানো এবং গ্রহণ করা সমস্ত ডেটা যদি এটি ভুলভাবে উল্লেখ করা হয় তবে তা অপ্রীতিকর হবে৷ কিছু ইউএসবি এবং ব্লুটুথ ডিভাইসের জন্য যেগুলি একটি সিরিয়াল পোর্ট অনুকরণ করে এই মানটি নিরাপদে যেকোনো মানতে সেট করা হতে পারে কারণ এটি এমুলেশন দ্বারা উপেক্ষা করা হয়।

// 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 : রিড এবং রাইট বাফারের আকার যা তৈরি করা উচিত (16MB এর কম হতে হবে)।
  • flowControl : প্রবাহ নিয়ন্ত্রণ মোড (হয় "none" বা "hardware" )।

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

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

সিরিয়াল পোর্ট সংযোগ প্রতিষ্ঠিত হওয়ার পরে, SerialPort অবজেক্ট থেকে readable এবং writable বৈশিষ্ট্যগুলি একটি ReadableStream এবং একটি WritableStream প্রদান করে। সেগুলি সিরিয়াল ডিভাইস থেকে ডেটা গ্রহণ এবং ডেটা পাঠাতে ব্যবহৃত হবে। উভয়ই ডেটা স্থানান্তরের জন্য Uint8Array উদাহরণ ব্যবহার করে।

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

যদি সিরিয়াল ডিভাইসটি টেক্সট ফেরত পাঠায়, তাহলে আপনি নীচে দেখানো হিসাবে TextDecoderStream এর মাধ্যমে port.readable পাইপ করতে পারেন। একটি 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 প্রদান করুন। মনে রাখবেন যে ওয়েব সিরিয়াল 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() ডেটা পাঠান। 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");

একটি সিরিয়াল পোর্ট বন্ধ করুন

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

সংযোগ এবং সংযোগ বিচ্ছিন্ন শুনুন

যদি একটি সিরিয়াল পোর্ট একটি 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 একটি প্রোগ্রামিং মোডে প্রবেশ করবে যদি ডেটা টার্মিনাল রেডি (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}`);

রূপান্তর স্ট্রীম

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

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

একটি বিমান কারখানার ছবি
দ্বিতীয় বিশ্বযুদ্ধের ক্যাসেল ব্রমউইচ এয়ারপ্লেন ফ্যাক্টরি

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

ট্রান্সফর্ম স্ট্রিম ক্লাস ব্যবহার করতে, আপনাকে এটির মাধ্যমে একটি ইনকামিং স্ট্রিম পাইপ করতে হবে। একটি সিরিয়াল পোর্ট থেকে Read এর অধীনে তৃতীয় কোড উদাহরণে, মূল ইনপুট স্ট্রীমটি শুধুমাত্র একটি 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();

যেহেতু forget() Chrome 103 বা পরবর্তীতে উপলব্ধ, এই বৈশিষ্ট্যটি নিম্নলিখিতগুলির সাথে সমর্থিত কিনা তা পরীক্ষা করুন:

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

দেব টিপস

Chrome-এ ওয়েব সিরিয়াল API ডিবাগ করা অভ্যন্তরীণ পৃষ্ঠার সাথে সহজ, about://device-log যেখানে আপনি একক জায়গায় সমস্ত সিরিয়াল ডিভাইস সম্পর্কিত ইভেন্ট দেখতে পারেন৷

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

কোডল্যাব

Google ডেভেলপার কোডল্যাবে , আপনি একটি বিবিসি মাইক্রো:বিট বোর্ডের সাথে ইন্টারঅ্যাক্ট করতে ওয়েব সিরিয়াল API ব্যবহার করবেন এর 5x5 LED ম্যাট্রিক্সে ছবি দেখানোর জন্য।

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

ওয়েব সিরিয়াল API Chrome 89-এ সমস্ত ডেস্কটপ প্ল্যাটফর্মে (ChromeOS, Linux, macOS এবং Windows) উপলব্ধ।

পলিফিল

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

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

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

নিরাপত্তা ট্রেডঅফগুলি বোঝার জন্য, ওয়েব সিরিয়াল API ব্যাখ্যাকারীর সুরক্ষা এবং গোপনীয়তা বিভাগগুলি দেখুন৷

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

ক্রোম টিম ওয়েব সিরিয়াল API এর সাথে আপনার চিন্তাভাবনা এবং অভিজ্ঞতা সম্পর্কে শুনতে পছন্দ করবে৷

API ডিজাইন সম্পর্কে আমাদের বলুন

API সম্পর্কে এমন কিছু আছে যা প্রত্যাশিত হিসাবে কাজ করে না? অথবা আপনার ধারণা বাস্তবায়নের জন্য আপনার প্রয়োজনীয় পদ্ধতি বা বৈশিষ্ট্যগুলি অনুপস্থিত আছে?

ওয়েব সিরিয়াল API GitHub রেপোতে একটি নির্দিষ্ট সমস্যা ফাইল করুন বা বিদ্যমান সমস্যাটিতে আপনার চিন্তাভাবনা যোগ করুন।

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

আপনি কি Chrome এর বাস্তবায়নের সাথে একটি বাগ খুঁজে পেয়েছেন? অথবা বাস্তবায়ন বৈশিষ্ট থেকে ভিন্ন?

https://new.crbug.com এ একটি বাগ ফাইল করুন। আপনি যতটা পারেন বিশদ অন্তর্ভুক্ত করতে ভুলবেন না, বাগ পুনরুত্পাদনের জন্য সহজ নির্দেশাবলী প্রদান করুন, এবং উপাদানগুলি Blink>Serial এ সেট করুন। দ্রুত এবং সহজ রিপ্রো শেয়ার করার জন্য গ্লিচ দুর্দান্ত কাজ করে।

সমর্থন দেখান

আপনি ওয়েব সিরিয়াল API ব্যবহার করার পরিকল্পনা করছেন? আপনার সর্বজনীন সমর্থন Chrome টিমকে বৈশিষ্ট্যগুলিকে অগ্রাধিকার দিতে সাহায্য করে এবং অন্যান্য ব্রাউজার বিক্রেতাদের দেখায় যে তাদের সমর্থন করা কতটা গুরুত্বপূর্ণ৷

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

সাহা্য্যকারী লিংক

ডেমো

স্বীকৃতি

এই নিবন্ধটির পর্যালোচনার জন্য রিলি গ্রান্ট এবং জো মেডলিকে ধন্যবাদ। আনস্প্ল্যাশে বার্মিংহাম মিউজিয়াম ট্রাস্ট দ্বারা বিমান কারখানার ছবি।