ওয়েব সিরিয়াল API ওয়েবসাইটগুলিকে সিরিয়াল ডিভাইসগুলির সাথে যোগাযোগ করার অনুমতি দেয়৷
ওয়েব সিরিয়াল 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
যেখানে আপনি একক জায়গায় সমস্ত সিরিয়াল ডিভাইস সম্পর্কিত ইভেন্ট দেখতে পারেন৷
কোডল্যাব
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- এ একটি টুইট পাঠান এবং আপনি এটি কোথায় এবং কীভাবে ব্যবহার করছেন তা আমাদের জানান।
সহায়ক লিঙ্ক
- স্পেসিফিকেশন
- ট্র্যাকিং বাগ
- ChromeStatus.com এন্ট্রি
- ব্লিঙ্ক কম্পোনেন্ট:
Blink>Serial
ডেমো
স্বীকৃতি
এই নিবন্ধটির পর্যালোচনার জন্য রিলি গ্রান্ট এবং জো মেডলিকে ধন্যবাদ। আনস্প্ল্যাশে বার্মিংহাম মিউজিয়াম ট্রাস্ট দ্বারা বিমান কারখানার ছবি।
,ওয়েব সিরিয়াল API ওয়েবসাইটগুলিকে সিরিয়াল ডিভাইসগুলির সাথে যোগাযোগ করার অনুমতি দেয়৷
ওয়েব সিরিয়াল 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
যেখানে আপনি একক জায়গায় সমস্ত সিরিয়াল ডিভাইস সম্পর্কিত ইভেন্ট দেখতে পারেন৷
কোডল্যাব
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- এ একটি টুইট পাঠান এবং আপনি এটি কোথায় এবং কীভাবে ব্যবহার করছেন তা আমাদের জানান।
সহায়ক লিঙ্ক
- স্পেসিফিকেশন
- ট্র্যাকিং বাগ
- ChromeStatus.com এন্ট্রি
- ব্লিঙ্ক কম্পোনেন্ট:
Blink>Serial
ডেমো
স্বীকৃতি
এই নিবন্ধটির পর্যালোচনার জন্য রিলি গ্রান্ট এবং জো মেডলিকে ধন্যবাদ। আনস্প্ল্যাশে বার্মিংহাম মিউজিয়াম ট্রাস্ট দ্বারা বিমান কারখানার ছবি।
,ওয়েব সিরিয়াল API ওয়েবসাইটগুলিকে সিরিয়াল ডিভাইসগুলির সাথে যোগাযোগ করার অনুমতি দেয়৷
ওয়েব সিরিয়াল 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
থেকে বাফারটি পুনরায় ব্যবহার করা যায় তার একটি উদাহরণ এখানে রয়েছে uff
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.releaseLock()
ক্ষেত্রে, reader.cancel()
reader.read()
করা { value: undefined, done: true }
// 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.
});
হ্যান্ডেল সিগন্যাল
সিরিয়াল পোর্ট সংযোগ স্থাপনের পরে, আপনি ডিভাইস সনাক্তকরণ এবং প্রবাহ নিয়ন্ত্রণের জন্য সিরিয়াল পোর্ট দ্বারা প্রকাশিত সংকেতগুলি স্পষ্টভাবে অনুসন্ধান করতে এবং সেট করতে পারেন। এই সংকেতগুলি বুলিয়ান মান হিসাবে সংজ্ঞায়িত করা হয়। উদাহরণস্বরূপ, কিছু ডিভাইস যেমন আরডুইনো একটি প্রোগ্রামিং মোডে প্রবেশ করবে যদি ডেটা টার্মিনাল রেডি (ডিটিআর) সিগন্যাল টগল করা হয়।
আউটপুট সংকেত সেট করা এবং ইনপুট সংকেত পাওয়া যথাক্রমে 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}`);
রূপান্তরকারী স্ট্রিম
আপনি যখন সিরিয়াল ডিভাইস থেকে ডেটা পাবেন, আপনি অগত্যা একবারে সমস্ত ডেটা পাবেন না। এটি নির্বিচারে খাঁজকাটা হতে পারে। আরও তথ্যের জন্য, স্ট্রিমগুলি এপিআই ধারণাগুলি দেখুন।
এটি মোকাবেলা করার জন্য, আপনি কিছু অন্তর্নির্মিত ট্রান্সফর্ম স্ট্রিম যেমন TextDecoderStream
ব্যবহার করতে পারেন বা আপনার নিজস্ব ট্রান্সফর্ম স্ট্রিম তৈরি করতে পারেন যা আপনাকে আগত স্ট্রিমটি পার্স করতে এবং পার্সড ডেটা ফেরত দিতে দেয়। ট্রান্সফর্ম স্ট্রিমটি সিরিয়াল ডিভাইস এবং স্ট্রিমটি গ্রাস করে এমন পড়ার লুপের মধ্যে বসে। এটি ডেটা খাওয়ার আগে একটি স্বেচ্ছাসেবী রূপান্তর প্রয়োগ করতে পারে। এটিকে একটি অ্যাসেম্বলি লাইনের মতো ভাবুন: একটি উইজেট লাইন থেকে নেমে আসার সাথে সাথে লাইনের প্রতিটি পদক্ষেপ উইজেটকে সংশোধন করে, যাতে এটি চূড়ান্ত গন্তব্যে পৌঁছে যাওয়ার সময় এটি সম্পূর্ণ কার্যকরী উইজেট।
উদাহরণস্বরূপ, কীভাবে একটি ট্রান্সফর্ম স্ট্রিম ক্লাস তৈরি করবেন তা বিবেচনা করুন যা একটি স্ট্রিম গ্রাস করে এবং লাইন বিরতির উপর ভিত্তি করে এটি খণ্ডন করে। এর 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();
যেমন forget()
ক্রোম 103 বা তার পরে উপলব্ধ, এই বৈশিষ্ট্যটি নিম্নলিখিতগুলির সাথে সমর্থিত কিনা তা পরীক্ষা করুন:
if ("serial" in navigator && "forget" in SerialPort.prototype) {
// forget() is supported.
}
দেব টিপস
ক্রোমে ওয়েব সিরিয়াল এপিআই ডিবাগ করা অভ্যন্তরীণ পৃষ্ঠার সাথে সহজ, about://device-log
যেখানে আপনি একক স্থানে সিরিয়াল ডিভাইস সম্পর্কিত সমস্ত ইভেন্ট দেখতে পারেন।
কোডল্যাব
গুগল ডেভেলপার কোডল্যাব -এ, আপনি বিবিসি মাইক্রো: বিট বোর্ডের 5x5 এলইডি ম্যাট্রিক্সে চিত্রগুলি দেখানোর জন্য ইন্টারঅ্যাক্ট করতে ওয়েব সিরিয়াল এপিআই ব্যবহার করবেন।
ব্রাউজার সমর্থন
ওয়েব সিরিয়াল এপিআই ক্রোম 89 -এ সমস্ত ডেস্কটপ প্ল্যাটফর্ম (ক্রোমোস, লিনাক্স, ম্যাকোস এবং উইন্ডোজ) এ উপলব্ধ।
পলিফিল
অ্যান্ড্রয়েডে, ইউএসবি-ভিত্তিক সিরিয়াল পোর্টগুলির জন্য সমর্থন ওয়েবাসবি এপিআই এবং সিরিয়াল এপিআই পলিফিল ব্যবহার করে সম্ভব। এই পলিফিলটি হার্ডওয়্যার এবং প্ল্যাটফর্মগুলির মধ্যে সীমাবদ্ধ যেখানে ডিভাইসটি ওয়েবএসবি এপিআইয়ের মাধ্যমে অ্যাক্সেসযোগ্য কারণ এটি কোনও অন্তর্নির্মিত ডিভাইস ড্রাইভার দ্বারা দাবি করা হয়নি।
নিরাপত্তা এবং গোপনীয়তা
স্পেক লেখকরা ব্যবহারকারী নিয়ন্ত্রণ, স্বচ্ছতা এবং এরগনোমিক্স সহ শক্তিশালী ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্যগুলিতে অ্যাক্সেস নিয়ন্ত্রণে সংজ্ঞায়িত মূল নীতিগুলি ব্যবহার করে ওয়েব সিরিয়াল এপিআই ডিজাইন ও প্রয়োগ করেছেন। এই এপিআই ব্যবহারের ক্ষমতাটি প্রাথমিকভাবে একটি অনুমতি মডেল দ্বারা গেটেড যা একবারে কেবল একটি একক সিরিয়াল ডিভাইসে অ্যাক্সেস দেয়। কোনও ব্যবহারকারীর প্রম্পটের প্রতিক্রিয়া হিসাবে, ব্যবহারকারীকে অবশ্যই একটি নির্দিষ্ট সিরিয়াল ডিভাইস নির্বাচন করতে সক্রিয় পদক্ষেপ নিতে হবে।
সুরক্ষা ট্রেড অফগুলি বুঝতে, ওয়েব সিরিয়াল এপিআই ব্যাখ্যার সুরক্ষা এবং গোপনীয়তা বিভাগগুলি দেখুন।
প্রতিক্রিয়া
ক্রোম টিম ওয়েব সিরিয়াল এপিআইয়ের সাথে আপনার চিন্তাভাবনা এবং অভিজ্ঞতা সম্পর্কে শুনতে পছন্দ করবে।
API ডিজাইন সম্পর্কে আমাদের বলুন
API সম্পর্কে এমন কিছু আছে যা প্রত্যাশিত হিসাবে কাজ করে না? অথবা আপনার ধারণা বাস্তবায়নের জন্য আপনার প্রয়োজনীয় পদ্ধতি বা বৈশিষ্ট্যগুলি অনুপস্থিত আছে?
ওয়েব সিরিয়াল এপিআই গিটহাব রেপোতে একটি নির্দিষ্ট সমস্যা ফাইল করুন বা একটি বিদ্যমান ইস্যুতে আপনার চিন্তাভাবনা যুক্ত করুন।
বাস্তবায়নের সাথে একটি সমস্যা রিপোর্ট করুন
আপনি কি Chrome এর বাস্তবায়নের সাথে একটি বাগ খুঁজে পেয়েছেন? অথবা বাস্তবায়ন বৈশিষ্ট থেকে ভিন্ন?
https://new.crbug.com এ একটি বাগ ফাইল করুন। আপনি যতটা বিস্তারিত অন্তর্ভুক্ত করতে পারেন তা নিশ্চিত করুন, বাগটি পুনরুত্পাদন করার জন্য সহজ নির্দেশাবলী সরবরাহ করুন এবং উপাদানগুলি Blink>Serial
সেট করা আছে। দ্রুত এবং সহজ রিপ্রো শেয়ার করার জন্য গ্লিচ দুর্দান্ত কাজ করে।
সমর্থন দেখান
আপনি কি ওয়েব সিরিয়াল এপিআই ব্যবহার করার পরিকল্পনা করছেন? আপনার সর্বজনীন সমর্থন Chrome টিমকে বৈশিষ্ট্যগুলিকে অগ্রাধিকার দিতে সাহায্য করে এবং অন্যান্য ব্রাউজার বিক্রেতাদের দেখায় যে তাদের সমর্থন করা কতটা গুরুত্বপূর্ণ৷
#SerialAPI
হ্যাশট্যাগ ব্যবহার করে @ ক্রোমিয়ামদেবকে একটি টুইট প্রেরণ করুন এবং আপনি কোথায় এবং কীভাবে এটি ব্যবহার করছেন তা আমাদের জানান।
সহায়ক লিঙ্ক
- স্পেসিফিকেশন
- ট্র্যাকিং বাগ
- ChromeStatus.com এন্ট্রি
- ব্লিঙ্ক উপাদান:
Blink>Serial
ডেমো
স্বীকৃতি
এই নিবন্ধটির তাদের পর্যালোচনার জন্য রিলি গ্রান্ট এবং জো মেডলিকে ধন্যবাদ। বার্মিংহাম মিউজিয়ামস ট্রাস্টের উপর আনস্প্ল্যাশের এয়ারপ্লেন কারখানার ছবি।