WebUSB API: інтеграція USB-пристроїв без драйверів

Ви інтегрували дорогий принтер етикеток на склад, але він працює тільки через нативний додаток під Windows. Кожне оновлення — завантаження інсталятора, кожен новий співробітник — встановлення драйверів. Це уповільнює процес розгортання та збільшує cost of ownership. Ми вирішуємо цю проблему: підключ

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
WebUSB API: інтеграція USB-пристроїв без драйверів
Складний
~2-3 дні

Наші компетенції:

Часті запитання

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1467
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1317
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1014
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1276
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1019
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1019

Ви інтегрували дорогий принтер етикеток на склад, але він працює тільки через нативний додаток під Windows. Кожне оновлення — завантаження інсталятора, кожен новий співробітник — встановлення драйверів. Це уповільнює процес розгортання та збільшує cost of ownership. Ми вирішуємо цю проблему: підключаємо Zebra, Arduino, POS-термінали та будь-які USB-пристрої безпосередньо в браузер через WebUSB API. Без драйверів, без додаткового ПЗ. Просто відкрили Chrome — і пристрій готовий до роботи.

Кейс із практики: для одного логістичного центру ми замінили нативний Windows-додаток на веб-інтерфейс з WebUSB. Десять принтерів Zebra тепер керуються з будь-якого пристрою в локальній мережі через браузер. Встановлення нового робочого місця скоротилося з 40 хвилин до 2 хвилин. Витрати на супровід впали на 70%. Подібний результат ми гарантуємо і для вашого обладнання.

Наш досвід: 6+ років інтеграції промислового обладнання, 30+ успішних проектів з WebUSB. Ми гарантуємо сумісність з Chrome 61+. Для початку отримайте консультацію по вашому пристрою — ми оцінимо можливість підключення за 1 день. Зв'яжіться з нами, щоб обговорити деталі.

Які пристрої підходять для WebUSB

WebUSB підходить для пристроїв, які не мають системного драйвера або мають спеціальну прошивку. Приклади: принтери етикеток (Zebra, TSC), Arduino з бібліотекою WebUSB, POS-термінали, сканери штрих-кодів, світлодіодні панелі, вимірювальні прилади. Важливе обмеження: пристрої HID (клавіатури, миші) та mass-storage (флешки) недоступні, оскільки їх драйвери вже зайняті ОС.

Чому WebUSB вигідніше нативних рішень?

Критерій WebUSB Нативний додаток
Встановлення Не потрібно Потрібен інсталятор + драйвери
Оновлення Автоматичне (браузер) Ручне або через менеджер оновлень
Кроссплатформенність Chrome/Edge на Windows/Mac/Android Під кожну ОС окрема збірка
Безпека Пісочниця браузера, user gesture Повний доступ до системи
Розробка Один код на TypeScript C++/C#/Java, різні SDK

WebUSB дає виграш у швидкості розгортання в 3 рази, а вартість розробки нижча в 2-3 рази. Економія на підтримці — до 70%. На відміну від нативних рішень, WebUSB не вимагає встановлення — достатньо відкрити браузер. Це особливо важливо для компаній з частою ротацією персоналу.

Які обмеження у WebUSB?

Підтримка: Chrome/Edge 61+ (десктоп і Android). Safari та Firefox — не підтримують. Тільки HTTPS. Тільки user gesture. USB-пристрої з активними ядерними USB-драйверами ОС (HID, мас-стораж, принтери з системними драйверами) — недоступні через WebUSB: браузер не перехоплює їх у ОС. Потрібен спеціальний firmware з WebUSB дескрипторами, або пристрій без автоматично встановлюваного драйвера.

Як працює підключення: від запиту до claim?

Технічна реалізація

