Web'deki USB Cihazlara Erişme

WebUSB API, USB'yi web'e taşıyarak daha güvenli ve kolay bir şekilde kullanılmasını sağlar.

François Beaufort
François Beaufort

Sade bir şekilde ve sadece "USB" dediysem klavyeleri, fareleri, sesleri, videoları ve depolama cihazlarını hemen düşünün. Artık ama başka türlerde Universal Serial Bus (USB) cihazları da vardır. inceleyeceğiz.

Bu standart olmayan USB cihazları, donanım tedarikçilerinin platforma özgü metin yazması gerekir sizin (geliştirici) yararlanabilmeniz için sürücüleri ve SDK'ları Ne yazık ki bu platforma özgü kod, geçmişte bu cihazların kullanılmasını engelliyordu sunar. WebUSB API'nin oluşturulma nedenlerinden biri de budur: USB cihaz hizmetlerinin Web'de açığa çıkarılması için bir yöntem sağlar. Bu API ile donanım, üreticiler, kendileri için platformlar arası JavaScript SDK'ları oluşturabilecek, cihazlar.

Ancak en önemlisi de bu; ya da yeni bir özellik oluşturarak USB'nin web'e iletebilir.

WebUSB API'de karşılaşabileceğiniz davranışı inceleyelim:

  1. Bir USB cihazı satın alın.
  2. Bilgisayarınıza takın. Hemen bir bildirim görünür ve bu cihaz için gidilecek bir web sitesi.
  3. Bildirimi tıklayın. Web sitesi hazır ve kullanıma hazır.
  4. Bağlanmak için tıklayın. Chrome'da bir USB cihaz seçici görünür. Buradan, cihazınızı seçin.

İşte oldu!

