Доступ к WebUSB Chrome через AngularJS

У меня возникла проблема при использовании API-интерфейсов WebUSB для chrome через angularJS. Это проект, в котором мне нужно получить доступ к термопринтеру esc/pos для печати счета.

В обычном JavaScript:

HTML:

<button id="connect">Connect</button>

Javascript:

document.addEventListener('DOMContentLoaded', async () => {
    try{
        let devices = await navigator.usb.getDevices({
            filters: [{
                vendorId: VENDOR_ID,
                productId: PRODUCT_ID
            }]
        });
        let button = document.getElementById('connect');

        button.addEventListener('click', async () => {
            if (devices.length === 0) {

                var device;
                let devices = [];

                try {
                    device = await navigator.usb.requestDevice({
                        filters: [{
                            vendorId: VENDOR_ID,
                            productId: PRODUCT_ID
                        }]
                    });
                }
                catch (error) {
                    console.log(error)
                }
            }
            else {
                device = devices[0];
            }
            console.log('open');
            await device.open();
            console.log('opened:', device);
            await device.selectConfiguration(1); // Select configuration #1 for the device.
            await device.claimInterface(0); // Request exclusive control over interface #0.
            console.log(await device.transferOut(2,buffer));
        })

    }
    catch (error) {
        console.log(error)
    }

в angularjs: HTML:

<button class="btn btn-warning" ng-init="newinvscopetest.bindPrint()" id="print">Print</button>

контроллер:

newinvscopetest.bindPrint = function (){
        let button = document.getElementById('print');

        button.addEventListener('click', async () => {
            let device;
            let devices = [];
            const VENDOR_ID = 0x0FE6;
            const PRODUCT_ID = 0x811E;
            try {
                devices = await navigator.usb.getDevices({
                    filters: [{
                        vendorId: VENDOR_ID,
                        productId: PRODUCT_ID
                    }]
                });
                if (devices.length === 0) {
                    try {
                        device = await navigator.usb.requestDevice({
                            filters: [{
                                vendorId: VENDOR_ID,
                                productId: PRODUCT_ID
                            }]
                        });
                    }
                    catch (error) {
                        console.log(error)
                    }
                }
                else {
                    device = devices[0];
                }
                console.log('open');
                await device.open();
                console.log('opened:', device);
                await device.selectConfiguration(1); // Select configuration #1 for the device.
                await device.claimInterface(0); // Request exclusive control over interface #0.
                let buffer = newinvscopetest.getPrintData();
                console.log(await device.transferOut(2,buffer));
            }
            catch (error) {
                console.log(error)
            }
        });
    };

При попытке использовать угловой скрипт DOMException выдает ошибку:

Должен обрабатывать пользовательский жест, чтобы показать запрос на разрешение.

Это требуется функцией requestDevice веб-usb, которая должна быть нажатием пользовательской кнопки или наведением мыши.

И это хорошо работает в первом примере, потому что пользователь нажимает кнопку, чтобы вызвать функцию.

Во втором примере происходит то же самое. Я даже избегал ng-click, чтобы иметь встроенный прослушиватель событий, чтобы попробовать, если это работает. Но с этим тоже не повезло.

Может кто-нибудь мне помочь? Что не так в angularJS?

1 ответ

Решение

Я не уверен насчет первого примера, но во втором примере перед вызовом requestDevice() вы ждете обещание, возвращенное getDevices(), Это означает, что остальная часть вашей асинхронной функции вызывается после того, как это обещание разрешено, и ваш код больше не имеет пользовательского жеста.

Вместо звонка getDevices() при каждом нажатии я рекомендую вызывать его только один раз при загрузке страницы и использовать прослушиватель событий (добавляется с navigator.usb.addEventListener('connect', ...)) для обнаружения устройства, подключенного после загрузки страницы.

Другие вопросы по тегам