Как подключиться к оборудованию по Telnet из 1С с помощью MSWinsock.Winsock?

Программист Промышленность, строительство и АПК
← На главную

При автоматизации складского учета или производственных линий часто возникает задача прямого получения данных с оборудования: автомобильных весов, датчиков или контроллеров. Одним из наиболее распространенных способов взаимодействия с такими устройствами в локальной сети является протокол TCP/IP (часто называемый Telnet-подключением). В среде Windows и 1С для этих целей традиционно используется библиотека MSWinsock.Winsock (ActiveX-компонент mswinsck.ocx). При необходимости интеграции оборудования без ручной работы с низкоуровневыми сокетами можно использовать внешнюю компоненту для подключения весовых терминалов.

Однако при работе с этим объектом разработчики 1С часто сталкиваются с ошибкой: Wrong protocol or connection state for the requested transaction or request. В этой статье мы подробно разберем, почему возникает эта проблема и как правильно организовать асинхронный обмен данными.

Анализируем причину ошибки: почему GetData не работает сразу

Рассмотрим типичный сценарий: программист создает объект, устанавливает адрес и порт, вызывает метод Connect() и сразу же пытается прочитать данные методом GetData(). Именно в этот момент происходит исключение. Проанализируем ситуацию: объект MSWinsock.Winsock является асинхронным. Это означает, что метод Connect() только инициирует процесс установки соединения, но не ждет его завершения. Программа на 1С продолжает выполнение следующей строки кода мгновенно, в то время как сокет еще находится в процессе «рукопожатия» (handshake) с удаленным узлом.

Попытка вызвать GetData() на сокете, который еще не перешел в состояние «Подключено», и вызывает ошибку протокола или состояния соединения.

Решение проблемы через событийную модель и обработчик ожидания

В языках программирования вроде VB6 или Delphi работа с Winsock строится на событиях (например, DataArrival или Connect). Однако в 1С:Предприятии при динамическом создании COM-объекта через конструктор Новый COMОбъект механизм событий не работает напрямую. Чтобы решить эту задачу, нам необходимо имитировать «прослушивание» состояния сокета. Для этого мы будем использовать обработчик ожидания.

Разберем по шагам правильную реализацию подключения (проверить результат внедрения подобных доработок в учете поможет автоматическая сверка бухгалтерских и налоговых проводок между базами 1С):

  1. Создаем объект сокета и инициируем подключение.
  2. Запускаем фоновый процесс (обработчик ожидания), который будет проверять состояние сокета.
  3. Внутри обработчика проверяем свойство State.
  4. Только при достижении нужного статуса вызываем чтение данных.

Пример программного кода для подключения

Ниже приведен доработанный и проверенный алгоритм для подключения к весам:


Перем WinSocket Экспорт; // Переменная должна быть доступна обработчику ожидания

Процедура ПодключитьсяКВесамНажатие(Кнопка)
    Попытка
        WinSocket = Новый COMОбъект("MSWinsock.Winsock");    
    Исключение
        Сообщить("Ошибка создания объекта Winsock. Возможно, компонент не зарегистрирован. " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    // Указываем параметры весов
    WinSocket.Protocol = 0; // sckTCPProtocol
    WinSocket.RemoteHost = "192.168.0.99";
    WinSocket.RemotePort = 1223;
    
    // Инициируем попытку подключения
    WinSocket.Connect(); 
    
    // Запускаем опрос состояния каждую секунду
    ПодключитьОбработчикОжидания("ПроверитьСостояниеИПрочитатьДанные", 1);
КонецПроцедуры

Реализация обработчика получения данных

Теперь создадим процедуру, которая будет вызываться системой автоматически. Нам важно отслеживать свойство State. Рассмотрим основные значения этого свойства:


Процедура ПроверитьСостояниеИПрочитатьДанные() Экспорт
    
    СостояниеСокета = WinSocket.State;
    
    Если СостояниеСокета = 7 Тогда 
        // Соединение установлено. Проверяем, пришло ли что-то в буфер.
        Если WinSocket.BytesReceived > 0 Тогда
            ТекстСообщения = "";
            // Читаем данные как строку (тип 8 - vbString)
            WinSocket.GetData(ТекстСообщения, 8); 
            
            Если ЗначениеЗаполнено(ТекстСообщения) Тогда
                Сообщить("Данные с весов получены: " + ТекстСообщения);
                // Если данные разовые, можно отключить обработчик и закрыть сокет
                // ОтключитьОбработчикОжидания("ПроверитьСостояниеИПрочитатьДанные");
                // WinSocket.Close();
            КонецЕсли;
        КонецЕсли;
        
    ИначеЕсли СостояниеСокета > 7 Тогда
        // Произошла ошибка или разрыв соединения (8 - sckClosing, 9 - sckError)
        Сообщить("Ошибка соединения или сокет закрыт. Код состояния: " + СостояниеСокета);
        ОтключитьОбработчикОжидания("ПроверитьСостояниеИПрочитатьДанные");
        WinSocket.Close();
    КонецЕсли; 
    
КонецПроцедуры

Важные нюансы при работе с весами

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

  1. Режим работы оборудования: Многие весы не транслируют вес постоянно. Они ждут от компьютера управляющую команду (запрос). В этом случае перед вызовом GetData необходимо отправить команду весам с помощью метода WinSocket.SendData("W") (где "W" — команда запроса веса согласно протоколу вашего устройства).
  2. Служебные символы Telnet: Если устройство действительно использует протокол Telnet (RFC 854), при подключении оно может отправить последовательность байтов настроек (начинаются с кода 255). Ваша обработка должна уметь очищать полезные данные от этих символов. Если же устройство работает по «сырому» TCP (Raw Socket), то данные будут приходить в чистом виде.
  3. Тип данных в GetData: В 1С рекомендуется явно указывать второй параметр метода GetData(Переменная, Тип). Значение 8 соответствует строке. Если весы передают данные в бинарном формате, работа через COM-объект в 1С может потребовать дополнительных преобразований массивов.
  4. Разрядность системы: Объект MSWinsock.Winsock является 32-битным (x86). Это означает, что он не будет работать в 64-битном сеансе 1С (на 64-битном сервере или в 64-битном тонком клиенте). Для работы в таких средах следует использовать либо внешние компоненты Native API, либо обертки над System.Net.Sockets из .NET.

Подведем итог: для стабильной работы с Winsock в 1С забудьте о линейном выполнении кода. Используйте циклическую проверку состояния через State и BytesReceived внутри обработчика ожидания. Это позволит вашей программе не «зависать» в ожидании ответа и корректно обрабатывать асинхронную природу сетевого обмена.

← На главную