WebUSB API olmadan bu prosedür nasıl olurdu?

  1. Platforma özel bir uygulama yükleyin.
  2. İşletim sistemimde destekleniyorsa dosyayı indirdiğimden emin olmak için emin olmanız gerekir.
  3. Ürünü yükleyin. Şanslıysanız korkutucu işletim sistemi istemleri veya pop-up'larla karşılaşmazsınız İnternet'ten sürücü/uygulama yükleme konusunda sizi uyarır. Eğer şanssızsanız yüklü sürücüler veya uygulamalar hatalı çalışır ve zarar görür bilgisayarınızdan erişebilirsiniz. (Web'in, kalite standartlarının hatalı olabilecek ziyaret edin).
  4. Bu özelliği yalnızca bir kez kullanırsanız kod siz izin verene kadar bilgisayarınızda kalır. kaldırabilirsiniz. (Web'de kullanılmayan alan nihayetinde reclaimed.)

Başlamadan önce

Bu makalede USB'nin işleyişiyle ilgili bazı temel bilgilere sahip olduğunuz varsayılmaktadır. Aksi halde NutShell'de USB'yi okumanızı öneririz. USB hakkında arka plan bilgileri için resmi USB özelliklerine göz atın.

WebUSB API, Chrome 61'de kullanılabilir.

Kaynak denemeleri için kullanılabilir

WebUSB kullanan geliştiricilerden mümkün olduğunca fazla geri bildirim almak için Chrome 54 ve Chrome'a bu özelliği daha önce ekledik, 57'yi kaynak denemesinde kullanabilirsiniz.

Son deneme sürümü Eylül 2017'de başarıyla sona erdi.

Gizlilik ve güvenlik

Yalnızca HTTPS

Bu özellik, gücü sayesinde yalnızca güvenli bağlamlarda çalışır. Bunun anlamı şudur: TLS'yi göz önünde bulundurarak geliştirmeniz gerekir.

Kullanıcı hareketi gerekli

Güvenlik önlemi olarak navigator.usb.requestDevice(), Dokunma veya fare tıklaması gibi bir kullanıcı hareketiyle çağrılabilir.

İzin Politikası

İzin Politikası, geliştiricilerin istediklerini seçmelerine olanak tanıyan bir mekanizmadır ve çeşitli tarayıcı özelliklerini ve API'leri devre dışı bırakın. HTTP üzerinden tanımlanabilir üstbilgi ve/veya iframe "allow" özelliğini gönderin.

usb özelliğinin Navigator nesnesinde gösterilir veya diğer bir deyişle WebUSB'ye izin verirseniz

Aşağıda, WebUSB'ye izin verilmeyen bir başlık politikası örneği verilmiştir:

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

Aşağıda, USB'ye izin verilen bir kapsayıcı politikasına başka bir örnek verilmiştir:

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

Kodlamaya başlayalım

WebUSB API, yoğun olarak JavaScript Promises'i kullanır. Bilmiyorsanız daha fazla bilgi için bu Promises eğiticisini inceleyin. Bir şey daha, () => {} basitçe ECMAScript 2015 ok işlevleridir.

USB cihazlarına erişim elde etme

Kullanıcıdan bağlı tek bir USB cihazını seçmesini isteyebilirsiniz: navigator.usb.requestDevice() veya navigator.usb.getDevices() numaralı telefonu arayarak web sitesinin erişmesine izin verilen tüm bağlı USB cihazlarının listesi.

navigator.usb.requestDevice() işlevi, zorunlu bir JavaScript nesnesi alıyor filters öğesini tanımlayan bir ifadedir. Bu filtreler, USB cihazlarıyla bu cihazları eşleştirmek için kullanılır sağlanan tedarikçi firma (vendorId) ve isteğe bağlı olarak ürün (productId) tanımlayıcıları. classCode, protocolCode, serialNumber ve subclassCode anahtarları burada da tanımlanmalıdır.

Chrome&#39;daki USB cihaz kullanıcı isteminin ekran görüntüsü
USB cihaz kullanıcı istemi.

Örneğin, yapılandırılmış başka bir Arduino cihazına tıklayın.

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

Siz sormadan önce, bu 0x2341 onaltılık sayıyı sihirli bir şekilde düşünmemiştim sayı. "Arduino" kelimesini aradım USB Kimlikleri listesindeki bilgileri inceleyin.

Yukarıda belirtilen sözü yerine getiren USB device cihazındaki bazı temel özellikler cihazla ilgili önemli bilgileri (ör. desteklenen USB sürümü, paket boyutunu, tedarikçiyi ve ürün kimliklerini, olası yapılandırmanın ne kadar önemli olduğu. Temelde bu dosya, cihaz USB Tanımlayıcısı.

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

Bu arada, bir USB cihazı WebUSB desteğini bir açılış sayfası URL'si tanımlarsanız USB cihazı takılı. Bu bildirimi tıkladığınızda açılış sayfası açılır.

Chrome&#39;daki WebUSB bildiriminin ekran görüntüsü
WebUSB bildirimi.

Arduino USB kartı ile konuşun

Tamam, şimdi de WebUSB ile uyumlu bir cihazdan iletişim kurmanın ne kadar kolay olduğuna bakalım. USB bağlantı noktası üzerinden Arduino kartı. Talimatları şu adreste bulabilirsiniz: Çizimlerinizi etkinleştirmek için https://github.com/webusb/arduino adresine gidin.

Merak etmeyin, aşağıda belirtilen tüm WebUSB cihaz yöntemlerini daha sonra ele alacağız bu makaleye göz atın.

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

Kullanmakta olduğum WebUSB kitaplığının standart USB seri protokolüne göre hazırlanan ve üreticiler istedikleri uç nokta türlerini ve türlerini oluşturabilir. Kontrol aktarımları özellikle küçük yapılandırma komutlarında otobüse daha fazla öncelik veriliyor ve iyi tanımlanmış bir yapıya sahip.

İşte Arduino panosuna yüklenen çizim.

// 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.
}

Yukarıdaki örnek kodda kullanılan üçüncü taraf WebUSB Arduino kitaplığı iki şey var:

  • Cihaz, Chrome'un açılış sayfası URL'sini okumasını sağlayan bir WebUSB cihazı gibi çalışır.
  • Bu sayfada, varsayılan API'yi geçersiz kılmak için kullanabileceğiniz bir WebUSB Serial API gösterilir.

JavaScript koduna tekrar bakın. Kullanıcının seçtiği device öğesini aldığımda device.open(), USB ile oturum başlatmak için platforma özel tüm adımları çalıştırır olanak tanır. Ardından mevcut bir USB Yapılandırmasını seçmem gerekiyor. device.selectConfiguration() Bir yapılandırmanın, güç tüketimi ve arayüz sayısı. Arayüzlerden bahsetmişken Veriler yalnızca bir arayüze aktarılabildiği için device.claimInterface() veya ilişkilendirilen uç noktaları gösterir. Son arama yapılıyor Arduino cihazını kurmak için device.controlTransferOut() iletişim kurmak için uygun komutları içerebilir.

device.transferIn() oradan şuraya toplu aktarım yapar: ana makinenin toplu veri almaya hazır olduğunu bildirir. Ardından, söz konusu DataView data içeren result nesnesiyle ayrıştırılması gerekir.

USB'ye aşinaysanız tüm bunlar size tanıdık gelecektir.

Daha fazlasını istiyorum

WebUSB API'si tüm USB aktarım/uç nokta türleriyle etkileşimde bulunmanıza olanak tanır:

  • konfigürasyon veya komut göndermek ya da almak için DENETİM aktarımları parametreleri controlTransferIn(setup, length) ve controlTransferOut(setup, data) ile işlenir.
  • Kısa süreli hassas veriler için kullanılan INTERRUPT aktarımları toplu e-posta yoluyla yapılan aktarımlarla aynı yöntemlerle transferIn(endpointNumber, length) ve transferOut(endpointNumber, data).
  • Görüntü ve ses gibi veri akışları için kullanılan ISOCHRONOUS aktarımları, isochronousTransferIn(endpointNumber, packetLengths) ve ile ele alındı isochronousTransferOut(endpointNumber, data, packetLengths).
  • Toplu aktarımlar, zamana duyarlı olmayan büyük miktarda veriyi transferIn(endpointNumber, length) ile ele alınır ve güvenli bir şekilde işlenir. transferOut(endpointNumber, data).

Ayrıca Mike Tsao'nun WebLight projesine USB kontrollü LED cihazlar için iyi bir örnektir. (burada Arduino kullanılmamalıdır). Donanım, yazılım, ve donanım yazılımı.

USB cihazına erişimi iptal etme

Web sitesi, artık ihtiyaç duymadığı bir USB cihaza erişim için izinleri temizleyebilir USBDevice örneğinde forget() çağırarak. Örneğin, birçok cihazla paylaşılan bir bilgisayarda kullanılan eğitim amaçlı web uygulamasıdır; kullanıcı tarafından oluşturulan izinlerin birikmesi kötü bir kullanıcı deneyimine neden olmaktadır.

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

forget(), Chrome 101 veya sonraki sürümlerde kullanıma sunulduğundan bu özelliğin şunlar tarafından desteklenir:

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

Aktarım boyutuyla ilgili sınırlar

Bazı işletim sistemleri, bir sistem kapsamında yer alabilecek veri miktarına USB işlemleri beklemede. Verilerinizi daha küçük işlemlere bölme ve yalnızca aynı anda birkaç tane göndermek bu sınırlamalardan kaçınmanıza yardımcı olur. Aynı zamanda ve uygulamanızın ilerlemeyi aktarım tamamlandı.

Bir uç noktaya gönderilen birden fazla aktarım her zaman sırayla yürütülür. mümkün olduğunca hızlı ilerlemesini sağlamak için gecikme olabilir. Bir parçanın tamamen iletildiği her seferde kodunuza, yardımcıda belirtildiği şekilde daha fazla veri sağlaması gerektiğini bildirin işlev örneğini aşağıda bulabilirsiniz.

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

İpuçları

about://device-log dahili sayfasını kullanarak Chrome'da USB'de hata ayıklama işlemi daha kolay Burada, USB cihazıyla ilgili tüm etkinlikleri tek bir yerden görebilirsiniz.

Chrome&#39;da WebUSB hatalarını ayıklamak için kullanılan cihaz günlük sayfasının ekran görüntüsü
WebUSB API'de hata ayıklama için Chrome'daki cihaz günlük sayfası.

Dahili sayfa about://usb-internals da kullanışlı bir hale gelir ve sanal WebUSB cihazların bağlantısını ve bağlantısını kesmeyi simüle eder. Bu, gerçek donanım olmadan kullanıcı arayüzü testi yaparken faydalıdır.

Chrome&#39;da WebUSB hatalarını ayıklamak için kullanılan dahili sayfanın ekran görüntüsü
WebUSB API'de hata ayıklamayla ilgili Chrome'daki dahili sayfa.

Çoğu Linux sisteminde, USB cihazları salt okuma izinleriyle varsayılandır. Chrome'un bir USB cihazı açmasına izin vermek için yeni bir udev eklemeniz gerekir kuralı ekleyin. /etc/udev/rules.d/50-yourdevicename.rules adresinde takip eden içerik:

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

Örneğin, cihazınız bir Arduino ise [yourdevicevendor] değeri 2341 olur. Daha belirli bir kural için ATTR{idProduct} da eklenebilir. Lütfen user, plugdev grubunun üyesi. Ardından cihazınızı yeniden bağlayın.

Kaynaklar

Hashtag'i kullanarak @ChromiumDev hesabına tweet gönderin #WebUSB ve nerede ve nasıl kullandığınızı bize bildirin.

Teşekkür

Bu makaleyi incelediği için Joe Medley'e teşekkür ederiz.