При разработке собственных конфигураций или доработке нетленки часто возникает задача подключить торговое оборудование, например, сканер штрихкода. Иногда задачи бывают сложнее, например, требуется реализовать печать на мобильных принтерах по bluetooth и сети или использовать специфические устройства ввода, такие как внешняя компонента SignotecPad для работы с дисплеями подписи. Однако использовать для этого всю Библиотеку подключаемого оборудования (БПО) не всегда целесообразно. Рассмотрим, как подключить сканер напрямую, используя технологию NativeAPI, и разберем типовые проблемы, с которыми можно столкнуться.
Первое, что нам понадобится — это сам драйвер. Для технологии NativeAPI драйвер поставляется в виде zip-архива, который должен быть загружен в конфигурацию как общий макет с типом "Двоичные данные". Внутри этого архива находятся файлы компоненты для разных операционных систем и разрядностей.
Важный момент, выявленный в ходе решения проблемы: макеты драйверов из разных типовых конфигураций могут быть несовместимы или содержать ошибки. Например, макет из конфигурации "Комплексная автоматизация 2.5" может приводить к падению приложения при попытке сканирования в "чистой" базе. Рекомендуем брать макет драйвера (например, Драйвер1СУстройстваВводаNative) из последней версии Библиотеки стандартных подсистем (БСП). Кстати, именно этот драйвер часто используется, когда выполняется подключение сканера Bluetooth SPP на мобильных устройствах под Android — для этого подойдёт беспроводной сканер штрихкодов из смартфона.
Драйвер1СУстройстваВводаNative.ОбщийМакет.Драйвер1СУстройстваВводаNative.В управляемых формах все операции, которые могут занять время, следует выполнять асинхронно, чтобы не блокировать интерфейс пользователя. Подключение внешней компоненты — одна из таких операций. Разместим весь код в модуле формы, где будет происходить работа со сканером.
Для хранения объекта драйвера создадим переменную в модуле формы. Если сканер будет использоваться глобально во всем приложении, можно использовать экспортируемую переменную общего клиентского модуля.
Проанализируем полный код для подключения и инициализации сканера.
&НаКлиенте
Перем мДрайверСканера; // Переменная для хранения объекта драйвера
// Процедура вызывается при открытии формы
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Начинаем асинхронное подключение внешней компоненты
// В качестве параметров передаем:
// 1. ОписаниеОповещения - какую процедуру вызвать после завершения попытки подключения
// 2. Имя макета с драйвером
// 3. Имя компоненты внутри архива (стандартно "InputDevice")
// 4. Тип компоненты - Native
ДопПараметры = Новый Структура("ПредложенаУстановкаКомпоненты", Ложь);
НачатьПодключениеВнешнейКомпоненты(
Новый ОписаниеОповещения("ПодключениеВнешнейКомпонентыЗавершение", ЭтаФорма, ДопПараметры),
"ОбщийМакет.Драйвер1СУстройстваВводаNative",
"InputDevice",
ТипВнешнейКомпоненты.Native);
КонецПроцедуры
// Эта процедура будет вызвана после завершения попытки подключения
&НаКлиенте
Процедура ПодключениеВнешнейКомпонентыЗавершение(Подключено, ДополнительныеПараметры) Экспорт
Если Подключено Тогда
// Если компонента успешно подключена, вызываем функцию инициализации сканера
Результат = ПодключитьСканер();
Если НЕ Результат.Подключено Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = Результат.ТекстОшибки;
Сообщение.Сообщить();
КонецЕсли;
Иначе
// Если подключить не удалось, возможно, компонента не установлена в системе
Если НЕ ДополнительныеПараметры.ПредложенаУстановкаКомпоненты Тогда
// Предлагаем пользователю установить компоненту
ДополнительныеПараметры.ПредложенаУстановкаКомпоненты = Истина;
// Начинаем асинхронную установку компоненты из макета
НачатьУстановкуВнешнейКомпоненты(
Новый ОписаниеОповещения("УстановкаВнешнейКомпонентыЗавершение", ЭтаФорма, ДополнительныеПараметры),
"ОбщийМакет.Драйвер1СУстройстваВводаNative");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Эта процедура будет вызвана после установки компоненты
&НаКлиенте
Процедура УстановкаВнешнейКомпонентыЗавершение(Результат, ДополнительныеПараметры) Экспорт
// После установки снова пытаемся подключить компоненту
НачатьПодключениеВнешнейКомпоненты(
Новый ОписаниеОповещения("ПодключениеВнешнейКомпонентыЗавершение", ЭтаФорма, ДополнительныеПараметры),
"ОбщийМакет.Драйвер1СУстройстваВводаNative",
"InputDevice",
ТипВнешнейКомпоненты.Native);
КонецПроцедуры
// Функция непосредственного подключения и настройки драйвера
&НаКлиенте
Функция ПодключитьСканер()
Результат = Новый Структура("Подключено, ТекстОшибки", Истина, "");
Попытка
// Создаем объект драйвера. ProgID для стандартного драйвера именно такой.
// Ошибка "Тип не определен" здесь означает, что компонента не была подключена на предыдущем шаге.
мДрайверСканера = Новый("AddIn.InputDevice.InputDevice");
Исключение
Результат.Подключено = Ложь;
Результат.ТекстОшибки = "Не удалось создать объект драйвера AddIn.InputDevice.InputDevice. " + ОписаниеОшибки();
Возврат Результат;
КонецПопытки;
// Устанавливаем параметры драйвера. Они зависят от модели сканера и типа подключения.
// Эти параметры нужно подбирать под ваше устройство.
Попытка
мДрайверСканера.УстановитьПараметр("Port", "Клавиатура"); // Для USB-сканеров в режиме эмуляции клавиатуры
мДрайверСканера.УстановитьПараметр("Suffix", 13); // Суффикс CR (Enter)
мДрайверСканера.УстановитьПараметр("DataBits", 8);
// и другие необходимые параметры...
// Включаем устройство, чтобы оно начало перехватывать события клавиатуры
мДрайверСканера.УстройствоВключено = Истина;
Исключение
Результат.Подключено = Ложь;
Результат.ТекстОшибки = "Ошибка установки параметров или включения драйвера: " + ОписаниеОшибки();
Возврат Результат;
КонецПопытки;
Возврат Результат;
КонецФункции
// Важно корректно отключать устройство при закрытии формы
&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
Если мДрайверСканера <> Неопределено Тогда
Попытка
мДрайверСканера.УстройствоВключено = Ложь;
мДрайверСканера = Неопределено;
Исключение
// Ошибку отключения можно проигнорировать или записать в лог
КонецПопытки;
КонецЕсли;
КонецПроцедуры
После того как драйвер успешно подключен и включен, при сканировании штрихкода он будет генерировать внешнее событие. Если у вас нет аппаратного устройства, для тестов можно организовать сканер QR через WEB-камеру с помощью соответствующей компоненты — для этого есть компонента распознавания штрихкодов с картинок. Чтобы обработать входящие данные, в модуле формы необходимо создать процедуру-обработчик ВнешнееСобытие.
&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
// Проверяем, что событие пришло именно от нашего драйвера
// Имя источника совпадает с именем компоненты, указанным при подключении
Если Источник = "InputDevice" И Событие = "BarCode" Тогда
// В параметре "Данные" приходит отсканированный штрихкод
ОбработатьШтрихкод(Данные);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьШтрихкод(Штрихкод)
Сообщить("Получен штрихкод: " + Штрихкод);
// Здесь размещается ваша логика по поиску товара, заполнению документа.
// Если источником служит файл, может потребоваться чтение текста, штрих-кодов, QR из PDF и картинок.
КонецПроцедуры
В процессе подключения можно столкнуться с рядом типовых ошибок. Разберем основные из них.
Эта ошибка возникает при вызове Новый("AddIn.InputDevice.InputDevice") и однозначно говорит о том, что внешняя компонента не была успешно подключена. Убедитесь, что в процедуре-обработчике ПодключениеВнешнейКомпонентыЗавершение параметр Подключено равен Истина, прежде чем создавать объект.
Такое сообщение появляется, если компонента не зарегистрирована в системе. Проверьте, что в цепочке вызовов выполняется НачатьУстановкуВнешнейКомпоненты, если первая попытка подключения была неудачной.
Это самая неприятная ошибка, так как она не перехватывается средствами 1С. Наиболее вероятная причина — некачественный или несовместимый макет драйвера. Как было сказано выше, попробуйте заменить используемый макет на заведомо рабочий из последней версии БСП/БПО. Другая возможная причина — неверные параметры, переданные драйверу.
Это происходит из-за попытки повторной инициализации уже работающего драйвера. Перед тем как выполнять код подключения, всегда проверяйте, не был ли объект драйвера уже создан. А при закрытии формы или логическом "отключении" сканера обязательно освобождайте объект, присваивая переменной значение Неопределено и выключая устройство (мДрайверСканера.УстройствоВключено = Ложь).
Таким образом, прямое подключение сканера — вполне реальная задача. Главное — использовать корректный макет драйвера, соблюдать асинхронный паттерн подключения в управляемых формах и аккуратно обрабатывать все этапы: установку, подключение, получение события и отключение устройства.