वेब पर यूएसबी डिवाइसों को ऐक्सेस करना

WebUSB API, यूएसबी को वेब पर लाकर, उसे इस्तेमाल करने में आसान और सुरक्षित बनाता है.

François Beaufort
François Beaufort

अगर मैंने साफ़ शब्दों में "यूएसबी" कहा, तो इस बात की बहुत ज़्यादा संभावना है कि कीबोर्ड, माउस, ऑडियो, वीडियो, और स्टोरेज डिवाइसों के बारे में तुरंत सोचें. कोई बकाया राशि नहीं है हालांकि, आपको दूसरी तरह के यूनिवर्सल सीरियल बस (यूएसबी) वाले डिवाइस मिलेंगे वहाँ.

इन नॉन-स्टैंडर्ड यूएसबी डिवाइसों में, हार्डवेयर वेंडर को प्लैटफ़ॉर्म के हिसाब से कॉन्टेंट लिखने की ज़रूरत होती है ड्राइवर और SDK टूल का इस्तेमाल कर सकें, ताकि आप (डेवलपर) उनका फ़ायदा ले सकें. अफ़सोस की बात यह है कि इस प्लैटफ़ॉर्म के खास कोड ने अब तक इन डिवाइसों का इस्तेमाल करने पर रोक लगाई हुई है को बेहतर बनाना है. WebUSB API के बनाए जाने की एक वजह यह भी है: USB डिवाइस सेवाओं को वेब पर प्रदर्शित करने का तरीका उपलब्ध कराती है. इस एपीआई की मदद से, हार्डवेयर मैन्युफ़ैक्चरर अपने ऐप्लिकेशन के लिए, क्रॉस-प्लैटफ़ॉर्म JavaScript SDK टूल बना सकेंगे डिवाइस.

लेकिन सबसे महत्वपूर्ण बात यह है कि उसे वेब पर कैसे भेजना है.

आइए, देखते हैं कि WebUSB API के साथ, आपको कैसा व्यवहार देखने को मिल सकता है:

  1. यूएसबी डिवाइस खरीदें.
  2. इसे अपने कंप्यूटर में प्लग करें. तुरंत दाईं ओर एक सूचना दिखती है इस डिवाइस के लिए वेबसाइट पर जाएं.
  3. सूचना पर क्लिक करें. वेबसाइट उपलब्ध है और उपयोग के लिए तैयार है!
  4. कनेक्ट करने के लिए क्लिक करें और Chrome में एक यूएसबी डिवाइस सिलेक्टर दिखाई देता है, जहां आप अपना डिवाइस चुनें.

टाडा!

WebUSB API के बिना यह प्रोसेस कैसी होगी?

  1. प्लैटफ़ॉर्म के हिसाब से ऐप्लिकेशन इंस्टॉल करें.
  2. यदि यह मेरे ऑपरेटिंग सिस्टम पर भी समर्थित है, तो जांचें कि मैंने बिलकुल सही.
  3. उस आइटम को इंस्टॉल करें. अगर आपकी किस्मत अच्छी है, तो आपको डरावने ओएस प्रॉम्प्ट या पॉप-अप नहीं मिलेंगे आपको इंटरनेट से ड्राइवर/ऐप्लिकेशन इंस्टॉल करने के बारे में चेतावनी देनी होगी. अगर आपने आपकी किस्मत अच्छी नहीं है, इंस्टॉल किए गए ड्राइवर या ऐप्लिकेशन की गड़बड़ी और नुकसान आपके कंप्यूटर पर. (याद रखें कि वेब को इस तरह बनाया गया है कि उसमें गड़बड़ी वेबसाइटें).
  4. अगर इस सुविधा का इस्तेमाल सिर्फ़ एक बार किया जाता है, तो कोड आपके कंप्यूटर पर तब तक रहता है, जब तक आप इसे हटाने के बारे में सोचें. (वेब पर, इस्तेमाल न किए गए स्पेस को आखिर में reclaimed.)

शुरू करने से पहले

