- PVSM.RU - https://www.pvsm.ru -

Работа с периферией из JavaScript: от теории к практике

Работа сотрудника банка опасна и трудна. В Единой фронтальной системе мы стараемся помочь сотруднику банка и автоматизировать его работу. Одна из многочисленных задач, которую нам нужно решить, — доработать тонкий клиент для возможности работы с периферийным банковским оборудованием. Но сделать это не так-то просто. В данной статье мы расскажем, как мы пытались решить задачу, и к чему это привело.

Статья будет полезна архитекторам и опытным front-end разработчикам систем масштаба предприятий, столкнувшихся с проблемой доступа к периферийному оборудованию из тонкого клиента своей системы.

Работа с периферией из JavaScript: от теории к практике - 1 [1]

И да, скажем сразу, задача усложняется тем, что стандартные подходы с применением ActiveX, Java Applet, плагина браузера нас не устраивают по соображениям безопасности, универсальности и сложностей с  управляемостью и сопровождаемостью.

Представьте себе скромный (по китайским меркам) банк, в отделениях которого работают более 100 тыс. операторов. У них есть рабочие места, на которых они обслуживают клиентов, а  к рабочим местам подключены различные периферийные устройства:

  1. Сетевой/локальный принтер.
  2. Чековый принтер (Epson-M950 или Olivetti).
  3. POS-терминал (Verifone VX820).
  4. Устройство для чтения «таблеток» (touch memory с ЭЦП).
  5. Сканеры разных типов (для штрих-кодов, паспортов или просто документов).
  6. Веб-камера (фотографировать потенциальных заемщиков).
  7. Специфическое банковское оборудование – cash dispenser/receiver и т.п.

Внушительный список, не правда ли? И со всем этим нужно взаимодействовать из работающего в браузере react-приложения.

Работа с устройствами на низком уровне осуществляется через драйвера производителей оборудования или native библиотеки внутренней разработки. Установка и обновление драйверов и другого ПО на рабочих местах осуществляются централизованно. На рабочих местах стоят Windows и Internet Explorer 11 или 8. Обсуждается возможность перехода на Linux и Chrome/Firefox. Отсюда возникает требование кросс-платформенности и кросс-браузерности.

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

Требования безопасности заключаются в контроле целостности кода, запускаемого на клиенте, ограничении доступа к периферии (доступ должен быть только с локального рабочего места) и ряда специфичных требований к работе с touch memory.

Отдельный вопрос – работа планшета с периферией. Идея в том, чтобы заменить компьютеры на мобильные девайсы, перенеся на них весь функционал оператора, включая совершение банковских операций. В этой статье мы не будем подробно говорить про планшеты, обязательно расскажем об этом в другой статье, просто обозначим, что здесь возникают как вопросы подключения самого планшета к внутренней банковской сети по wi-fi, так и вопросы работы с устройствами, подключаемыми непосредственно к планшету, например, mPOS-терминалами.

Как мы пытались все это приручить, почему не сразу получилось

Из условий эксплуатации следует схема работы с периферией:

Работа с периферией из JavaScript: от теории к практике - 2 Мы попытались найти решение проблемы и проработали несколько вариантов.

HTML5

Хотя в нем потенциально есть работа с периферийными устройствами, текущие реализации заточены под мобильные устройства или аудио/видео,  и для наших задач не подходят от слова «совсем».

WebUSB

https://wicg.github.io/webusb/ [2] — во-первых, не все устройства подключаются через USB. Во-вторых, поддержки WebUSB на текущий момент нет нигде, кроме экспериментальной feature [3] в Chrome. Так что тоже нам не подходит.

ActiveX

Способ старинный и проверенный – делаются обертки над драйверами, устанавливаемые как локальные OCX или DLL, обращение к которым идет через ActiveXObject:

var printer = new ActiveXObject("LocalPrinterComponent.Printer");
printer.print(data + "rn");

Но он работает только в IE и Windows. Несмотря на попытки сделать технологию ActiveX переносимой,  Microsoft отказалась [4] от развития ActiveX в пользу технологии плагинов.

Плагины браузера

Это тоже нам не подходит, не является целевым, привязывает к браузеру и ограничивает универсальность.

Нативные компоненты на Java

На localhost выставляется cервис, который доступен из JavaScript. От этого тоже решили отказаться, т.к. реализация более трудоемкая, требуется использовать веб-сервер либо писать свой.

Applet

Не целевой, возникают проблемы с правами доступа на локальном устройстве.

И что же делать?

В итоге мы остановились на следующей архитектуре работы с периферийными устройствами:

Работа с периферией из JavaScript: от теории к практике - 3

Клиентское приложение в JavaScript обращается к локальному сервису через модуль работы с периферийным API, который является обвязкой над клиентской частью socket.io [5].

На рабочие места устанавливается node.js [6], который запускается под сервисной учетной записью при старте операционки. В node.js работает наш модуль bootstrap, отвечающий за загрузку npm-модулей для работы с периферийными устройствами с сервера в локальную файловую систему. Клиентский код генерирует event, в качестве атрибутов передается код и версия модуля, который работает с устройством, вызываемый метод и его параметры:

Работа с периферией из JavaScript: от теории к практике - 4

Также bootstrap отвечает за работу с платформенными сервисами (выгрузку логов с рабочего места по запросу администратора и т.п.)

Для каждого периферийного устройства  имеется свой модуль работы с ним, исполняемый в node.js. Bootstrap проксирует вызов в метод модуля:

Работа с периферией из JavaScript: от теории к практике - 5

Работа с периферией из JavaScript: от теории к практике - 6

Модуль работает с низкоуровневым API операционной системы или драйвера через npm модуль node.js «ffi»:

Работа с периферией из JavaScript: от теории к практике - 7

Когда клиентское приложение обращается к bootstrap, передавая модуль и версию, bootstrap проверяет локальное хранилище. Если нужного модуля нет в локальном хранилище, он выкачивается его с сервера. Таким образом, централизованно устанавливаются только драйвера и node.js с bootstrap’ом, а npm-модули для работы с устройствами скачиваются в рантайме. Но данная функция вряд ли будет использоваться в промышленной конфигурации, так что предполагаем, что при удаленной инсталляции драйверов устройств на рабочие места сотрудников будет устанавливаться и соответствующий npm модуль периферийного API, представляющий собой JS bundle.

Решение пока еще не реализовано, мы работаем над этим и обязательно расскажем о результатах в другой статье. А пока хотим спросить у вас, что вы думаете о выбранном подходе? Какие подводные камни нас ждут? Приглашаем всех принять участие в дискуссии в комментариях.

Автор: EFS_programm

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/257965

Ссылки в тексте:

[1] Image: https://habrahabr.ru/company/efs/blog/330374/

[2] https://wicg.github.io/webusb/: https://wicg.github.io/webusb/

[3] экспериментальной feature: https://www.chromestatus.com/feature/5651917954875392

[4] отказалась: http://www.computerworld.com/article/2920892/web-browsers/microsoft-nixes-activex-add-on-technology-in-new-edge-browser.html

[5] socket.io: https://socket.io/

[6] node.js: https://nodejs.org/en/

[7] Источник: https://habrahabr.ru/post/330374/