WebUSB API membuat USB lebih aman dan lebih mudah digunakan dengan menghadirkannya ke Web.
Jika saya mengatakan dengan jelas dan sederhana "USB", ada kemungkinan bahwa Anda akan langsung memikirkan {i>keyboard<i}, {i>mouse<i}, audio, video, dan perangkat penyimpanan. Anda berada benar, tetapi Anda akan menemukan jenis perangkat {i>Universal Serial Bus<i} lain di luar di sana.
Perangkat USB yang tidak distandardisasi ini membutuhkan vendor perangkat keras untuk menulis {i>driver<i} dan SDK agar Anda (pengembang) dapat memanfaatkannya. Sayangnya, kode khusus platform ini secara historis mencegah perangkat ini digunakan oleh Web. Dan itulah salah satu alasan dibuatnya WebUSB API: menyediakan cara untuk mengekspos layanan perangkat USB ke Web. Dengan API ini, perangkat keras produsen akan dapat membangun SDK JavaScript lintas platform untuk perangkat.
Namun yang paling penting, hal ini akan membuat USB lebih aman dan mudah digunakan dengan ke Web.
Mari kita lihat perilaku yang dapat Anda harapkan dengan WebUSB API:
- Beli perangkat USB.
- Colokkan ke komputer. Notifikasi akan langsung muncul, dengan sisi situs web yang harus dikunjungi untuk perangkat ini.
- Klik notifikasi tersebut. Situs sudah tersedia dan siap digunakan!
- Klik untuk menghubungkan dan pemilih perangkat USB akan muncul di Chrome tempat Anda dapat pilih perangkatmu.
Tada!
Akan seperti apa prosedur ini tanpa WebUSB API?
- Instal aplikasi khusus platform.
- Jika itu didukung pada sistem operasi saya, pastikan bahwa saya telah mengunduh memastikannya.
- Instal aplikasi tersebut. Jika beruntung, Anda tidak akan mendapatkan prompt atau pop-up OS yang menakutkan memperingatkan Anda tentang menginstal {i>driver<i}/aplikasi dari internet. Jika Anda tidak beruntung, {i>driver<i} atau aplikasi yang terinstal tidak berfungsi dan membahayakan seperti di komputer Anda. (Ingat, web dibuat untuk mengandung fungsi yang tidak berfungsi situs).
- Jika Anda hanya menggunakan fitur ini satu kali, kode tetap berada di komputer hingga Anda berpikir untuk menghapusnya. (Di Web, ruang penyimpanan yang tidak terpakai pada akhirnya reclaimed.)
Sebelum saya mulai
Artikel ini mengasumsikan bahwa Anda memiliki pengetahuan dasar tentang cara kerja USB. Jika tidak, saya sebaiknya baca USB di NutShell. Untuk informasi latar belakang tentang USB, lihat spesifikasi USB resmi.
WebUSB API tersedia di Chrome 61.
Tersedia untuk uji coba origin
Untuk mendapatkan umpan balik sebanyak mungkin dari pengembang yang menggunakan WebUSB API di kolom, sebelumnya kami telah menambahkan fitur ini di Chrome 54 dan Chrome 57 sebagai uji coba origin.
Uji coba terbaru telah berhasil berakhir pada bulan September 2017.
Privasi dan keamanan
Khusus HTTPS
Karena kecanggihan fitur ini, fitur ini hanya berfungsi pada konteks yang aman. Artinya Anda harus membuat aplikasi dengan mempertimbangkan TLS.
Gestur pengguna diperlukan
Sebagai tindakan pengamanan, navigator.usb.requestDevice()
mungkin hanya
dipanggil melalui {i>gesture <i}pengguna seperti
sentuhan atau klik {i>mouse<i}.
Kebijakan Izin
Kebijakan Izin adalah mekanisme yang memungkinkan developer mengaktifkan secara selektif serta menonaktifkan berbagai fitur browser dan API. URL ini dapat ditentukan melalui HTTP header dan/atau "izinkan" iframe .
Anda dapat menetapkan Kebijakan Izin yang mengontrol apakah atribut usb
diekspos pada objek Navigator, atau dengan kata lain jika Anda mengizinkan WebUSB.
Berikut adalah contoh kebijakan header yang tidak mengizinkan WebUSB:
Feature-Policy: fullscreen "*"; usb "none"; payment "self" https://payment.example.com
Berikut adalah contoh lain kebijakan penampung yang mengizinkan USB:
<iframe allowpaymentrequest allow="usb; fullscreen"></iframe>
Mari mulai coding
WebUSB API sangat bergantung pada Promise JavaScript. Jika Anda tidak familier
dengan mereka, lihat tutorial Promise yang luar biasa ini. Satu hal lagi, () => {}
hanyalah fungsi Panah ECMAScript 2015.
Mendapatkan akses ke perangkat USB
Anda dapat meminta pengguna untuk memilih satu perangkat USB yang terhubung menggunakan
navigator.usb.requestDevice()
atau hubungi navigator.usb.getDevices()
untuk mendapatkan
daftar semua perangkat USB tersambung yang
dapat diakses oleh {i>website<i}.
Fungsi navigator.usb.requestDevice()
mengambil objek JavaScript wajib
yang menentukan filters
. Filter ini digunakan untuk mencocokkan perangkat USB apa pun dengan
ID vendor (vendorId
) tertentu dan, secara opsional, ID produk (productId
).
Kunci classCode
, protocolCode
, serialNumber
, dan subclassCode
dapat
juga didefinisikan di sana.
Misalnya, berikut ini cara mendapatkan akses ke perangkat Arduino yang terhubung dan telah dikonfigurasi untuk mengizinkan origin.
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); });
Sebelum Anda bertanya, saya tidak mendapatkan ide heksadesimal 0x2341
ini
angka Saya cukup cari kata "Arduino" dalam Daftar ID USB ini.
device
USB yang ditampilkan dalam promise yang telah terpenuhi di atas memiliki beberapa hal dasar, tetapi
informasi penting tentang perangkat,
seperti versi USB yang didukung,
ukuran paket maksimum, vendor, dan ID produk, jumlah
konfigurasi yang dapat dimiliki perangkat. Pada dasarnya ini berisi
semua {i>field <i}yang ada di
Deskripsi USB perangkat.
// 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"
});
})
Ngomong-ngomong, jika perangkat USB mengumumkan dukungan untuk WebUSB, menentukan URL halaman landing, Chrome akan menampilkan notifikasi persisten Perangkat USB dicolokkan. Mengklik notifikasi ini akan membuka halaman landing.
Berbicara dengan board USB Arduino
Oke, sekarang mari kita lihat betapa mudah berkomunikasi dari perangkat lunak yang kompatibel Board Arduino melalui port USB. Baca petunjuknya di https://github.com/webusb/arduino untuk mengaktifkan sketsa pada WebUSB.
Jangan khawatir, saya akan membahas semua metode perangkat WebUSB yang disebutkan di bawah nanti artikel ini.
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); });
Perlu diingat bahwa {i>library<i} WebUSB yang saya gunakan hanya mengimplementasikan satu contoh protokol (berdasarkan protokol serial USB standar) dan itu produsen dapat membuat set dan jenis endpoint apa pun yang mereka inginkan. Transfer kontrol sangat bagus untuk perintah konfigurasi kecil karena mereka mendapatkan prioritas bus dan memiliki struktur yang terdefinisi dengan baik.
Dan inilah sketsa yang telah diunggah ke papan 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.
}
Library Arduino WebUSB pihak ketiga yang digunakan dalam kode contoh di atas melakukan pada dasarnya ada dua hal:
- Perangkat bertindak sebagai perangkat WebUSB yang memungkinkan Chrome membaca URL halaman landing.
- WebUSB Serial API mengekspos WebUSB Serial API yang dapat Anda gunakan untuk mengganti versi default.
Lihat kode JavaScript lagi. Setelah saya mendapatkan device
yang dipilih oleh pengguna,
device.open()
menjalankan semua langkah khusus platform untuk memulai sesi dengan USB
perangkat seluler. Kemudian, saya harus memilih Konfigurasi
USB yang tersedia dengan
device.selectConfiguration()
. Perlu diingat bahwa konfigurasi menentukan bagaimana
perangkat dinyalakan, konsumsi daya maksimum, dan jumlah antarmukanya.
Berbicara tentang antarmuka, saya juga perlu
meminta akses eksklusif dengan
device.claimInterface()
karena data hanya dapat ditransfer ke antarmuka atau
endpoint terkait saat antarmuka diklaim. Akhirnya menelepon
device.controlTransferOut()
diperlukan untuk menyiapkan perangkat Arduino dengan
perintah yang sesuai untuk berkomunikasi
melalui WebUSB Serial API.
Dari sana, device.transferIn()
melakukan transfer massal ke
untuk memberi tahu bahwa {i>host<i} siap menerima data massal. Lalu,
promise terpenuhi dengan objek result
yang berisi data
DataView yang
harus diurai dengan benar.
Jika Anda sudah terbiasa dengan USB, semua ini akan terlihat cukup familier.
Saya ingin lebih banyak
WebUSB API memungkinkan Anda berinteraksi dengan semua jenis endpoint/transfer USB:
- CONTROL ditransfer, digunakan untuk mengirim atau menerima konfigurasi atau perintah
parameter ke perangkat USB, ditangani dengan
controlTransferIn(setup, length)
dancontrolTransferOut(setup, data)
. - Transfer INTERRUPT, yang digunakan untuk data sensitif dalam waktu singkat,
ditangani dengan metode yang sama seperti
transfer BULK dengan
transferIn(endpointNumber, length)
dantransferOut(endpointNumber, data)
. - Transfer ISOCHRONOUS, digunakan untuk
aliran data seperti video dan suara,
ditangani dengan
isochronousTransferIn(endpointNumber, packetLengths)
danisochronousTransferOut(endpointNumber, data, packetLengths)
. - Transfer BAGUS, digunakan untuk mentransfer data
yang tidak mendesak dalam jumlah besar di
dengan cara yang andal, ditangani dengan
transferIn(endpointNumber, length)
dantransferOut(endpointNumber, data)
.
Anda mungkin juga ingin melihat proyek WebLight Mike Tsao yang memberikan contoh dari bawah ke atas dari pembuatan perangkat LED yang dikontrol USB yang dirancang untuk WebUSB API (tidak menggunakan Arduino di sini). Anda akan menemukan perangkat keras, perangkat lunak, dan {i>firmware<i}.
Mencabut akses ke perangkat USB
Situs web dapat membersihkan izin akses ke perangkat USB yang tidak lagi diperlukan
dengan memanggil forget()
pada instance USBDevice
. Misalnya, untuk
aplikasi web pendidikan yang digunakan di komputer bersama
dengan banyak perangkat, sebuah
akumulasi izin yang dibuat pengguna akan
menghasilkan pengalaman pengguna yang buruk.
// Voluntarily revoke access to this USB device.
await device.forget();
Karena forget()
tersedia di Chrome 101 atau yang lebih baru, periksa apakah fitur ini
didukung dengan hal berikut:
if ("usb" in navigator && "forget" in USBDevice.prototype) {
// forget() is supported.
}
Batas ukuran transfer
Beberapa sistem operasi membatasi jumlah data yang dapat menjadi bagian dari transaksi USB yang tertunda. Memisahkan data Anda menjadi transaksi yang lebih kecil dan hanya mengirimkan beberapa template sekaligus membantu menghindari keterbatasan tersebut. Hal ini juga mengurangi jumlah memori yang digunakan dan memungkinkan aplikasi Anda melaporkan kemajuan sebagai transfer selesai.
Karena beberapa transfer yang dikirimkan ke titik akhir selalu dijalankan secara berurutan, meningkatkan throughput dengan mengirimkan beberapa potongan antrian untuk menghindari latensi antar-transfer USB. Setiap kali potongan dikirimkan secara penuh, kode itu akan memberi tahu kode untuk menyediakan lebih banyak data seperti yang didokumentasikan dalam contoh fungsi di bawah ini.
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);
}
Tips
Proses debug USB di Chrome lebih mudah dilakukan dengan halaman internal about://device-log
di mana Anda dapat melihat semua
peristiwa terkait perangkat USB di satu tempat.
Halaman internal about://usb-internals
juga berguna dan memungkinkan Anda
untuk menyimulasikan koneksi dan pemutusan
perangkat WebUSB virtual.
Ini berguna untuk melakukan pengujian UI tanpa perangkat keras yang sebenarnya.
Pada sebagian besar sistem Linux, perangkat USB
dipetakan dengan izin hanya-baca berdasarkan
secara default. Untuk mengizinkan Chrome membuka perangkat USB, Anda perlu menambahkan udev baru
aturan. Buat file di /etc/udev/rules.d/50-yourdevicename.rules
dengan
konten berikut:
SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"
dengan [yourdevicevendor]
adalah 2341
jika perangkat Anda adalah Arduino, misalnya.
ATTR{idProduct}
juga dapat ditambahkan untuk aturan yang lebih spesifik. Pastikan atribut
user
adalah anggota grup plugdev
. Kemudian, cukup hubungkan kembali perangkat.
Resource
- Stack Overflow: https://stackoverflow.com/questions/tagged/webusb
- Spesifikasi WebUSB API: http://wicg.github.io/webusb/
- Status Fitur Chrome: https://www.chromestatus.com/feature/5651917954875392
- Masalah Spesifikasi: https://github.com/WICG/webusb/issues
- Bug Penerapan: http://crbug.com?q=component:Blink>USB
- WebUSB ❤ ️Arduino: https://github.com/webusb/arduino
- IRC: #webusb di IRC W3C
- Milis WICG: https://lists.w3.org/Archives/Public/public-wicg/
- Project WebLight: https://github.com/sowbug/weblight
Kirim tweet ke @ChromiumDev menggunakan hashtag
#WebUSB
dan beri tahu kami tempat serta
cara Anda menggunakannya.
Ucapan terima kasih
Terima kasih kepada Joe Medley telah meninjau artikel ini.