ওয়েব সিরিয়াল API দিয়ে শুরু করা

১. ভূমিকা

সর্বশেষ হালনাগাদ: ২১-০৭-২০২০

আপনি যা তৈরি করবেন

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

81167ab7c01d353d.png

আপনি যা শিখবেন

  • ওয়েব সিরিয়াল পোর্ট কীভাবে খুলবেন এবং বন্ধ করবেন
  • ইনপুট স্ট্রিম থেকে ডেটা পরিচালনা করতে কীভাবে একটি রিড লুপ ব্যবহার করবেন
  • রাইট স্ট্রিমের মাধ্যমে কীভাবে ডেটা পাঠাতে হয়

আপনার যা যা লাগবে

এই কোডল্যাবের জন্য আমরা মাইক্রো:বিট ব্যবহার করার সিদ্ধান্ত নিয়েছি, কারণ এটি সাশ্রয়ী, এতে কয়েকটি ইনপুট (বাটন) ও আউটপুট (৫x৫ এলইডি ডিসপ্লে) রয়েছে এবং এটি অতিরিক্ত ইনপুট ও আউটপুটও সরবরাহ করতে পারে। মাইক্রো:বিট কী কী করতে সক্ষম, সে সম্পর্কে বিস্তারিত জানতে এস্প্রুইনো সাইটে বিবিসি মাইক্রো:বিট পেজটি দেখুন।

২. ওয়েব সিরিয়াল এপিআই সম্পর্কে

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

ওয়েব প্রযুক্তি ব্যবহার করে কন্ট্রোল সফটওয়্যার তৈরির অনেক উদাহরণ রয়েছে। যেমন:

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

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

৩. প্রস্তুতি গ্রহণ

কোডটি নিন

এই কোডল্যাবের জন্য আপনার প্রয়োজনীয় সবকিছু আমরা একটি গ্লিচ প্রোজেক্টে রেখেছি।

  1. একটি নতুন ব্রাউজার ট্যাব খুলুন এবং https://web-serial-codelab-start.glitch.me/ -এ যান।
  2. স্টার্টার প্রজেক্টটির আপনার নিজস্ব সংস্করণ তৈরি করতে রিমিক্স গ্লিচ লিঙ্কে ক্লিক করুন।
  3. আপনার কোডটি কার্যকরভাবে দেখতে, 'Show' বোতামে ক্লিক করুন এবং তারপরে 'In a New Window' নির্বাচন করুন।

৪. একটি সিরিয়াল সংযোগ খুলুন

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

প্রথমেই দেখতে হবে বর্তমান ব্রাউজারে ওয়েব সিরিয়াল এপিআই (Web Serial API) সমর্থিত কিনা। তা করার জন্য, navigator serial আছে কিনা তা যাচাই করুন।

আপনার প্রজেক্টে DOMContentLoaded ইভেন্টে নিম্নলিখিত কোডটি যোগ করুন:

script.js - DOMContentLoaded

// CODELAB: Add feature detection here.
const notSupported = document.getElementById('notSupported');
notSupported.classList.toggle('hidden', 'serial' in navigator);

এটি ওয়েব সিরিয়াল সমর্থিত কিনা তা যাচাই করে। যদি সমর্থিত হয়, তবে এই কোডটি ‘ওয়েব সিরিয়াল সমর্থিত নয়’ লেখা ব্যানারটি লুকিয়ে ফেলে।

চেষ্টা করে দেখুন

  1. পৃষ্ঠাটি লোড করুন।
  2. যাচাই করুন যে পৃষ্ঠাটিতে 'ওয়েব সিরিয়াল সমর্থিত নয়' লেখা কোনো লাল ব্যানার প্রদর্শিত হচ্ছে না।

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

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

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

আপনার প্রজেক্টে নিম্নলিখিত কোডটি যোগ করুন:

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

requestPort কলটি ব্যবহারকারীর কাছে জানতে চায় যে তিনি কোন ডিভাইসের সাথে সংযোগ করতে চান। port.open কল করলে পোর্টটি খুলে যায়। সিরিয়াল ডিভাইসের সাথে আমরা যে গতিতে যোগাযোগ করতে চাই, সেই গতিও আমাদের জানাতে হবে। বিবিসি মাইক্রো:বিট ইউএসবি-টু-সিরিয়াল চিপ এবং মূল প্রসেসরের মধ্যে ৯৬০০ বড সংযোগ ব্যবহার করে।