interface USBDeviceInfo { vendorId: number // з документації виробника productId: number } async function requestUSBDevice(filters: USBDeviceInfo[]): Promise<USBDevice> { const device = await navigator.usb.requestDevice({ filters }) return device } async function connectDevice(device: USBDevice): Promise<void> { await device.open() // Якщо пристрій має кілька конфігурацій — вибираємо потрібну if (device.configuration === null) { await device.selectConfiguration(1) } // Захоплюємо інтерфейс (потрібний номер — з документації або USB descriptor) await device.claimInterface(0) console.log(`Підключено: ${device.manufacturerName} ${device.productName}`) console.log(`USB ${device.usbVersionMajor}.${device.usbVersionMinor}`) } 

Приклад: принтер етикеток ZPL (Zebra)

Принтери Zebra використовують ZPL. Команди надсилаються як plain text через bulk transfer:

class ZebraPrinter { private device: USBDevice private interfaceNumber = 0 private endpointOut = 1 constructor(device: USBDevice) { this.device = device } async print(zplCommands: string): Promise<void> { const encoder = new TextEncoder() const data = encoder.encode(zplCommands) const result = await this.device.transferOut(this.endpointOut, data) if (result.status !== 'ok') { throw new Error(`Print error: ${result.status}`) } } async printLabel(params: { barcode: string; title: string; price: string; sku: string }): Promise<void> { const zpl = ` ^XA ^CI28 ^FO20,10^A0N,24,24^FD${params.title}^FS ^FO20,40^BY2^BCN,50,Y,N,N^FD${params.barcode}^FS ^FO20,100^A0N,20,20^FDSKU: ${params.sku}^FS ^FO20,125^A0N,28,28^FD${params.price}^FS ^XZ`.trim() await this.print(zpl) } async getStatus(): Promise<string> { await this.print('~HS') const result = await this.device.transferIn(1, 64) const decoder = new TextDecoder() return decoder.decode(result.data!) } } 

Приклад: Arduino (двосторонній обмін)

Arduino з кастомною прошивкою через WebUSB бібліотеку:

class ArduinoDevice { private device: USBDevice private interfaceNumber = 2 private endpointIn = 5 private endpointOut = 4 private decoder = new TextDecoder() private encoder = new TextEncoder() private readBuffer = '' private isReading = false constructor(device: USBDevice) { this.device = device } async startReading(onData: (line: string) => void) { this.isReading = true while (this.isReading) { try { const result = await this.device.transferIn(this.endpointIn, 64) const chunk = this.decoder.decode(result.data!, { stream: true }) this.readBuffer += chunk const lines = this.readBuffer.split('\n') this.readBuffer = lines.pop()! for (const line of lines) { if (line.trim()) onData(line.trim()) } } catch (err) { if ((err as Error).name === 'NetworkError') break throw err } } } async sendCommand(command: string): Promise<void> { const data = this.encoder.encode(command + '\n') await this.device.transferOut(this.endpointOut, data) } stopReading() { this.isReading = false } } // Використання const arduino = new ArduinoDevice(device) arduino.startReading((line) => { const match = line.match(/TEMP:([\d.]+),HUM:([\d.]+)/) if (match) { setSensorData({ temp: parseFloat(match[1]), humidity: parseFloat(match[2]) }) } }) await arduino.sendCommand('LED:ON') await arduino.sendCommand('SERVO:90') 

React-хук для WebUSB

function useWebUSB() { const [device, setDevice] = useState<USBDevice | null>(null) const [isConnected, setIsConnected] = useState(false) const [isSupported] = useState(() => 'usb' in navigator) useEffect(() => { if (!isSupported) return function onConnect(event: USBConnectionEvent) { console.log('USB підключено:', event.device.productName) } function onDisconnect(event: USBConnectionEvent) { if (event.device === device) { setDevice(null) setIsConnected(false) } } navigator.usb.addEventListener('connect', onConnect) navigator.usb.addEventListener('disconnect', onDisconnect) return () => { navigator.usb.removeEventListener('connect', onConnect) navigator.usb.removeEventListener('disconnect', onDisconnect) } }, [device, isSupported]) async function reconnectPaired() { const devices = await navigator.usb.getDevices() if (devices.length > 0) { const dev = devices[0] await connectDevice(dev) setDevice(dev) setIsConnected(true) } } return { device, isConnected, isSupported, reconnectPaired } } 

Діагностика та реверс-інжиніринг

Як читати USB-дескриптор без документації

function inspectDevice(device: USBDevice) { console.log('Vendor ID:', device.vendorId.toString(16)) console.log('Product ID:', device.productId.toString(16)) device.configuration?.interfaces.forEach((iface) => { console.log(`\nInterface ${iface.interfaceNumber}:`) iface.alternates.forEach((alt) => { alt.endpoints.forEach((ep) => { console.log(` Endpoint ${ep.endpointNumber}: ${ep.direction} ${ep.type}, packet size: ${ep.packetSize}`) }) }) }) } 

Це дозволяє знайти потрібні endpoint-номери без документації.

Детальніше про реверс-інжиніринг протоколу

Якщо документація на пристрій відсутня, ми використовуємо сніфер USB-трафіку (наприклад, Wireshark з usbmon) для захоплення команд. Після аналізу ми відновлюємо протокол і реалізуємо його на TypeScript. Цей метод вимагає доступу до еталонного пристрою та додатку.

Типові проблеми та їх вирішення

Проблема Причина Рішення
Пристрій не знайдено requestDevice() Невірні фільтри або активний системний драйвер Перевірити vendorId/productId, замінити драйвер на WinUSB через Zadig
SecurityError при виклику API Не HTTPS або не user gesture Відкрити сторінку за HTTPS, викликати API після кліку
NotFoundError після requestDevice Пристрій вже зайнятий іншим додатком Закрити інші програми, що використовують USB
NetworkError при transferIn Відключення пристрою або таймаут Перепідключити пристрій, реалізувати повторну спробу

Чек-лист діагностики:

  1. Перевірте 'usb' in navigator — має бути true.
  2. Переконайтеся, що сторінка відкрита за HTTPS (або localhost).
  3. Запустіть navigator.usb.requestDevice() тільки після кліку користувача.
  4. Якщо пристрій не з'являється — відкрийте DevTools, подивіться на консоль на помилки.
  5. На Windows спробуйте замінити драйвер пристрою на WinUSB через Zadig.

Що входить в інтеграцію

  • Аналітика: підбір фільтрів, вивчення протоколу, визначення endpoint'ів.
  • Розробка прототипу: підключення, надсилання команд, прийом даних, обробка помилок.
  • Тестування: на цільових ОС (Windows, macOS, Android), перевірка відключення та повторного підключення.
  • Документація: опис схеми взаємодії, приклади коду.
  • Навчання: інструкція для користувачів, рекомендації з налаштування драйверів (WinUSB).

Замовте інтеграцію WebUSB під ключ — ми підготуємо прототип за 5 днів. Отримайте консультацію по вашому пристрою прямо зараз.