При интеграции различного торгового оборудования — весов, сканеров штрихкодов, терминалов сбора данных или RFID-считывателей — разработчики на платформе 1С 7.7 часто сталкиваются с неприятной ситуацией. В системных утилитах тестирования (например, в HyperTerminal или PuTTY) данные из COM-порта поступают в чистом, красивом и читаемом виде, но при попытке получить их в коде 1С с помощью сторонних библиотек вроде rs232.dll программа возвращает «неведомую кодировку» — хаотичный набор нечитаемых символов.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем физические и программные механизмы искажения данных и рассмотрим проверенные способы решения этой задачи с примерами кода.
Для начала выясним причину такого поведения системы. Если терминал показывает текст корректно, значит, само устройство работает исправно. Искажение информации происходит на этапе передачи данных из буфера операционной системы в среду 1С. Выделим четыре основные причины:
0x00. В 1С 7.7 нулевой байт интерпретируется как маркер конца строки, из-за чего строка обрезается после первого же символа. Если же передается кириллица, то двухбайтовые символы склеиваются в пары и отображаются в виде хаотичных китайских иероглифов или спецсимволов.0x00), любая стандартная текстовая компонента обрежет строку при первой же попытке передать её в 1С.Давайте подробно разберем, как исправить каждую из этих проблем по шагам.
Прежде всего, убедимся, что параметры инициализации порта в коде 1С 7.7 в точности соответствуют настройкам устройства. Стандартный набор параметров выглядит так: 9600,N,8,1 (скорость 9600 bps, без четности, 8 бит данных, 1 стоповый бит). Проверьте документацию к вашему оборудованию. Если параметры не совпадают, измените их при вызове метода инициализации вашей библиотеки.
Если данные приходят искаженными из-за DOS-кодировки оборудования, нам необходимо перекодировать полученную строку внутри 1С. Разберем по шагам, как написать функцию конвертации символов на основе стандартных кодовых таблиц:
Функция ПерекодироватьИзDOS(СтрДанных)
Перем Результат, НомерСимвола, КодСимвола, НовыйКод;
Результат = "";
Для НомерСимвола = 1 По СтрДлина(СтрДанных) Цикл
ТекущийСимвол = Сред(СтрДанных, НомерСимвола, 1);
КодСимвола = КодСимв(ТекущийСимвол);
// Перевод символов основной кириллицы CP866 -> CP1251
Если (КодСимвола >= 128) И (КодСимвола <= 175) Тогда
НовыйКод = КодСимвола + 64;
ИначеЕсли (КодСимвола >= 224) И (КодСимвола <= 239) Тогда
НовыйКод = КодСимвола + 16;
ИначеЕсли КодСимвола = 240 Тогда // Буква Ё
НовыйКод = 168;
ИначеЕсли КодСимвола = 241 Тогда // Буква ё
НовыйКод = 184;
Иначе
// Оставляем латиницу и цифры без изменений
НовыйКод = КодСимвола;
КонецЕсли;
Результат = Результат + Симв(НовыйКод);
КонецЦикла;
Возврат Результат;
КонецФункции
Применим эту функцию к буферу, прочитанному из порта, чтобы вернуть тексту нормальный вид.
Чтобы не гадать, как именно работает неизвестная библиотека rs232.dll, и не тратить время на ее декомпиляцию, крайне рекомендуется использовать проверенное временем стандартное решение от Microsoft — библиотеку MSCOMM32.OCX. Она официально документирована, стабильна и легко настраивается.
Для начала зарегистрируем её в операционной системе. Для этого запустим командную строку от имени администратора и выполним команду:
regsvr32 mscomm32.ocx
После успешной регистрации мы можем напрямую работать с COM-портом из кода 1С 7.7. Рассмотрим пример реализации:
Процедура ПолучитьДанныеИзПорта()
Перем КомПорт, ВходящаяСтрока;
Попытка
// Создаем COM-объект Microsoft Communications Control
КомПорт = СоздатьОбъект("MSCOMMLib.MSComm");
Исключение
Предупреждение("Компонента MSCOMM32.OCX не зарегистрирована в системе!");
Возврат;
КонецПопытки;
// Настраиваем параметры подключения
КомПорт.CommPort = 1; // Указываем номер COM-порта (например, COM1)
КомПорт.Settings = "9600,N,8,1"; // Скорость, четность, бит данных, стоп-бит
КомПорт.InputLen = 0; // Настройка указывает читать весь накопившийся буфер за один раз
Попытка
КомПорт.PortOpen = 1; // Открываем порт
Исключение
Предупреждение("Не удалось открыть COM-порт! Возможно, он занят другим приложением.");
Возврат;
КонецПопытки;
// Делаем небольшую паузу для ожидания ответа от физического устройства
// (актуально для весов и сканеров)
Для х = 1 По 10000 Цикл
// Пустой цикл-задержка или использование встроенного ожидания
КонецЦикла;
Если КомПорт.InBufferCount > 0 Тогда
ВходящаяСтрока = КомПорт.Input;
// Перекодируем, если устройство шлет данные в DOS-кодировке
ЧитаемыйТекст = ПерекодироватьИзDOS(ВходящаяСтрока);
Сообщить("Успешно получено: " + ЧитаемыйТекст);
Иначе
Сообщить("Буфер порта пуст, данные не поступили.");
КоENDЕсли;
// Обязательно закрываем порт после завершения сессии связи
КомПорт.PortOpen = 0;
КонецПроцедуры
Если ваше оборудование передает бинарные пакеты, содержащие нулевые байты 0x00, стандартные текстовые методы работы с COM-портом вам не подойдут — строка будет постоянно обрезаться. В этом случае идеальным выбором станет использование специализированной внешней компоненты Ромикса под названием vk_rs232_hex.dll.
Эта компонента решает проблему кардинально: она считывает данные из порта в бинарном режиме и переводит их в текстовую шестнадцатеричную последовательность (HEX). Например, вместо неопределенного байта 0x00 вы получите обычную текстовую пару "00", а вместо спецсимволов — "FF", "CC" и т.д. Полученную строку можно легко разобрать побайтно средствами самой 1С 7.7.
Рассмотрим по шагам пример работы с hex-версией компоненты:
Процедура ПрочитатьБинарныйПорт()
Перем Компонента, ДанныеВФорматеHex, ТекущийБайт;
// Загружаем внешнюю компоненту
Если ЗагрузитьВнешнююКомпоненту("vk_rs232_hex.dll") = 0 Тогда
Предупреждение("Не найдена библиотека vk_rs232_hex.dll!");
Возврат;
КонецЕсли;
// Создаем объект связи с портом
Компонента = СоздатьОбъект("AddIn.Vk_RS232_Hex");
// Открываем порт COM1 со скоростью 9600
Если Компонента.ОткрытьПорт(1, 9600, 0, 8, 1) = 0 Тогда
Предупреждение("Не удалось открыть COM-порт.");
Возврат;
КонецЕсли;
// Считываем шестнадцатеричную строку из буфера устройства
ДанныеВФорматеHex = Компонента.ЧитатьСтроку();
Если ПустаяСтрока(ДанныеВФорматеHex) = 0 Тогда
Сообщить("Получен HEX-пакет: " + ДанныеВФорматеHex);
// Разбираем пакет побайтно (каждые 2 символа HEX строки — это 1 байт данных)
Для к = 1 По СтрДлина(ДанныеВФорматеHex) / 2 Цикл
ТекущийБайт = Сред(ДанныеВФорматеHex, (к - 1) * 2 + 1, 2);
Сообщить("Байт № " + к + " = " + ТекущийБайт);
// Здесь вы можете проанализировать конкретные байты веса или штрихкода
// Например, если первый байт "02" (STX), а последний "03" (ETX)
КонецЦикла;
КонецЕсли;
// Закрываем соединение
Компонента.ЗакрытьПорт();
КонецПроцедуры
Мы выяснили, что «неведомая кодировка» в 1С 7.7 при работе с последовательным портом — это не случайный сбой, а вполне логичное следствие различий в представлении данных между старыми аппаратными устройствами и операционной системой Windows. Для исправления ситуации достаточно применить правильный инструмент:
MSCOMM32.OCX и функцию перекодировки таблиц ASCII.vk_rs232_hex.dll для получения чистых HEX-последовательностей.