WebUSB API, USB को वेब पर उपलब्ध कराकर, इसे इस्तेमाल करने के तरीके को सुरक्षित और आसान बनाता है.
अगर मैंने साफ़ तौर पर और आसानी से "यूएसबी" कहा, तो हो सकता है कि आपके मन में तुरंत कीबोर्ड, माउस, ऑडियो, वीडियो, और स्टोरेज डिवाइसों की इमेज बन जाए. आपका जवाब सही है, लेकिन यहां आपको अन्य तरह के यूनिवर्सल सीरियल बस (यूएसबी) डिवाइस मिलेंगे.
इन नॉन-स्टैंडर्ड यूएसबी डिवाइसों के लिए, हार्डवेयर वेंडर को अलग से प्लैटफ़ॉर्म के हिसाब से ड्राइवर और SDK टूल लिखने होते हैं, ताकि आप (डेवलपर) उनका फ़ायदा ले सकें. माफ़ करें, प्लैटफ़ॉर्म के हिसाब से दिए गए इस कोड की वजह से, इन डिवाइसों पर वेब का इस्तेमाल नहीं किया जा सकता. WebUSB API के बनाए जाने की एक वजह यह है: यूएसबी डिवाइस सेवाओं को वेब पर सार्वजनिक करने का तरीका उपलब्ध कराना. इस एपीआई की मदद से, हार्डवेयर मैन्युफ़ैक्चरर अपने डिवाइसों के लिए, क्रॉस-प्लैटफ़ॉर्म JavaScript SDK टूल बना पाएंगे.
सबसे अहम बात यह है कि इससे यूएसबी को वेब पर उपलब्ध कराने के बाद, इसे इस्तेमाल करना ज़्यादा सुरक्षित और आसान हो जाएगा.
आइए, देखें कि WebUSB API के साथ आपको कैसा व्यवहार मिल सकता है:
- कोई यूएसबी डिवाइस खरीदें.
- इसे अपने कंप्यूटर में प्लग करें. इसके बाद, आपको तुरंत एक सूचना दिखेगी. इसमें, इस डिवाइस के लिए सही वेबसाइट का लिंक होगा.
- सूचना पर क्लिक करें. वेबसाइट बनकर तैयार है और इसका इस्तेमाल किया जा सकता है!
- कनेक्ट करने के लिए क्लिक करें. इसके बाद, Chrome में यूएसबी डिवाइस चुनने वाला टूल दिखेगा. यहां से अपना डिवाइस चुना जा सकता है.
वाह!
WebUSB API के बिना यह प्रोसेस कैसी होगी?
- किसी प्लैटफ़ॉर्म के लिए खास तौर पर बनाया गया ऐप्लिकेशन इंस्टॉल करना.
- अगर यह मेरे ऑपरेटिंग सिस्टम पर काम करता है, तो पुष्टि करें कि मैंने सही ऐप्लिकेशन डाउनलोड किया है.
- थिंग इंस्टॉल करें. अगर आपका डिवाइस सही तरीके से काम कर रहा है, तो आपको इंटरनेट से ड्राइवर/ऐप्लिकेशन इंस्टॉल करने के बारे में, ओएस से कोई डरावना मैसेज या पॉप-अप नहीं दिखेगा. अगर आपके साथ ऐसा होता है, तो इंस्टॉल किए गए ड्राइवर या ऐप्लिकेशन ठीक से काम नहीं करते और आपके कंप्यूटर को नुकसान पहुंचाते हैं. (याद रखें कि वेब को काम न करने वाली वेबसाइटों को शामिल करने के लिए बनाया गया है).
- अगर इस सुविधा का इस्तेमाल सिर्फ़ एक बार किया जाता है, तो कोड आपके कंप्यूटर पर तब तक बना रहता है, जब तक आप उसे हटाने का फ़ैसला नहीं ले लेते. (वेब पर, इस्तेमाल न किए गए स्पेस को आखिर में फिर से हासिल कर लिया जाता है.)
शुरू करने से पहले
इस लेख के मुताबिक, आपको यूएसबी के काम करने के तरीके की कुछ बुनियादी जानकारी है. अगर ऐसा नहीं है, तो हमारा सुझाव है कि आप यूएसबी के बारे में खास जानकारी पढ़ें. यूएसबी के बारे में ज़्यादा जानकारी के लिए, यूएसबी की आधिकारिक खास जानकारी देखें.
WebUSB API, Chrome 61 में उपलब्ध है.
ऑरिजिन ट्रायल के लिए उपलब्ध
इस फ़ील्ड में WebUSB API का इस्तेमाल करने वाले डेवलपर से ज़्यादा से ज़्यादा सुझाव, शिकायत या राय पाने के लिए, हमने पहले इस सुविधा को Chrome 54 और Chrome 57 में ऑरिजिन ट्रायल के तौर पर जोड़ा है.
नया ट्रायल, सितंबर 2017 में खत्म हो गया है.
निजता और सुरक्षा
सिर्फ़ एचटीटीपीएस
इस सुविधा की खास बात यह है कि यह सिर्फ़ सुरक्षित कॉन्टेक्स्ट पर काम करती है. इसका मतलब है कि आपको TLS को ध्यान में रखकर बनाना होगा.
उपयोगकर्ता के जेस्चर की ज़रूरत है
सुरक्षा से जुड़ी सावधानी के तौर पर, navigator.usb.requestDevice()
को सिर्फ़ उपयोगकर्ता के जेस्चर से कॉल किया जा सकता है. जैसे, टच या माउस क्लिक.
अनुमतियों की नीति
अनुमतियों की नीति एक ऐसा तरीका है जिसकी मदद से डेवलपर, ब्राउज़र की अलग-अलग सुविधाओं और एपीआई को चुनिंदा तौर पर चालू और बंद कर सकते हैं. इसे एचटीटीपी हेडर और/या iframe "allow" एट्रिब्यूट के ज़रिए तय किया जा सकता है.
अनुमतियों की ऐसी नीति तय की जा सकती है जो यह कंट्रोल करती है कि usb
एट्रिब्यूट, नेविगेटर ऑब्जेक्ट पर दिखाया जाए या नहीं. दूसरे शब्दों में, यह नीति यह तय करती है कि WebUSB को अनुमति दी जाए या नहीं.
यहां हेडर नीति का एक उदाहरण दिया गया है, जिसमें WebUSB की अनुमति नहीं है:
Feature-Policy: fullscreen "*"; usb "none"; payment "self" https://payment.example.com
यहां कंटेनर की ऐसी नीति का एक और उदाहरण दिया गया है जिसमें यूएसबी की अनुमति है:
<iframe allowpaymentrequest allow="usb; fullscreen"></iframe>
आइए, कोडिंग शुरू करें
WebUSB API, JavaScript Promises पर काफ़ी निर्भर करता है. अगर आपको इनके बारे में जानकारी नहीं है, तो Promises ट्यूटोरियल देखें. एक और बात, () => {}
सिर्फ़ ECMAScript 2015 ऐरो फ़ंक्शन हैं.
यूएसबी डिवाइसों का ऐक्सेस पाना
navigator.usb.requestDevice()
का इस्तेमाल करके, उपयोगकर्ता से कनेक्ट किए गए किसी एक यूएसबी डिवाइस को चुनने के लिए कहा जा सकता है. इसके अलावा, navigator.usb.getDevices()
को कॉल करके, कनेक्ट किए गए उन सभी यूएसबी डिवाइसों की सूची देखी जा सकती है जिनका ऐक्सेस वेबसाइट को दिया गया है.
navigator.usb.requestDevice()
फ़ंक्शन में ज़रूरी JavaScript ऑब्जेक्ट का इस्तेमाल किया जाता है, जो filters
की परिभाषा देता है. इन फ़िल्टर का इस्तेमाल, किसी भी यूएसबी डिवाइस को दिए गए वेंडर (vendorId
) और ज़रूरत पड़ने पर, प्रॉडक्ट (productId
) आइडेंटिफ़ायर से मैच करने के लिए किया जाता है.
classCode
, protocolCode
, serialNumber
, और subclassCode
कुंजियों को वहां भी तय किया जा सकता है.
उदाहरण के लिए, यहां उस Arduino डिवाइस का ऐक्सेस पाने का तरीका बताया गया है जिसे ऑरिजिन को अनुमति देने के लिए कॉन्फ़िगर किया गया है.
navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] })
.then(device => {
console.log(device.productName); // "Arduino Micro"
console.log(device.manufacturerName); // "Arduino LLC"
})
.catch(error => { console.error(error); });
आपके पूछने से पहले, मैं 0x2341
हेक्साडेसिमल नंबर को आपके हिसाब से नहीं समझ पाई. मैंने बस इस यूएसबी आईडी की सूची में "Arduino" शब्द के लिए खोज की है.
ऊपर दिए गए, पूरे किए गए वादे में दिखाए गए यूएसबी device
में, डिवाइस के बारे में कुछ बुनियादी, फिर भी अहम जानकारी होती है. जैसे, काम करने वाला यूएसबी वर्शन, ज़्यादा से ज़्यादा पैकेट साइज़, वेंडर, और प्रॉडक्ट आईडी. साथ ही, डिवाइस में संभावित कॉन्फ़िगरेशन की संख्या. आम तौर पर, इसमें डिवाइस के यूएसबी डिस्क्रिप्टर के सभी फ़ील्ड शामिल होते हैं.
// Get all connected USB devices the website has been granted access to.
navigator.usb.getDevices().then(devices => {
devices.forEach(device => {
console.log(device.productName); // "Arduino Micro"
console.log(device.manufacturerName); // "Arduino LLC"
});
})
अगर कोई यूएसबी डिवाइस, WebUSB के साथ काम करने की सुविधा के साथ-साथ, लैंडिंग पेज के यूआरएल की जानकारी देता है, तो यूएसबी डिवाइस प्लग इन होने पर Chrome, लगातार सूचना दिखाएगा. इस सूचना पर क्लिक करने से लैंडिंग पेज खुल जाएगा.
Arduino यूएसबी बोर्ड से बात करना
ठीक है, अब देखते हैं कि WebUSB के साथ काम करने वाले Arduino बोर्ड से, USB पोर्ट के ज़रिए डेटा भेजना और पाना कितना आसान है. अपने स्केच को WebUSB की मदद से चालू करने के लिए, https://github.com/webusb/arduino पर दिए गए निर्देश देखें.
चिंता न करें, इस लेख में आगे, WebUSB डिवाइस के सभी तरीकों के बारे में बताया जाएगा.
let device;
navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] })
.then(selectedDevice => {
device = selectedDevice;
return device.open(); // Begin a session.
})
.then(() => device.selectConfiguration(1)) // Select configuration #1 for the device.
.then(() => device.claimInterface(2)) // Request exclusive control over interface #2.
.then(() => device.controlTransferOut({
requestType: 'class',
recipient: 'interface',
request: 0x22,
value: 0x01,
index: 0x02})) // Ready to receive data
.then(() => device.transferIn(5, 64)) // Waiting for 64 bytes of data from endpoint #5.
.then(result => {
const decoder = new TextDecoder();
console.log('Received: ' + decoder.decode(result.data));
})
.catch(error => { console.error(error); });
ध्यान रखें कि जिस WebUSB लाइब्रेरी का इस्तेमाल किया जा रहा है वह सिर्फ़ एक उदाहरण प्रोटोकॉल (स्टैंडर्ड यूएसबी सीरियल प्रोटोकॉल के आधार पर) लागू कर रही है. साथ ही, मैन्युफ़ैक्चरर अपनी पसंद के मुताबिक, एंडपॉइंट का कोई भी सेट और टाइप बना सकते हैं. कंट्रोल ट्रांसफ़र, छोटे कॉन्फ़िगरेशन कमांड के लिए खास तौर पर अच्छे होते हैं, क्योंकि उन्हें बस की प्राथमिकता मिलती है और उनका स्ट्रक्चर अच्छी तरह से तय होता है.
यहां Arduino बोर्ड पर अपलोड किया गया स्केच दिया गया है.
// Third-party WebUSB Arduino library
#include <WebUSB.h>
WebUSB WebUSBSerial(1 /* https:// */, "webusb.github.io/arduino/demos");
#define Serial WebUSBSerial
void setup() {
Serial.begin(9600);
while (!Serial) {
; // Wait for serial port to connect.
}
Serial.write("WebUSB FTW!");
Serial.flush();
}
void loop() {
// Nothing here for now.
}
ऊपर दिए गए सैंपल कोड में इस्तेमाल की गई तीसरे पक्ष की WebUSB Arduino लाइब्रेरी, मुख्य रूप से दो काम करती है:
- यह डिवाइस, WebUSB डिवाइस के तौर पर काम करता है. इससे Chrome, लैंडिंग पेज के यूआरएल को पढ़ पाता है.
- इससे WebUSB का सीरियल एपीआई दिखता है. इसका इस्तेमाल, डिफ़ॉल्ट एपीआई को बदलने के लिए किया जा सकता है.
JavaScript कोड को फिर से देखें. जब उपयोगकर्ता मुझे device
चुन लेगा, तब यूएसबी डिवाइस के साथ सेशन शुरू करने के लिए, device.open()
प्लैटफ़ॉर्म के हिसाब से सभी चरण पूरे करता है. इसके बाद, मुझे device.selectConfiguration()
के साथ उपलब्ध USB कॉन्फ़िगरेशन चुनना होगा. याद रखें कि कॉन्फ़िगरेशन से यह पता चलता है कि डिवाइस को कैसे पावर दी जाती है, उसकी ज़्यादा से ज़्यादा पावर खपत क्या है, और उसके इंटरफ़ेस की संख्या कितनी है.
इंटरफ़ेस के बारे में बात करते हुए, मुझे device.claimInterface()
के साथ खास ऐक्सेस का अनुरोध भी करना होगा. ऐसा इसलिए, क्योंकि इंटरफ़ेस पर दावा करने के बाद ही डेटा को किसी इंटरफ़ेस या उससे जुड़े एंडपॉइंट पर ट्रांसफ़र किया जा सकता है. आखिर में, Arduino डिवाइस को WebUSB सीरियल एपीआई के ज़रिए कम्यूनिकेट करने के लिए, सही निर्देशों के साथ सेट अप करने के लिए, device.controlTransferOut()
को कॉल करना ज़रूरी है.
इसके बाद, device.transferIn()
डिवाइस पर बल्क डेटा ट्रांसफ़र करता है, ताकि उसे यह जानकारी मिल सके कि होस्ट बल्क डेटा पाने के लिए तैयार है. इसके बाद, प्रॉमिस को ऐसे result
ऑब्जेक्ट के साथ पूरा किया जाता है जिसमें DataView data
होता है और इसे सही तरीके से पार्स करना होता है.
अगर आपको यूएसबी के बारे में पता है, तो आपको यह सब काफ़ी जाना-पहचाना लगेगा.
मुझे और जानकारी चाहिए
WebUSB API की मदद से, सभी यूएसबी ट्रांसफ़र/एंडपॉइंट टाइप के साथ इंटरैक्ट किया जा सकता है:
- कंट्रोल ट्रांसफ़र, यूएसबी डिवाइस पर कॉन्फ़िगरेशन या कमांड पैरामीटर भेजने या पाने के लिए इस्तेमाल किए जाते हैं. इन्हें
controlTransferIn(setup, length)
औरcontrolTransferOut(setup, data)
से मैनेज किया जाता है. - थोड़े समय के लिए ज़रूरी डेटा के लिए इस्तेमाल किए जाने वाले 'ट्रांसफ़र रोकें' विकल्प को,
transferIn(endpointNumber, length)
औरtransferOut(endpointNumber, data)
के साथ बल्क ट्रांसफ़र के जैसे ही मैनेज किया जाता है. - वीडियो और साउंड जैसी डेटा स्ट्रीम के लिए, एक साथ होने वाले ट्रांसफ़र का इस्तेमाल किया जाता है. इन्हें
isochronousTransferIn(endpointNumber, packetLengths)
औरisochronousTransferOut(endpointNumber, data, packetLengths)
के साथ मैनेज किया जाता है. - एक साथ कई फ़ाइलें ट्रांसफ़र करने की सुविधा का इस्तेमाल, बहुत ज़्यादा डेटा को भरोसेमंद तरीके से ट्रांसफ़र करने के लिए किया जाता है. इसमें,
transferIn(endpointNumber, length)
औरtransferOut(endpointNumber, data)
का इस्तेमाल किया जाता है.
माइक त्साओ के WebLight प्रोजेक्ट पर भी एक नज़र डालें. इसमें, WebUSB API के लिए डिज़ाइन किए गए यूएसबी से कंट्रोल किए जाने वाले एलईडी डिवाइस को बनाने का उदाहरण दिया गया है. इसमें Arduino का इस्तेमाल नहीं किया गया है. आपको हार्डवेयर, सॉफ़्टवेयर, और फ़र्मवेयर मिलेंगे.
किसी यूएसबी डिवाइस का ऐक्सेस वापस लेना
वेबसाइट, USBDevice
इंस्टेंस पर forget()
को कॉल करके, उस यूएसबी डिवाइस को ऐक्सेस करने की अनुमतियों को हटा सकती है जिसकी अब उसे ज़रूरत नहीं है. उदाहरण के लिए, कई डिवाइसों के साथ शेयर किए जा रहे कंप्यूटर पर इस्तेमाल किए जाने वाले शैक्षणिक वेब ऐप्लिकेशन के लिए, उपयोगकर्ता से मिली अनुमतियों की बड़ी संख्या से उपयोगकर्ता अनुभव खराब हो जाता है.
// Voluntarily revoke access to this USB device.
await device.forget();
forget()
, Chrome 101 या इसके बाद के वर्शन में उपलब्ध है. इसलिए, देखें कि यह सुविधा इनके साथ काम करती है या नहीं:
if ("usb" in navigator && "forget" in USBDevice.prototype) {
// forget() is supported.
}
ट्रांसफ़र किए जाने वाले डेटा के साइज़ की सीमाएं
कुछ ऑपरेटिंग सिस्टम, USB के ज़रिए किए जाने वाले लेन-देन में, डेटा के ट्रांसफ़र की सीमा तय करते हैं. अपने डेटा को छोटे-छोटे ट्रांज़ैक्शन में बांटें और एक बार में सिर्फ़ कुछ ही ट्रांज़ैक्शन को सबमिट करने से इन सीमाओं से बचा जा सकता है. इससे इस्तेमाल की जाने वाली मेमोरी की मात्रा भी कम हो जाती है. साथ ही, ट्रांसफ़र पूरा होने पर, आपके ऐप्लिकेशन को प्रोग्रेस की रिपोर्ट करने की सुविधा मिलती है.
किसी एंडपॉइंट पर सबमिट किए गए कई ट्रांसफ़र हमेशा क्रम में लागू होते हैं. इसलिए, USB ट्रांसफ़र के बीच लगने वाले इंतज़ार से बचने के लिए, सूची में मौजूद कई चंक सबमिट करके, डेटा ट्रांसफ़र की स्पीड को बेहतर बनाया जा सकता है. जब भी कोई चंक पूरी तरह से ट्रांसमिट हो जाएगा, तो यह आपके कोड को सूचना देगा कि उसे ज़्यादा डेटा देना चाहिए. इस बारे में, यहां दिए गए हेल्पर फ़ंक्शन के उदाहरण में बताया गया है.
const BULK_TRANSFER_SIZE = 16 * 1024; // 16KB
const MAX_NUMBER_TRANSFERS = 3;
async function sendRawPayload(device, endpointNumber, data) {
let i = 0;
let pendingTransfers = [];
let remainingBytes = data.byteLength;
while (remainingBytes > 0) {
const chunk = data.subarray(
i * BULK_TRANSFER_SIZE,
(i + 1) * BULK_TRANSFER_SIZE
);
// If we've reached max number of transfers, let's wait.
if (pendingTransfers.length == MAX_NUMBER_TRANSFERS) {
await pendingTransfers.shift();
}
// Submit transfers that will be executed in order.
pendingTransfers.push(device.transferOut(endpointNumber, chunk));
remainingBytes -= chunk.byteLength;
i++;
}
// And wait for last remaining transfers to complete.
await Promise.all(pendingTransfers);
}
सलाह
Chrome में यूएसबी को डीबग करना आसान है. इसके लिए, इंटरनल पेज about://device-log
पर जाएं. यहां आपको यूएसबी डिवाइस से जुड़े सभी इवेंट एक ही जगह पर दिखेंगे.
इंटरनल पेज about://usb-internals
भी काम का है. इसकी मदद से, वर्चुअल WebUSB डिवाइसों को कनेक्ट और डिसकनेक्ट करने की प्रक्रिया को सिम्युलेट किया जा सकता है.
यह असल हार्डवेयर के बिना यूज़र इंटरफ़ेस (यूआई) टेस्टिंग करने में मददगार होता है.
ज़्यादातर Linux सिस्टम पर, यूएसबी डिवाइसों को डिफ़ॉल्ट रूप से, सिर्फ़ पढ़ने की अनुमतियों के साथ मैप किया जाता है. Chrome को यूएसबी डिवाइस खोलने की अनुमति देने के लिए, आपको एक नया udev
नियम जोड़ना होगा. /etc/udev/rules.d/50-yourdevicename.rules
पर, यहां दिए गए कॉन्टेंट वाली फ़ाइल बनाएं:
SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"
उदाहरण के लिए, अगर आपका डिवाइस Arduino है, तो [yourdevicevendor]
की जगह 2341
होगा.
ज़्यादा खास नियम के लिए भी ATTR{idProduct}
जोड़ा जा सकता है. पक्का करें कि आपका user
, plugdev
ग्रुप का सदस्य हो. इसके बाद, अपने डिवाइस को फिर से कनेक्ट करें.
संसाधन
- स्टैक ओवरफ़्लो: https://stackoverflow.com/questions/tagged/webusb
- WebUSB API की खास जानकारी: http://wicg.github.io/webusb/
- Chrome की सुविधा की स्थिति: https://www.chromestatus.com/feature/5651917954875392
- स्पेसिफ़िकेशन से जुड़ी समस्याएं: https://github.com/WICG/webusb/issues
- लागू करने से जुड़ी गड़बड़ियां: http://crbug.com?q=component:Blink>USB
- WebUSB ❤ ️Arduino: https://github.com/webusb/arduino
- आईआरसी: W3C के आईआरसी पर #webusb
- डब्ल्यूआईसीजी ईमेल पाने वाले लोगों की सूची: https://lists.w3.org/Archives/Public/public-wicg/
- WebLight प्रोजेक्ट: https://github.com/sowbug/weblight
#WebUSB
हैशटैग का इस्तेमाल करके, @ChromiumDev को ट्वीट करें और हमें बताएं कि इसका इस्तेमाल कहां और कैसे किया जा रहा है.
धन्यवाद
इस लेख की समीक्षा करने के लिए, Joe Medley का धन्यवाद.