При переходе на современные 64-разрядные платформы «1С:Предприятие 8.3» разработчики часто сталкиваются с аппаратной проблемой: старые, годами проверенные библиотеки для работы с последовательными (COM) портами отказываются запускаться. Инструменты вроде MSComm.ocx, vk_rs_232.dll или старые ActiveX-компоненты просто не могут быть загружены в 64-битный процесс платформы. Разберем по шагам, почему возникает эта проблема, как ее обойти с помощью штатных средств 1С, и проанализируем альтернативные способы интеграции торгового и промышленного оборудования.
Основная причина кроется в архитектурных ограничениях операционных систем и технологии COM/ActiveX. Давайте выясним ключевые моменты:
regsvr32. В современных ОС для этого требуются права администратора, что сильно усложняет развертывание и обновление системы на рабочих местах обычных пользователей.Решением этих проблем стала разработка новой технологии создания внешних компонент — Native API. Компоненты, написанные по этой технологии, загружаются напрямую платформой 1С, поставляются в виде общих макетов прямо внутри конфигурации и автоматически поддерживают нужную разрядность клиента (как 32, так и 64 бит).
Как показывает практика, для получения текстовых данных из COM-порта не обязательно писать собственную компоненту или искать сомнительные платные решения. Мы можем воспользоваться штатным драйвером «1С:Сканер штрихкода» (AddIn.Scanner), который поставляется в составе «1С:Библиотеки подключаемого оборудования» (БПО) и присутствует практически во всех типовых конфигурациях (например, «1С:Розница», «1С:Управление торговлей» или «1С:ERP»).
Этот драйвер по сути представляет собой универсальный слушатель последовательного порта. При поступлении в порт текстовых данных, завершающихся определенным символом (суффиксом), драйвер генерирует в 1С асинхронное внешнее событие, которое мы можем перехватить и обработать.
Рассмотрим, где взять нужную компоненту. Нам необходимо открыть конфигурацию-донор (например, «1С:Розница») и найти в ветке Общие -> Общие макеты макет с именем Драйвер1ССканерШтрихкода (или аналогичный макет компоненты сканера штрихкодов в БПО). Выгрузим этот макет на диск в виде двоичных данных.
Затем в нашей целевой конфигурации создадим новый общий макет с типом Двоичные данные, назовем его, например, КомпонентаРаботыCOM и загрузим туда ранее сохраненный файл.
Для того чтобы система начала прослушивать порт при старте программы, нам нужно инициализировать компоненту и настроить ее параметры. Рекомендуется выполнять этот код при начале работы системы в модуле управляемого приложения или в модуле обычного приложения (в зависимости от типа используемого клиента).
Разберем пример кода инициализации:
Процедура ПриНачалеРаботыСистемы()
// Подключаем внешнюю компоненту из общего макета нашей конфигурации
РезультатПодключения = ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаРаботыCOM", "Scanner", ТипВнешнейКомпоненты.Native);
Если Не РезультатПодключения Тогда
ЗаписатьЛогСобытий("Не удалось подключить внешнюю компоненту работы с COM-портом!");
Возврат;
КонецЕсли;
// Создаем объект драйвера
Попытка
ОбъектДрайвера = Новый ("AddIn.Scanner.Scanner");
Исключение
ЗаписатьЛогСобытий("Не удалось создать объект драйвера сканера!");
Возврат;
КонецПопытки;
// Настраиваем параметры подключения к COM-порту
// Подсоединяем логическое устройство
Результат = (ОбъектДрайвера.Подсоединить("СканерШтрихкода") = 0);
// Задаем имя события, которое будет генерироваться при получении данных
ОбъектДрайвера.ИмяСобытия = "ПолученыДанныеПорта";
// Задаем кодировку, в которой устройство присылает строку
ОбъектДрайвера.COMКодировка = "UTF-8";
// Настройки порта (должны строго соответствовать настройкам самого устройства)
ОбъектДрайвера.Порт = 1; // Номер COM-порта (например, 1 для COM1)
ОбъектДрайвера.Скорость = 9600; // Скорость передачи данных в бодах
ОбъектДрайвера.БитДанных = 8; // Количество бит данных в байте
// Критически важная настройка: символ окончания посылки данных.
// Обычно устройства в конце строки присылают символ перевода строки (Line Feed - LF, или Carriage Return - CR)
ОбъектДрайвера.СуффиксСтрока = Символы.ПС;
// Монопольно занимаем порт в операционной системе
РезультатЗанятия = (ОбъектДрайвера.Занять(1) = 0);
Если РезультатЗанятия Тогда
// Включаем устройство и разрешаем отправку внешних событий в 1С
ОбъектДрайвера.УстройствоВключено = 1;
ОбъектДрайвера.ПосылкаДанных = 1;
// Очищаем буферы порта перед началом работы
ОбъектДрайвера.ОчиститьВход();
ОбъектДрайвера.ОчиститьВыход();
Иначе
ЗаписатьЛогСобытий("Не удалось занять COM-порт. Возможно, он занят другой программой.");
КонецЕсли;
КонецПроцедуры
Важное примечание по параметру СуффиксСтрока: Внешняя компонента накапливает приходящие в порт байты в своем внутреннем буфере. Событие в 1С будет сгенерировано только тогда, когда в потоке данных обнаружится символ-суффикс (в нашем примере это перевод строки Символы.ПС). Если ваше устройство не присылает в конце строки символ перевода строки, вам необходимо выяснить, какой именно байт является признаком конца посылки, и настроить свойство СуффиксСтрока соответствующим образом (например, символом возврата каретки Символы.ВК).
После успешной инициализации компонента работает в фоновом режиме. Как только устройство отправит данные в порт, платформа 1С автоматически вызовет процедуру-обработчик внешнего события. Ее необходимо разместить в модуле управляемого приложения или в модуле формы, если подключение выполнялось локально для конкретной формы.
Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
// Проверяем, что событие пришло именно от нашего прослушивателя порта
Если Источник = "СканерШтрихкода" И Событие = "ПолученыДанныеПорта" Тогда
// В переменной "Данные" содержится строка, принятая из COM-порта
ОчищенныеДанные = СокрЛП(Данные);
// Вызываем логику обработки полученной строки
ОбработатьПринятыеДанные(ОчищенныеДанные);
КонецЕсли;
КонецПроцедуры
Процедура ОбработатьПринятыеДанные(Знач ТекстДанных)
// Здесь размещается ваша прикладная бизнес-логика.
// Например, парсинг веса с весов, вывод сообщения пользователю или запись в документ.
ПоказатьОповещениеПользователя("Получены данные из порта:", , ТекстДанных);
КонецПроцедуры
Бывают ситуации, когда использование Native API внешних компонент нежелательно из соображений корпоративной безопасности или технических ограничений инфраструктуры заказчика. В этом случае мы можем прибегнуть к архитектурным альтернативам. В качестве альтернативного варианта подойдёт утилита для эмуляции клавиатурного ввода данными из COM-порта.
Существует класс программного обеспечения, преобразующий физический COM-порт в виртуальный сетевой TCP-порт (например, утилиты *HW VSP*, *com2tcp* или *Tibbo Virtual Serial Port*). Программа-мост постоянно слушает COM-порт локального компьютера и перенаправляет все приходящие байты на определенный сетевой порт (например, localhost:4001).
В этом сценарии в 1С нам вообще не требуются низкоуровневые драйверы. Мы можем использовать штатный объект платформы 1С TCPСоединение (или HTTP-запросы) для подключения к локальному сокету и чтения данных из него в стандартном коде 1С.
Если требуется высокая надежность и гибкая предварительная обработка данных, отличным решением станет написание небольшого скрипта на языке Python, который запускается в качестве службы ОС.
Скрипт использует библиотеку pyserial для чтения порта и отправляет данные в 1С через механизм публикации HTTP-сервисов. Проанализируем схему работы:
COM1./hs/DeviceData/).Такой подход полностью развязывает интерфейс пользователя и работу с оборудованием, гарантируя, что зависание порта или сбой устройства никак не повлияют на стабильность работы сеанса 1С. Для организации чтения данных через внешнюю утилиту-посредник можно использовать программу чтения данных с COM-порта с записью в файл.
Если ваши рабочие места или серверы 1С переводятся на операционные системы семейства Linux (например, Astra Linux или RedOS), учтите следующие особенности работы с портами:
COM1, COM2. Физические порты и USB-переходники отображаются как файлы устройств в каталоге /dev/. Обычно это /dev/ttyS0, /dev/ttyS1 (для аппаратных портов материнской платы) или /dev/ttyUSB0, /dev/ttyUSB1 (для USB-Serial конвертеров). Соответственно, в настройках внешней компоненты в качестве номера порта необходимо передавать путь к файлу устройства.dialout или uucp). Сделать это можно консольной командой: sudo usermod -aG dialout имя_пользователя_1сТаким образом, использование штатных Native API компонент 1С позволяет элегантно и без дополнительных затрат решить проблему получения данных с COM-порта на современных 64-битных платформах, обеспечивая кроссплатформенность и простоту развертывания решения.