চলুন কানেক্ট বাটনটিকেও সংযুক্ত করি এবং ব্যবহারকারী এটিতে ক্লিক করলে যেন connect() ফাংশনটি কল হয়।

আপনার প্রজেক্টে নিম্নলিখিত কোডটি যোগ করুন:

script.js - clickConnect()

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

চেষ্টা করে দেখুন

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

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. ট্যাবটিতে আপনি একটি আইকন দেখতে পাবেন, যা নির্দেশ করে যে আপনি একটি সিরিয়াল ডিভাইসের সাথে সংযুক্ত হয়েছেন:

d9d0d3966960aeab.png

সিরিয়াল পোর্ট থেকে ডেটা শোনার জন্য একটি ইনপুট স্ট্রিম সেট আপ করুন।

সংযোগ স্থাপন হয়ে গেলে, ডিভাইস থেকে ডেটা পড়ার জন্য আমাদের একটি ইনপুট স্ট্রিম এবং একটি রিডার সেট আপ করতে হবে। প্রথমে, আমরা port.readable কল করে পোর্ট থেকে পাঠযোগ্য স্ট্রিমটি নেব। যেহেতু আমরা জানি যে ডিভাইস থেকে টেক্সট ফেরত আসবে, তাই আমরা এটিকে একটি টেক্সট ডিকোডারের মাধ্যমে পাঠাব। এরপর, আমরা একটি রিডার নেব এবং রিড লুপটি শুরু করব।

আপনার প্রজেক্টে নিম্নলিখিত কোডটি যোগ করুন:

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

রিড লুপ হলো একটি অ্যাসিঙ্ক্রোনাস ফাংশন যা মূল থ্রেডকে ব্লক না করেই একটি লুপের মধ্যে চলে এবং কন্টেন্টের জন্য অপেক্ষা করে। যখন নতুন ডেটা আসে, রিডার দুটি প্রপার্টি রিটার্ন করে: value এবং একটি done বুলিয়ান। যদি done মান ট্রু হয়, তার মানে পোর্টটি বন্ধ হয়ে গেছে অথবা আর কোনো ডেটা আসছে না।

আপনার প্রজেক্টে নিম্নলিখিত কোডটি যোগ করুন:

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

চেষ্টা করে দেখুন

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

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. আপনার এসপ্রুইনো লোগোটি দেখা উচিত:

93494fd58ea835eb.png

সিরিয়াল পোর্টে ডেটা পাঠানোর জন্য একটি আউটপুট স্ট্রিম সেট আপ করুন।

সিরিয়াল কমিউনিকেশন সাধারণত দ্বিমুখী হয়। সিরিয়াল পোর্ট থেকে ডেটা গ্রহণ করার পাশাপাশি, আমরা পোর্টে ডেটা পাঠাতেও চাই। ইনপুট স্ট্রিমের মতোই, আমরা আউটপুট স্ট্রিমের মাধ্যমে মাইক্রো:বিটে শুধুমাত্র টেক্সট পাঠাব।

প্রথমে, একটি টেক্সট এনকোডার স্ট্রিম তৈরি করুন এবং স্ট্রিমটিকে 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;

Espruino ফার্মওয়্যারের সাথে সিরিয়াল সংযোগের মাধ্যমে যুক্ত হলে, BBC micro:bit বোর্ডটি একটি জাভাস্ক্রিপ্ট রিড-ইভ্যাল-প্রিন্ট লুপ (REPL) হিসেবে কাজ করে, যা Node.js শেলে পাওয়া যায়। এরপর, স্ট্রিমে ডেটা পাঠানোর জন্য আমাদের একটি মেথড প্রদান করতে হবে। নিচের কোডটি আউটপুট স্ট্রিম থেকে একটি রাইটার নেয় এবং তারপর প্রতিটি লাইন পাঠানোর জন্য write ব্যবহার করে। পাঠানো প্রতিটি লাইনে একটি নিউ-লাইন ক্যারেক্টার ( \n ) থাকে, যা micro:bit-কে পাঠানো কমান্ডটি মূল্যায়ন করতে নির্দেশ দেয়।

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

