Как объявить типизированные переменные и массивы COMSafeArray для работы с OPC DA сервером в 1С?

Программист 1С v8.3 (Обычные формы) Промышленность, строительство и АПК
← На главную

При интеграции 1С с промышленным оборудованием через протокол OPC DA (Data Access) программисты часто сталкиваются с жесткими требованиями к типам данных. В отличие от 1С, где типизация переменных динамическая, COM-объекты (такие как OPC.Automation) ожидают строго определенные типы: Long, Variant, а также специфические массивы SafeArray. В этой статье мы подробно разберем, как правильно подготовить данные для вызова метода SyncRead и избежать ошибок несовпадения типов.

Анализ проблемы и структуры метода SyncRead

Для начала проанализируем сигнатуру метода SyncRead, который используется для синхронного чтения данных из OPC-сервера. Она выглядит следующим образом:

SyncRead(Source As Integer, NumItems As Long, ServerHandles() As Long, ByRef Values() As Variant, ByRef Errors() As Long, Optional ByRef Qualities As Variant, Optional ByRef TimeStamps As Variant)

Основные сложности в 1С вызывают следующие параметры:

  1. NumItems (Long): 32-битное целое число. В 1С обычное число имеет тип Numeric (с плавающей точкой), поэтому при передаче в COM-метод важно убедиться, что оно передается без дробной части.
  2. ServerHandles() (Массив Long): Список идентификаторов тегов на сервере.
  3. Values() (Массив Variant): Массив, куда сервер запишет считанные значения.
  4. Errors() (Массив Long): Массив для кодов ошибок по каждому тегу.

Работа с COMSafeArray в 1С

Рассмотрим, как в среде 1С создать структуры, которые будут понятны COM-объекту. Единственным способом передать типизированный массив является использование объекта COMSafeArray. При его создании мы должны явно указать тип элементов, используя константы типов VARTYPE.

Выделим основные типы, которые нам понадобятся:

Пошаговая реализация подключения и чтения данных

Давайте разберем процесс подготовки переменных по шагам. Предположим, что мы уже успешно создали соединение с сервером и добавили необходимые группы тегов.

Шаг 1: Подготовка идентификаторов (Server Handles)

Прежде чем читать данные, нам нужно получить массив серверных дескрипторов тегов. Эти дескрипторы выдает сервер при вызове метода AddItem. Проанализируем пример кода:


// Инициализируем количество элементов
КоличествоТегов = 1;
// Создаем массив для дескрипторов (тип Long -> VT_I4)
ServerHandles = Новый COMSafeArray("VT_I4", КоличествоТегов);

// Получаем дескриптор тега (обычно это свойство объекта OPCItem)
Дескриптор = Item.ServerHandle; 

// Заполняем массив (индексация в COMSafeArray в 1С начинается с 0)
ServerHandles.SetValue(0, Дескриптор);

Шаг 2: Создание приемных массивов для данных и ошибок

Метод SyncRead требует передачи массивов, в которые он "вернет" результат. Даже если мы читаем один элемент, это должен быть массив. Важно инициализировать их правильными типами:


// Массив для значений (VT_VARIANT)
Values = Новый COMSafeArray("VT_VARIANT", КоличествоТегов);

// Массив для ошибок (VT_I4)
Errors = Новый COMSafeArray("VT_I4", КоличествоТегов);

// Необязательные параметры (Качество и Метки времени)
// Их также рекомендуется инициализировать как SafeArray для стабильности
Qualities = Новый COMSafeArray("VT_VARIANT", КоличествоТегов);
TimeStamps = Новый COMSafeArray("VT_VARIANT", КоличествоТегов);

Шаг 3: Вызов метода SyncRead

Теперь, когда все переменные типизированы, вызовем метод чтения. Выясним назначение первого параметра Source: значение 1 (OPC_DS_CACHE) означает чтение из кэша сервера, значение 2 (OPC_DS_DEVICE) — прямое чтение с физического устройства.


ИсточникДанных = 1; // Читаем из кэша
Попытка
    OPCGroup.SyncRead(ИсточникДанных, КоличествоТегов, ServerHandles, Values, Errors, Qualities, TimeStamps);
Исключение
    Сообщить("Ошибка при вызове SyncRead: " + ОписаниеОшибки());
КонецПопытки;

Обработка полученных данных

После успешного выполнения метода SyncRead, данные будут находиться внутри объектов COMSafeArray. Нам необходимо извлечь их для дальнейшего использования в 1С. Посмотрим, как это сделать правильно:


Для Индекс = 0 По КоличествоТегов - 1 Цикл
    // Проверяем код ошибки для конкретного тега (0 - успех)
    КодОшибки = Errors.GetValue(Индекс);
    Если КодОшибки = 0 Тогда
        ТекущееЗначение = Values.GetValue(Индекс);
        ТекущееКачество = Qualities.GetValue(Индекс);
        МеткаВремени    = TimeStamps.GetValue(Индекс);
        
        Сообщить("Значение тега: " + Строка(ТекущееЗначение) + " | Качество: " + Строка(ТекущееКачество));
    Иначе
        Сообщить("Ошибка чтения тега с индексом " + Индекс + ". Код: " + КодОшибки);
    КонецЕсли;
КонецЦикла;

Важные нюансы и рекомендации

1. Проблема нижней границы массива (LBound)

Исторически библиотеки OPC Automation писались на Visual Basic 6, где массивы часто начинаются с индекса 1. Платформа 1С при создании COMSafeArray всегда создает массив с нижней границей 0. Большинство современных OPC-серверов корректно это обрабатывают, но если вы получаете ошибку "Неверный аргумент", стоит проверить документацию конкретного OPC-сервера. Возможно, он ожидает массив, созданный через специальную обертку с базой 1.

2. Использование метода Item.Read()

Если вам нужно прочитать всего один тег и вы хотите избежать сложностей с COMSafeArray, рассмотрим альтернативный вариант. У каждого объекта OPCItem есть собственный метод Read:


// Объявляем переменные для результата
Значение = Неопределено;
Качество = Неопределено;
Время    = Неопределено;

// Вызов метода (параметры передаются по ссылке)
Item.Read(1, Значение, Качество, Время);

Сообщить("Результат: " + Значение);

Этот способ значительно проще в реализации, но он менее эффективен, если вам нужно считывать сотни параметров одновременно, так как каждый вызов Read создает отдельный сетевой запрос.

3. Типизация параметра NumItems

Хотя 1С автоматически пытается привести типы при передаче в COM, иногда возникают ошибки, если число передается в формате с плавающей точкой (например, 1.000). Чтобы гарантировать тип Long, убедитесь, что вы передаете целое число, полученное функцией Цел(), или используйте прямое указание значения.

Заключение

Работа с типизированными переменными в 1С при взаимодействии с COM-объектами требует внимательности к деталям. Использование COMSafeArray с типами VT_I4 и VT_VARIANT позволяет полностью реализовать протокол обмена данными с любым OPC DA сервером без использования сторонних внешних компонент. Мы разобрали основные шаги от инициализации массивов до извлечения данных, что должно помочь вам успешно решить задачу интеграции.

← На главную