На предприятии эксплуатируется весовой комплекс для взвешивания железнодорожных вагонов. Исторически работа с ним выполнялась через приложение на FoxPro, и прямой интеграции с 1С не было. Документация к комплексу отсутствовала, а попытки восстановить протокол обмена через COM-порт не дали результата.
Решением стала разработка внешней компоненты 1С на C++, которая использует существующий DLL-драйвер весового комплекса и транслирует его функции в методы, доступные из 1С.
В этой статье описан путь: от выявления проблемы и ограничений до архитектуры решения, реализации, подключения драйвера и получения данных в 1С.
Почему интеграция устаревшего оборудования с 1С - актуальная задача
На производственных предприятиях измерительное оборудование (весы, терминалы, контроллеры) часто работает десятилетиями. Его замена дорогостоящая и связана с остановками процессов. При этом учетные системы обновляются чаще: в частности, предприятия стремятся централизовать учет операций в 1С.
Типичный конфликт:
оборудование и драйвер - “старые”, закрытые, без документации;
учетная система - современная, требует интеграции и надежного обмена данными.
Исходные условия: весовой комплекс и FoxPro-приложение
Весовой комплекс для завешивания ЖД вагонов. Работа с комплексом выполнялась через приложение, написанное на FoxPro.
В 1С требовалось получать результаты взвешивания и использовать их в документах/операциях учета.
Проблемы при прямой интеграции с 1С
Отсутствует документация к весовому комплексу и протоколу обмена. Поиск информации в интернете результата не дал (нет описаний команд/протокола/SDK).
Прослушивание COM порта не помогло:
либо обмен шел не в “чистом” виде через COM,
либо использовался нестандартный формат/скорость/инициализация,
либо взаимодействие шло через драйвер, который скрывал реальный обмен.
Производственный процесс критичен: решение должно быть надежным, повторяемым, пригодным для эксплуатации.
Формулировка задачи: подключение оборудования к 1С через рабочий драйвер
Разработать механизм интеграции, который:
позволяет 1С получать данные с весового комплекса;
минимально зависит от неизвестного протокола;
использует существующий рабочий драйвер, с которым уже работает FoxPro приложение
Идея решения: использовать уже работающий драйвер
Поскольку FoxPro приложение успешно работало с комплексом, было принято решение:
взять DLL драйвер, который использовался этим приложением, понять, какие функции драйвера вызываются, реализовать внешнюю компоненту 1С на C++, которая будет:
1) подключать DLL,
2) вызывать нужные функции,
3) отдавать данные в 1С в удобном виде.
Анализ FoxPro-приложения: выявление нужных функций драйвера
Был выполнен анализ исходного кода FoxPro приложения для выявления:
мест, где происходит инициализация весового комплекса;
вызовов DLL;
последовательности действий: открыть/настроить/получить вес/закрыть.
Был составлен перечень функций драйвера (методов), которые обеспечивали работу комплекса:
Connect_VATS (подключение к комплксу);
Read_VATS (чтение данных с комплекса);
Disconnect_VATS (отключение).
Главное: стало понятно какие именно вызовы нужно “поднять” на уровень 1С.
Выбор технологии: внешняя компонента 1С на C++
Варианты интеграции могли быть такими:
прямое чтение COM порта из 1С;
внешняя компонента 1С;
замена оборудования.
Учитывая отсутствие документации и наличие рабочей DLL, оптимальным стал путь внешней компоненты:
- компонента может напрямую работать с WinAPI и DLL;
- можно аккуратно контролировать загрузку/выгрузку и типы данных;
- 1С получает простой API: «подключись» → «дай вес» → «отключись»
Основа проекта
За основу был взят шаблон внешней компоненты, скачанный с сайта ИТС (типовой каркас проекта).
Это снижает риски, потому что:
уже реализованы обязательные точки входа и структура;
проще правильно “подружить” C++ и интерфейсы 1С;
ускоряется разработка и отладка.
Архитектура решения: «мост» между 1С и весовым комплексом
Общая схема 1С (конфигурация / обработка) → вызывает методы компоненты
Внешняя компонента (C++) → динамически подключает DLL драйвера → вызывает функции драйвера
DLL драйвера → общается с весовым комплексом
Весовой комплекс → возвращает измерения/статусы
Принцип “трансляции” методов
Компонента выступает как “адаптер”: в драйвере - функции с низкоуровневыми параметрами (указатели, буферы, коды ошибок);
в 1С - понятные методы и результаты (число, строка, структура, признак ошибки).
Подключение драйвера: почему DLL сохраняется во временный каталог
Требование к развертыванию
Чтобы упростить эксплуатацию и избежать ручной настройки на рабочих местах, выбран подход:
Подключение DLL и динамическая загрузка в C++ДвоичныеДанные = ПолучитьОбщийМакет("ДрайверЖДВесов"); АдресДвоичныхДанных = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор); ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресДвоичныхДанных); ДвоичныеДанные.Записать(ПутьКДрайверу);
Путь к DLL передается в компоненту.
Компонента загружает DLL и начинает работатьОчиститьСообщения();
Весы = Новый("AddIn.Weigher.WeightData");
ПараметрыПодключения = НастройкиПодключенияOnComm(Склад);
Если ПараметрыПодключения = Неопределено Тогда
ТекстСообщения = НСтр("ru = 'Для данного склада не найдено настроек подключения для весов'");
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
Возврат;
КонецЕсли;
Весы.НомерПорта = ПараметрыПодключения.CommPort;
Весы.ИмяФайла = ПутьКДрайверу;
Весы.ПолучитьДанныеВеса();
Если Весы.Статус = -1 Тогда
ТекстОшибки = НСтр("ru = 'Ошибка подключения драйвера весов'");
ИначеЕсли Весы.Статус = -2 Тогда
ТекстОшибки = НСтр("ru = 'Ошибка работы драйвера весов'");
ИначеЕсли Весы.Статус = -3 Тогда
ТекстОшибки = НСтр("ru = 'Ошибка подключения к весам'");
ИначеЕсли Весы.Статус = 1 Тогда
ТекстОшибки = НСтр("ru = 'Груз на весах вне диапазона'");
ИначеЕсли Весы.Статус = 2 Тогда
ТекстОшибки = НСтр("ru = 'Вес не стабилен'");
ИначеЕсли Весы.Статус = 8 Тогда
ТекстОшибки = НСтр("ru = 'Таймаут по связи'");
КонецЕсли;
Если ЗначениеЗаполнено(ТекстОшибки)Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки);
Возврат;
КонецЕсли;
Вес = Весы.ВесБрутто;
Как это реализуется на стороне C++
Технически (в общем виде) применяется динамическая загрузка:
загрузить библиотеку по пути (аналог LoadLibrary);
получить адреса нужных функций (аналог GetProcAddress);
вызывать их, соблюдая соглашение о вызовах и типы параметров;
при завершении корректно выгрузить библиотеку.
bool CAddInNative::CallAsProc(const long lMethodNum,
tVariant* paParams, const long lSizeArray)
{
HMODULE hDLL = LoadLibraryW(FileName);
if (!hDLL) {
Status = -1;
return true;
}
// Получаем адреса функций из DLL
typedef int (WINAPI Connect_VATSPROC)(int);
typedef int (WINAPI Read_VATSPROC)(double&, double&, long&);
typedef void (WINAPI Disconnect_VATSPROC)();
auto pConnect_VATS = (Connect_VATSPROC*)::GetProcAddress(hDLL, "Connect_VATS");
auto pRead_VATS = (Read_VATSPROC*)::GetProcAddress(hDLL, "Read_VATS");
auto pDisconnect_VATS = (Disconnect_VATSPROC*)::GetProcAddress(hDLL, "Disconnect_VATS");
if (!pConnect_VATS !pRead_VATS !pDisconnect_VATS) {
FreeLibrary(hDLL);
Status = -2;
return true;
}
pDisconnect_VATS();
// Соединяемся с устройством
if (pConnect_VATS(PortNumber) == 0) { // Успешное соединение возвращает ненулевое значение
pDisconnect_VATS();
FreeLibrary(hDLL);
Status = -3;
return true;
}
long W_Status = 0l;
// Читаем значения с весов
pRead_VATS(Brutto, Tara, W_Status);
Status = static_cast<int>(W_Status);
pDisconnect_VATS();
FreeLibrary(hDLL);
return true;
}
Реализация API компоненты для 1С и обработка ошибок
Экспортируемые методы (логика)
Компонента предоставляет минимально необходимый набор:
Инициализация/подключение: загрузка DLL, подготовка к работе, настройка порта.
Получение данных: чтение веса, статуса стабильности.
Завершение: закрытие сеанса, освобождение ресурсов, выгрузка DLL.
Ошибки и диагностика
Так как драйвер “чужой” и документации нет, критично:
возвращать в 1С коды ошибок и читаемые сообщения;
логировать ключевые события: загрузка DLL, успех/неуспех получения адресов функций, ответы драйвера.
Практический результат: эксплуатация становится управляемой - при сбое есть что анализировать, а не “просто не работает”.
Результаты внедрения и практическая ценность
В результате создана внешняя компонента на C++, которая:
обеспечивает работу 1С с весовым комплексом без необходимости знать внутренний протокол;
использует проверенный в эксплуатации драйвер;
предоставляет в 1С понятный интерфейс получения данных взвешивания;
упрощает развертывание за счет загрузки DLL по пути (через временный каталог).
Фактически, предприятие получило “мост” между современным учетом в 1С и устаревшим, но рабочим оборудованием.
Данный кейс показывает практический путь интеграции с устаревшим оборудованием при отсутствии документации: вместо попыток восстановить протокол на уровне порта был использован работающий драйвер и проанализирован код существующего FoxPro решения.
На базе шаблона ИТС разработана внешняя компонента 1С на C++, которая динамически подключает DLL драйвера и транслирует его методы в удобные вызовы 1С.
Это позволило обеспечить надежное получение веса в 1С и сохранить работоспособность производственного процесса без замены оборудования.