সিস্টেমটিকে একটি পরিচিত অবস্থায় আনতে এবং আমাদের পাঠানো অক্ষরগুলোর প্রতিধ্বনি বন্ধ করতে, আমাদের CTRL-C চেপে ইকো বন্ধ করতে হবে।

script.js - connect()

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

চেষ্টা করে দেখুন

আমাদের প্রজেক্টটি এখন মাইক্রো:বিট থেকে ডেটা পাঠাতে ও গ্রহণ করতে পারে। চলুন যাচাই করে দেখি যে আমরা সঠিকভাবে একটি কমান্ড পাঠাতে পারি কি না:

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. Chrome DevTools-এর Console ট্যাবটি খুলুন এবং writeToStream('console.log("yes")');

পৃষ্ঠাটিতে এইরকম কিছু ছাপা দেখতে পাবেন:

a13187e7e6260f7f.png

৫. এলইডি ম্যাট্রিক্স নিয়ন্ত্রণ করুন

ম্যাট্রিক্স গ্রিড স্ট্রিং তৈরি করুন

মাইক্রো:বিটের এলইডি ম্যাট্রিক্স নিয়ন্ত্রণ করতে, আমাদের show() কল করতে হবে। এই মেথডটি বিল্ট-ইন 5x5 এলইডি স্ক্রিনে গ্রাফিক্স প্রদর্শন করে। এটি একটি বাইনারি সংখ্যা বা একটি স্ট্রিং গ্রহণ করে।

আমরা চেকবক্সগুলোর উপর পুনরাবৃত্তি করব এবং কোনটি চেক করা হয়েছে আর কোনটি হয়নি তা নির্দেশ করার জন্য ১ এবং ০-এর একটি অ্যারে তৈরি করব। এরপর আমাদের অ্যারেটিকে উল্টে দিতে হবে, কারণ আমাদের চেকবক্সগুলোর ক্রম ম্যাট্রিক্সের এলইডিগুলোর ক্রমের বিপরীত। এরপর, আমরা অ্যারেটিকে একটি স্ট্রিং-এ রূপান্তর করব এবং মাইক্রো:বিটে পাঠানোর জন্য কমান্ডটি তৈরি করব।

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

ম্যাট্রিক্স আপডেট করার জন্য চেকবক্সগুলো সংযুক্ত করুন।

