Изучение WebUSB API: подключение к USB-устройствам и печать с помощью TSPL/TSPL2

Изучение WebUSB API: подключение к USB-устройствам и печать с помощью TSPL/TSPL2

5 апреля 2023 г.

Что такое WebUSB API?

WebUSB API предоставляет классы и методы, которые позволяют нам подключать устройства и отправлять или получать данные через USB в веб-браузерах.

Краткий обзор того, как использовать WebUSB

Мы используем метод USB.requestDevice(), чтобы отобразить диалоговое окно сопряжения для пользователя. После того, как пользователь выбирает USB-устройство в диалоговом окне, он возвращает выбранное устройство как экземпляр USBDevice.

Позже мы можем отправлять или получать данные с этого устройства. Чтобы получить список уже сопряженных устройств, мы можем использовать метод USB.getDevices().

Браузеры, поддерживаемые WebUSB

Не все браузеры могут поддерживать WebUSB API. На данный момент поддерживаются следующие браузеры: Google Chrome, Microsoft Edge, Opera, Samsung Internet и Baidu Browser. Вы можете проверить, какие браузеры поддерживают WebUSB.

Один из способов проверить, поддерживает ли браузер WebUSB с JavaScript:

if (!('usb' in navigator)) {
    console.log('WebUSB API is not supported!');
}

WebUSB API доступен только в защищенных контекстах (HTTPS)

WebUSB API можно использовать только в защищенных контекстах, другими словами, он должен предоставляться по URL-адресам https:// или wss://.

Однако вы все равно можете протестировать его на localhost, поскольку, согласно веб-документам MDN, локальные ресурсы считаются доставленными безопасно:

<цитата>

Локально доставляемые ресурсы, такие как ресурсы с URL-адресами http://127.0.0.1, http://localhost и http://*.localhost (например, http://dev.whatever.localhost/) и URL-адреса file:// также считаются доставленными безопасно.

Включить или отключить WebUSB API

Если вы хотите отключить WebUSB API, вы можете добавить HTTP-заголовок Permissions-Policy: usb=() и использовать атрибут allow для iframe. Вот пример для Node.js:

res.setHeader('Permissions-Policy', 'usb=()');

Если вы попытаетесь использовать WebUSB API после его отключения, вы получите сообщение об ошибке: Нарушение политики разрешений: USB не разрешен в этом документе. Подробнее см. Веб-документы MDN — Политика разрешений.

WebUSB API с примером

Давайте рассмотрим, как мы можем использовать WebUSB API, на пошаговых примерах.

Сопряжение и подключение к USB-устройству с помощью WebUSB

Мы можем использовать метод USB.requestDevice() для сопряжения и получения доступа к USB-устройству. Этот метод открывает диалоговое окно в браузере, где мы можем выбрать USB-устройство, к которому мы хотим подключиться. В случае успеха возвращается экземпляр USBDevice.

Если устройство не выбрано, выдается исключение: Не удалось выполнить «requestDevice» на «USB»: устройство не выбрано.

Этот метод можно вызвать только с помощью жестов пользователя, таких как клики. В противном случае выдается исключение: Не удалось выполнить requestDevice на USB-накопителе: должен обрабатываться жест пользователя для отображения запроса на разрешение.

Чтобы сбросить разрешение на USB-устройство, мы можем использовать device.forget().

Давайте напишем код. Добавьте простую кнопку, которая вызывает метод USB.requestDevice() при нажатии:

<button onclick="requestDevice()">Request device</button>

async function requestDevice() {
  try {
    const device = await navigator.usb.requestDevice({ filters: [] });
    console.log(device);
  } catch (e) {
    console.error(e);
  }
}

Параметр filters используется для указания списка объектов для возможных устройств, которые мы хотели бы связать. Если оставить пустым, возвращаются все USB-устройства. Объекты фильтра могут иметь такие свойства, как vendorId, productId, classCode, subclassCode, protocolCode. и серийный номер.