इस लेख के मुताबिक, आपको यूएसबी के काम करने के तरीके की कुछ बुनियादी जानकारी है. अगर नहीं, तो NtShell में यूएसबी पढ़ने का सुझाव दें. यूएसबी के बारे में बैकग्राउंड जानकारी के लिए, यूएसबी के बारे में आधिकारिक जानकारी देखें.

WebUSB API, Chrome 61 में उपलब्ध है.

ऑरिजिन ट्रायल के लिए उपलब्ध है

WebUSB का इस्तेमाल करने वाले डेवलपर से ज़्यादा से ज़्यादा सुझाव, शिकायत या राय पाने के लिए एपीआई फ़ील्ड में, हमने पहले इस सुविधा को Chrome 54 और Chrome में जोड़ा था 57 को ऑरिजिन ट्रायल के तौर पर फ़्लैग करें.

नया ट्रायल सितंबर 2017 में खत्म हो गया है.

निजता और सुरक्षा

सिर्फ़ एचटीटीपीएस

इस सुविधा की बेहतरीन सुविधाओं की वजह से, यह सिर्फ़ सुरक्षित कॉन्टेक्स्ट पर काम करती है. इसका मतलब है तो आपको TLS को ध्यान में रखकर बनाना होगा.

उपयोगकर्ता का जेस्चर ज़रूरी है

सुरक्षा के लिहाज़ से, navigator.usb.requestDevice() सिर्फ़ उपयोगकर्ता जेस्चर के ज़रिए कॉल किया जाना चाहिए, जैसे कि छूना या माउस क्लिक करना.

अनुमतियों की नीति

अनुमतियों की नीति एक ऐसा तरीका है जिससे डेवलपर को चुनिंदा तरीके से ये सेटिंग चालू करने की अनुमति मिलती है और ब्राउज़र की कई सुविधाओं और एपीआई को बंद कर सकता है. इसे एचटीटीपी के ज़रिए तय किया जा सकता है हेडर और/या iframe "अनुमति दें" एट्रिब्यूट की वैल्यू सबमिट करें.

अनुमतियों से जुड़ी नीति बनाई जा सकती है, जो यह कंट्रोल करती है कि usb एट्रिब्यूट को Navigator ऑब्जेक्ट पर या दूसरे शब्दों में तब दिखाया जाएगा, जब आप WebUSB की अनुमति दें.

नीचे हेडर नीति का एक उदाहरण दिया गया है, जिसमें WebUSB की अनुमति नहीं है:

Feature-Policy: fullscreen "*"; usb "none"; payment "self" https://payment.example.com

नीचे कंटेनर नीति का एक और उदाहरण दिया गया है, जिसमें यूएसबी की अनुमति है:

<iframe allowpaymentrequest allow="usb; fullscreen"></iframe>

आइए, कोडिंग शुरू करें

WebUSB API, JavaScript के वादों पर बहुत ज़्यादा निर्भर करता है. अगर आपको इसके बारे में नहीं पता है, तो साथ ही, यह शानदार प्रॉमिसेस ट्यूटोरियल देखें. एक और चीज़, () => {} बस ECMAScript 2015 के ऐरो फ़ंक्शन हैं.

यूएसबी डिवाइसों का ऐक्सेस पाएं

उपयोगकर्ता को इनमें से किसी एक विकल्प का इस्तेमाल करके, कनेक्ट किया गया यूएसबी डिवाइस चुनने के लिए कहा जा सकता है पाने के लिए navigator.usb.requestDevice() या navigator.usb.getDevices() पर कॉल करें कनेक्ट किए गए उन सभी यूएसबी डिवाइसों की सूची जिनका ऐक्सेस वेबसाइट को दे दिया गया है.

navigator.usb.requestDevice() फ़ंक्शन एक ज़रूरी JavaScript ऑब्जेक्ट लेता है जो filters को परिभाषित करता है. इन फ़िल्टर का उपयोग किसी भी USB डिवाइस को वेंडर (vendorId) और प्रॉडक्ट (productId) आइडेंटिफ़ायर दिए गए हैं. classCode, protocolCode, serialNumber, और subclassCode कुंजियां ये काम कर सकती हैं भी परिभाषित की गई हैं.

Chrome में यूएसबी डिवाइस इस्तेमाल करने के अनुरोध का स्क्रीनशॉट
यूएसबी डिवाइस के उपयोगकर्ता का अनुरोध.

उदाहरण के लिए, कनेक्ट किए गए 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 के साथ काम करने के बारे में बताता है और साथ ही लैंडिंग पेज URL तय करते हैं, तो Chrome उस समय एक स्थायी सूचना दिखाएगा जब यूएसबी डिवाइस को प्लग-इन किया गया है. इस सूचना पर क्लिक करने से लैंडिंग पेज खुलेगा.

Chrome में WebUSB सूचना का स्क्रीनशॉट
WebUSB सूचना.

किसी Arduino यूएसबी बोर्ड से बात करें

ठीक है, अब देखते हैं कि WebUSB के साथ काम करने वाले डिवाइस से कम्यूनिकेट करना कितना आसान है USB पोर्ट के ऊपर लगा Arduino बोर्ड. निर्देश यहां देखें https://github.com/webusb/arduino पर क्लिक करें और WebUSB की मदद से, अपने स्केच चालू करें.

चिंता न करें, मैं बाद में नीचे बताए गए 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(). याद रखें कि कॉन्फ़िगरेशन यह तय करता है कि डिवाइस का इस्तेमाल किया जाता है, उसकी ज़्यादा से ज़्यादा बिजली की खपत होती है, और उसमें कई इंटरफ़ेस हैं. इंटरफ़ेस की बात करें, तो मुझे इनके साथ खास ऐक्सेस का भी अनुरोध करना होगा device.claimInterface() क्योंकि डेटा को सिर्फ़ इंटरफ़ेस पर ट्रांसफ़र किया जा सकता है या इंटरफ़ेस पर दावा करने के दौरान, उससे जुड़े एंडपॉइंट. आख़िर में कॉल किया जा रहा है Arduino डिवाइस को device.controlTransferOut() ज़रूरी कमांड का इस्तेमाल करें.

वहां से, device.transferIn() डिवाइस को सूचित कर देगा कि होस्ट बल्क डेटा प्राप्त करने के लिए तैयार है. इसके बाद, प्रॉमिस को उस result ऑब्जेक्ट के साथ पूरा किया जाता है जिसमें DataView data शामिल होता है, जो को सही तरीके से पार्स करना होगा.

अगर आपको यूएसबी के बारे में पता है, तो सब कुछ जाना-पहचाना होना चाहिए.

मुझे और चाहिए

WebUSB API की मदद से, सभी यूएसबी ट्रांसफ़र/एंडपॉइंट टाइप के साथ इंटरैक्ट किया जा सकता है:

  • कंट्रोल ट्रांसफ़र, जिसका इस्तेमाल कॉन्फ़िगरेशन या निर्देश भेजने या पाने के लिए किया जाता है यूएसबी डिवाइस के पैरामीटर, controlTransferIn(setup, length) और controlTransferOut(setup, data) की मदद से हैंडल किए जाते हैं.
  • INTERRUPT ट्रांसफ़र का इस्तेमाल, कुछ समय के लिए संवेदनशील जानकारी के लिए किया जाता है. उसी तरीके से हैंडल किए जाते हैं जैसे BULK का इस्तेमाल करके ट्रांसफ़र किया जाता है transferIn(endpointNumber, length) और transferOut(endpointNumber, data).
  • ISOCHRONOUS ट्रांसफ़र का इस्तेमाल, वीडियो और साउंड जैसे डेटा स्ट्रीम के लिए किया जाता है. isochronousTransferIn(endpointNumber, packetLengths) ने हैंडल किया और isochronousTransferOut(endpointNumber, data, packetLengths).
  • BULK ट्रांसफ़र का इस्तेमाल करके, ऐसे डेटा को ट्रांसफ़र किया जाता है जो समय के हिसाब से संवेदनशील नहीं है उन्हें भरोसेमंद बनाने के लिए, transferIn(endpointNumber, length) और transferOut(endpointNumber, data).

शायद आप माइक त्साओ के WebLight प्रोजेक्ट को भी देखना चाहें इस उदाहरण में, यूएसबी से कंट्रोल किए गए एलईडी डिवाइस को बनाने का उदाहरण दिया गया है. इस डिवाइस को इस तरह से डिज़ाइन किया गया है (यहां Arduino का इस्तेमाल नहीं किया जा रहा है). आपको हार्डवेयर, सॉफ़्टवेयर, और फ़र्मवेयर.

यूएसबी डिवाइस से ऐक्सेस वापस लेना

वेबसाइट, ऐसे यूएसबी डिवाइस को ऐक्सेस करने के लिए अनुमतियों में बदलाव कर सकती है जिसकी अब ज़रूरत नहीं है USBDevice इंस्टेंस पर forget() कॉल करके. उदाहरण के लिए, किसी ऐसे कंप्यूटर पर इस्तेमाल किया जाने वाला शिक्षा से जुड़ा वेब ऐप्लिकेशन जिसे कई डिवाइसों पर इस्तेमाल किया जाता है. उपयोगकर्ताओं की जनरेट की गई अनुमतियों की संख्या भी कम हो जाती है. इससे उपयोगकर्ता अनुभव पर बुरा असर पड़ता है.

// Voluntarily revoke access to this USB device.
await device.forget();

Chrome 101 या इसके बाद के वर्शन में forget() उपलब्ध है. इसलिए, देखें कि यह सुविधा इनके साथ काम करता है:

if ("usb" in navigator && "forget" in USBDevice.prototype) {
  // forget() is supported.
}

ट्रांसफ़र साइज़ की सीमाएं

कुछ ऑपरेटिंग सिस्टम, डेटा के इस्तेमाल की सीमा तय करते हैं लंबित 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);
}

सलाह

इंटरनल पेज about://device-log से, Chrome में यूएसबी को डीबग करना आसान है जहां आपको एक ही जगह पर, यूएसबी डिवाइस से जुड़े सभी इवेंट दिखेंगे.

Chrome में WebUSB को डीबग करने के लिए, डिवाइस के लॉग पेज का स्क्रीनशॉट
WebUSB API को डीबग करने के लिए, Chrome में डिवाइस का लॉग पेज.

आंतरिक पेज about://usb-internals भी काम में आता है और आपको इसकी सुविधा देता है का इस्तेमाल, वर्चुअल WebUSB डिवाइसों के कनेक्शन और डिस्कनेक्शन को सिम्युलेट करने के लिए किया जाता है. यह असल हार्डवेयर के बिना यूज़र इंटरफ़ेस (यूआई) टेस्टिंग करने में मददगार होता है.

Chrome में WebUSB को डीबग करने के लिए, इंटरनल पेज का स्क्रीनशॉट
WebUSB API को डीबग करने के लिए, Chrome का इंटरनल पेज.

ज़्यादातर Linux सिस्टम पर, यूएसबी डिवाइसों को रीड-ओनली अनुमतियों के साथ मैप किया जाता है: डिफ़ॉल्ट. Chrome को यूएसबी डिवाइस खोलने की अनुमति देने के लिए, आपको एक नया udev जोड़ना होगा नियम में सेट अप किया गया है. /etc/udev/rules.d/50-yourdevicename.rules पर फ़ाइल बनाने के लिए निम्न सामग्री:

SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"

जहां [yourdevicevendor], 2341 है. उदाहरण के लिए, आपके डिवाइस का नाम Arduino है. ज़्यादा खास नियम के लिए भी ATTR{idProduct} जोड़ा जा सकता है. पक्का करें कि user, plugdev ग्रुप का सदस्य है. इसके बाद, अपने डिवाइस को फिर से कनेक्ट करें.

संसाधन

हैशटैग का इस्तेमाल करके @ChromiumDev को ट्वीट भेजें #WebUSB और हमें बताएं कि उसका इस्तेमाल कहां और कैसे किया जा रहा है.

स्वीकार की गई

इस लेख को पढ़ने के लिए, जो मेडली का धन्यवाद.