এরপরে, আমাদের চেকবক্সগুলিতে হওয়া পরিবর্তনগুলি লক্ষ্য করতে হবে এবং সেগুলি পরিবর্তিত হলে সেই তথ্য মাইক্রো:বিট-এ পাঠাতে হবে। ফিচার ডিটেকশন কোডে ( // CODELAB: Add feature detection here. ), নিম্নলিখিত লাইনটি যোগ করুন:

script.js - DOMContentLoaded

initCheckboxes();

মাইক্রো:বিট প্রথমবার সংযোগ করার সময় গ্রিডটিও রিসেট করা যাক, যাতে এটি একটি হাসিমুখ দেখায়। ` drawGrid() ফাংশনটি ইতিমধ্যেই দেওয়া আছে। এই ফাংশনটি sendGrid() এর মতোই কাজ করে; এটি ১ এবং ০-এর একটি অ্যারে নেয় এবং প্রয়োজন অনুযায়ী চেকবক্সগুলোতে টিক চিহ্ন দেয়।

script.js - clickConnect()

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

চেষ্টা করে দেখুন

এখন, যখন পৃষ্ঠাটি মাইক্রো:বিটের সাথে একটি সংযোগ স্থাপন করবে, তখন এটি একটি হাসিমুখ পাঠাবে। চেকবক্সগুলিতে ক্লিক করলে এলইডি ম্যাট্রিক্সের ডিসপ্লে আপডেট হবে।

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. আপনি মাইক্রো:বিট এলইডি ম্যাট্রিক্সে একটি হাসি দেখতে পাবেন।
  5. চেকবক্সগুলো পরিবর্তন করে এলইডি ম্যাট্রিক্সে একটি ভিন্ন নকশা আঁকুন।

৬. মাইক্রো:বিট বাটনগুলো সংযুক্ত করুন।

micro:bit বাটনগুলিতে একটি ওয়াচ ইভেন্ট যোগ করুন

মাইক্রো:বিটে দুটি বাটন আছে, এলইডি ম্যাট্রিক্সের দুই পাশে একটি করে। Espruino একটি setWatch ফাংশন প্রদান করে যা বাটন চাপলে একটি ইভেন্ট/কলব্যাক পাঠায়। যেহেতু আমরা দুটি বাটনেরই সংকেত শুনতে চাই, তাই আমরা আমাদের ফাংশনটিকে জেনেরিক বানাবো এবং ইভেন্টের বিস্তারিত তথ্য প্রিন্ট করার ব্যবস্থা করবো।

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

এরপরে, প্রতিবার সিরিয়াল পোর্টটি ডিভাইসের সাথে সংযুক্ত করার সময় আমাদের উভয় বাটনই (মাইক্রো:বিট বোর্ডে যেগুলোর নাম BTN1 এবং BTN2) সংযুক্ত করতে হবে।

script.js - clickConnect()

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

চেষ্টা করে দেখুন

সংযুক্ত থাকা অবস্থায় একটি হাসিমুখ দেখানোর পাশাপাশি, মাইক্রো:বিটের যেকোনো একটি বোতাম চাপলে পৃষ্ঠায় লেখা যুক্ত হবে, যা থেকে বোঝা যাবে কোন বোতামটি চাপা হয়েছে। সম্ভবত, প্রতিটি অক্ষর আলাদা লাইনে থাকবে।

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. আপনি মাইক্রো:বিটস এলইডি ম্যাট্রিক্সে একটি হাসি দেখতে পাবেন।
  5. micro:bit-এর বাটনগুলো চাপুন এবং যাচাই করুন যে এটি চাপা বাটনটির বিবরণসহ পৃষ্ঠায় নতুন লেখা যোগ করছে।

৭. আগত ডেটা পার্স করতে একটি ট্রান্সফর্ম স্ট্রিম ব্যবহার করুন।

মৌলিক প্রবাহ পরিচালনা

যখন মাইক্রো:বিটের কোনো একটি বাটন চাপা হয়, তখন মাইক্রো:বিট একটি স্ট্রিমের মাধ্যমে সিরিয়াল পোর্টে ডেটা পাঠায়। স্ট্রিমগুলো খুবই দরকারি, কিন্তু এগুলো একটি চ্যালেঞ্জও হতে পারে, কারণ আপনি সবসময় সমস্ত ডেটা একসাথে পাবেন না এবং এটি যথেচ্ছভাবে খণ্ডে খণ্ডে বিভক্ত থাকতে পারে।

অ্যাপটি বর্তমানে ইনকামিং স্ট্রিমটি আসার সাথে সাথেই ( readLoop এর মধ্যে) প্রিন্ট করে। বেশিরভাগ ক্ষেত্রে, প্রতিটি ক্যারেক্টার আলাদা লাইনে থাকে, কিন্তু এটি খুব একটা সহায়ক নয়। আদর্শগতভাবে, স্ট্রিমটিকে আলাদা আলাদা লাইনে পার্স করা উচিত এবং প্রতিটি মেসেজকে তার নিজস্ব লাইনে দেখানো উচিত।

TransformStream ব্যবহার করে স্ট্রিম রূপান্তর করা

এটি করার জন্য, আমরা একটি ট্রান্সফর্ম স্ট্রিম ( TransformStream ) ব্যবহার করতে পারি, যা আগত স্ট্রিমকে পার্স করা এবং পার্স করা ডেটা ফেরত দেওয়া সম্ভব করে তোলে। একটি ট্রান্সফর্ম স্ট্রিম, স্ট্রিমের উৎস (এই ক্ষেত্রে, মাইক্রো:বিট) এবং যা কিছু স্ট্রিমটি ব্যবহার করছে (এই ক্ষেত্রে readLoop ) তার মধ্যে থাকতে পারে এবং চূড়ান্তভাবে ব্যবহৃত হওয়ার আগে যেকোনো ধরনের ট্রান্সফর্ম প্রয়োগ করতে পারে। এটিকে একটি অ্যাসেম্বলি লাইনের মতো ভাবুন: যখন একটি উইজেট লাইন ধরে এগিয়ে আসে, লাইনের প্রতিটি ধাপ উইজেটটিকে পরিবর্তন করে, যাতে এটি তার চূড়ান্ত গন্তব্যে পৌঁছানোর সময় একটি সম্পূর্ণ কার্যকরী উইজেটে পরিণত হয়।

আরও তথ্যের জন্য, MDN-এর Streams API concepts দেখুন।

LineBreakTransformer দিয়ে স্ট্রিমটি রূপান্তর করুন

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

আমাদের transform মেথডে, আমরা container এ নতুন ডেটা যোগ করব এবং তারপর দেখব container মধ্যে কোনো লাইন ব্রেক আছে কিনা। যদি থাকে, তবে সেটিকে একটি অ্যারেতে ভাগ করে নেব এবং তারপর লাইনগুলোর মধ্যে দিয়ে পুনরাবৃত্তি করে controller.enqueue() কল করে পার্স করা লাইনগুলো পাঠিয়ে দেব।

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

যখন স্ট্রিমটি বন্ধ করা হবে, আমরা enqueue ব্যবহার করে কন্টেইনারে থাকা অবশিষ্ট ডেটা বের করে দেব।

script.js - LineBreakTransformer.flush()

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

অবশেষে, আমাদের ইনকামিং স্ট্রিমটিকে নতুন LineBreakTransformer মধ্য দিয়ে পাইপ করতে হবে। আমাদের আসল ইনপুট স্ট্রিমটি শুধুমাত্র একটি TextDecoderStream মধ্য দিয়ে পাইপ করা হয়েছিল, তাই এটিকে আমাদের নতুন LineBreakTransformer মধ্য দিয়ে পাইপ করার জন্য একটি অতিরিক্ত pipeThrough যোগ করতে হবে।

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

চেষ্টা করে দেখুন

এখন, আপনি যখন মাইক্রো:বিট বাটনগুলোর মধ্যে একটি চাপবেন, তখন প্রিন্ট হওয়া ডেটা একটি লাইনে ফেরত আসবে।

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. আপনি মাইক্রো:বিট এলইডি ম্যাট্রিক্সে একটি হাসি দেখতে পাবেন।
  5. micro:bit-এর বাটনগুলো টিপুন এবং যাচাই করুন যে আপনি নিচের মতো কিছু দেখতে পাচ্ছেন কিনা:

6c2193880c748412.png

JSONTransformer দিয়ে স্ট্রিমটি রূপান্তর করুন

আমরা readLoop এর মধ্যে স্ট্রিংটিকে JSON-এ পার্স করার চেষ্টা করতে পারতাম, কিন্তু তার পরিবর্তে, চলুন একটি খুব সাধারণ JSON ট্রান্সফরমার তৈরি করি যা ডেটাটিকে একটি JSON অবজেক্টে রূপান্তর করবে। যদি ডেটাটি বৈধ JSON না হয়, তবে যা এসেছে তাই ফেরত দিন।

script.js - JSONTransformer.transform

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

এরপরে, স্ট্রিমটিকে LineBreakTransformer মধ্যে দিয়ে পাঠানোর পর JSONTransformer এর মধ্যে দিয়ে পাইপ করুন। এর ফলে আমরা আমাদের JSONTransformer সরল রাখতে পারি, কারণ আমরা জানি যে JSON ডেটা সবসময় শুধুমাত্র একটি লাইনেই পাঠানো হবে।

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

চেষ্টা করে দেখুন

এখন, আপনি যখন মাইক্রো:বিট বাটনগুলোর মধ্যে একটি চাপবেন, তখন পৃষ্ঠায় [object Object] লেখাটি প্রিন্ট হতে দেখবেন।

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. আপনি মাইক্রো:বিট এলইডি ম্যাট্রিক্সে একটি হাসি দেখতে পাবেন।
  5. micro:bit-এর বাটনগুলো টিপুন এবং যাচাই করুন যে আপনি নিচের মতো কিছু দেখতে পাচ্ছেন কিনা:

বোতাম চাপার প্রতিক্রিয়া

micro:bit বাটন প্রেসের প্রতিক্রিয়া জানাতে, readLoop আপডেট করে পরীক্ষা করুন যে এটি যে ডেটা পেয়েছে তা button প্রপার্টিসহ একটি object কিনা। তারপর, বাটন প্রেসটি হ্যান্ডেল করার জন্য buttonPushed কল করুন।

script.js - readLoop()

const { value, done } = await reader.read();
if (value && value.button) {
  buttonPushed(value);
} else {
  log.textContent += value + '\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();
  }
}

চেষ্টা করে দেখুন

এখন, যখন আপনি মাইক্রো:বিট বাটনগুলোর মধ্যে একটি চাপবেন, তখন এলইডি ম্যাট্রিক্সটি হয় একটি হাসিমুখ অথবা একটি বিষণ্ণমুখে পরিবর্তিত হবে।

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. আপনি মাইক্রো:বিটস এলইডি ম্যাট্রিক্সে একটি হাসি দেখতে পাবেন।
  5. মাইক্রো:বিটের বাটনগুলো টিপুন এবং যাচাই করুন যে এলইডি ম্যাট্রিক্সটি পরিবর্তিত হচ্ছে।

৮. সিরিয়াল পোর্ট বন্ধ করা

চূড়ান্ত ধাপটি হলো ব্যবহারকারীর কাজ শেষ হলে পোর্টটি বন্ধ করার জন্য ডিসকানেক্ট কার্যকারিতাটি সংযুক্ত করা।

ব্যবহারকারী কানেক্ট/ডিসকানেক্ট বোতামে ক্লিক করলে পোর্টটি বন্ধ হয়ে যাবে।

যখন ব্যবহারকারী কানেক্ট / ডিসকানেক্ট বোতামে ক্লিক করেন, তখন আমাদের সংযোগটি বন্ধ করতে হবে। যদি পোর্টটি আগে থেকেই খোলা থাকে, তাহলে disconnect() কল করুন এবং UI আপডেট করে জানান যে পেজটি আর সিরিয়াল ডিভাইসের সাথে সংযুক্ত নেই।

script.js - clickConnect()

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

স্রোত এবং বন্দর বন্ধ করুন

disconnect ফাংশনে, আমাদের ইনপুট স্ট্রিম, আউটপুট স্ট্রিম এবং পোর্ট বন্ধ করতে হবে। ইনপুট স্ট্রিম বন্ধ করতে, reader.cancel() কল করুন। cancel এর কলটি অ্যাসিঙ্ক্রোনাস, তাই এটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে আমাদের await ব্যবহার করতে হবে।

script.js - disconnect()

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

আউটপুট স্ট্রিম বন্ধ করতে, একটি writer নিন, close() কল করুন, এবং outputDone অবজেক্টটি বন্ধ হওয়া পর্যন্ত অপেক্ষা করুন:

script.js - disconnect()

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

অবশেষে, সিরিয়াল পোর্টটি বন্ধ করুন এবং এটি বন্ধ হওয়া পর্যন্ত অপেক্ষা করুন:

script.js - disconnect()

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

চেষ্টা করে দেখুন

এখন আপনি ইচ্ছামতো সিরিয়াল পোর্ট খুলতে ও বন্ধ করতে পারবেন।

  1. পৃষ্ঠাটি পুনরায় লোড করুন।
  2. কানেক্ট বাটনটিতে ক্লিক করুন।
  3. সিরিয়াল পোর্ট চুজার ডায়ালগে, BBC micro:bit ডিভাইসটি নির্বাচন করুন এবং কানেক্ট-এ ক্লিক করুন।
  4. আপনি মাইক্রো:বিট এলইডি ম্যাট্রিক্সে একটি হাসি দেখতে পাবেন।
  5. ডিসকানেক্ট বাটনটি চাপুন এবং যাচাই করুন যে এলইডি ম্যাট্রিক্সটি বন্ধ হয়ে গেছে এবং কনসোলে কোনো ত্রুটি নেই।

৯. অভিনন্দন

অভিনন্দন! আপনি ওয়েব সিরিয়াল এপিআই ব্যবহার করে আপনার প্রথম ওয়েব অ্যাপটি সফলভাবে তৈরি করেছেন।

ওয়েব সিরিয়াল এপিআই এবং ক্রোম টিমের তৈরি করা অন্যান্য সব আকর্ষণীয় নতুন ওয়েব ফিচারের সর্বশেষ তথ্যের জন্য https://goo.gle/fugu-api-tracker- এ নজর রাখুন।