Например, если мы хотим получить только список устройств Apple, код должен выглядеть так:

navigator.usb.requestDevice({ filters: [{ vendorId: 0x05ac }] });

Вот список идентификаторов USB.

Получение списка уже сопряженных устройств

После сопряжения и получения разрешения мы можем получить все сопряженные устройства с помощью метода USB.getDevices(). Нам нужно использовать метод USB.requestDevice() только один раз, чтобы получить разрешение, после чего мы можем получить массив сопряженных устройств с помощью USB.getDevices().. р>

async function getDevices() {
  const devices = await navigator.usb.getDevices();
  devices.forEach((device) => {
    console.log(`Name: ${device.productName}, Serial: ${device.serialNumber}`);
  });
  return devices;
}

Отправка данных на USB-устройство с помощью WebUSB API

Теперь, когда у нас есть разрешение на использование USB-устройства и мы можем получить список сопряженных устройств, давайте посмотрим, как мы можем отправить на него данные.

Вот простой код, который отправляет данные на подключенное устройство:

async function transferOutTest(device) {
  await device.open();
  await device.selectConfiguration(1);
  await device.claimInterface(0);
  await device.transferOut(
    2,
    new Uint8Array(
      new TextEncoder().encode('Test valuen')
    ),
  );
  await device.close();
}

* open() запускает сеанс устройства.

* selectConfiguration() выбирает конфигурацию для конкретного устройства.

* claimInterface() запрашивает монопольный доступ к специфичному для устройства интерфейсу.

* transferOut() отправляет данные на USB-устройство.

* close() освобождает интерфейсы и завершает сеанс устройства.

Пример печати этикеток с помощью WebUSB API

Я создал простой пример печати этикеток с помощью TSPL и WebUSB API. Вы можете получить его с GitHub, но вот более короткая версия:

<button onclick="requestDevice()">Request device</button><br><br>
<button id="device"></button>

<script>
async function requestDevice() {
  try {
    const device = await navigator.usb.requestDevice({ filters: [] });
    const elem = document.querySelector('#device');
    elem.textContent = `Print with '${device.productName}'`;
    elem.onclick = () => testPrint(device);
  } catch (e) {
    console.error(e);
  }
}

async function testPrint(device) {
  const cmds = [
    'SIZE 48 mm,25 mm',
    'CLS',
    'TEXT 30,10,"4",0,1,1,"HackerNoon"',
    'TEXT 30,50,"2",0,1,1,"WebUSB API"',
    'BARCODE 30,80,"128",70,1,0,2,2,"altospos.com"',
    'PRINT 1',
    'END',
  ];

  await device.open();
  await device.selectConfiguration(1);
  await device.claimInterface(0);
  await device.transferOut(
    device.configuration.interfaces[0].alternate.endpoints.find(obj => obj.direction === 'out').endpointNumber,
    new Uint8Array(
      new TextEncoder().encode(cmds.join('rn'))
    ),
  );
  await device.close();
}
</script>

И результат выглядит так:

Label printed using WebUSB API

Если вам интересно узнать больше о TSPL/TSPL2, я написал несколько статей, которые могут быть вам полезны. Они охватывают такие темы, как печать этикеток и изображений, а также печать квитанций с использованием TSPL и JavaScript.

Я написал эти статьи после добавления поддержки печати в Alto POS & Inventory, надеясь, что они будут полезны кому-то в похожей ситуации.

* Как печатать этикетки с помощью TSPL и JavaScript * Как печатать ИЗОБРАЖЕНИЯ с помощью TSPL и JavaScript * Как печатать квитанции с помощью TSPL и JavaScript

Несколько полезных инструментов:

  • chrome://device-log/ — используйте это, чтобы получить сведения об устройстве и создать тестовое устройство.
  • chrome://device-log/ — показывает журналы, связанные с устройствами.
  • Zadig — общие драйверы USB для Windows — вам может потребоваться установить драйвер в Windows.

Не было войны! ✋🏽


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE