Как получить изображение с IP-камеры в 1С:Предприятие через HTTP-запрос?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В современной практике автоматизации бизнеса часто возникает задача интеграции системы 1С с системами видеонаблюдения. Это может быть фиксация взвешивания автомобилей на складе, распознавание номеров, контроль сборки заказов или фиксация посетителей. Самый простой и быстрый способ получить текущий кадр с IP-камеры — отправить прямой HTTP-запрос к её внутреннему веб-серверу для получения статического JPEG-изображения (снапшота).

В этой статье мы подробно разберем, как правильно настроить такое взаимодействие в 1С, проанализируем типичные ошибки разработчиков, рассмотрим нюансы авторизации различных производителей оборудования и оптимизируем работу с полученными двоичными данными.

Типичная ошибка: Относительный против Абсолютного пути

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


// Ошибочный вариант реализации запроса
Соединение = Новый HTTPСоединение("192.168.0.101",, Имя, Пароль);
Запрос = Новый HTTPЗапрос("http://192.168.0.101/cgi-bin/jpg/image.cgi?");
Ответ = Соединение.Получить(Запрос);
ДвоичныеДанныеКартинки = Ответ.ПолучитьТелоКакДвоичныеДанные();    
ДвоичныеДанныеКартинки.Записать("C:\temp\1.jpg");

При выполнении этого кода сервер возвращает ошибку 503 Service Unavailable или 400 Bad Request. Выясним причину этой неполадки.

Дело в том, что при создании объекта HTTPСоединение мы уже жестко указываем адрес хоста (IP-адрес или доменное имя камеры) — в нашем примере это "192.168.0.101". При последующем создании объекта HTTPЗапрос в качестве параметра конструктора необходимо передавать относительный путь к ресурсу на сервере, а не полный абсолютный URL.

Давайте исправим эту ошибку и посмотрим на корректный рабочий пример кода:


// Исправленный и рабочий вариант запроса снапшота
АдресКамеры = "192.168.0.101";
Логин = "admin";
Пароль = "secure_pass_123";

// Инициализируем соединение с указанием хоста и учетных данных
Соединение = Новый HTTPСоединение(АдресКамеры, , Логин, Пароль);

// Указываем только относительный путь к CGI-скрипту получения кадра
ОтносительныйПуть = "/cgi-bin/jpg/image.cgi?";
Запрос = Новый HTTPЗапрос(ОтносительныйПуть);

Попытка
    Ответ = Соединение.Получить(Запрос);
    Если Ответ.КодСостояния = 200 Тогда
        ДвоичныеДанныеКартинки = Ответ.ПолучитьТелоКакДвоичныеДанные();
        // Далее обрабатываем полученные двоичные данные
    Иначе
        ВызватьИсключение "Ошибка камеры. Код состояния: " + Ответ.КодСостояния;
    КонецЕсли;
Исключение
    ЗаписьЖурналаРегистрации("ПолучениеКадра", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

Проблема авторизации: Basic против Digest

Если после исправления адреса на относительный вы всё равно получаете ошибку (например, 401 Unauthorized), дело может быть в используемом типе авторизации.

В платформе 1С передача параметров логина и пароля непосредственно в конструктор HTTPСоединение по умолчанию задействует базовую авторизацию (Basic Authorization). При этом логин и пароль кодируются методом Base64 и передаются в заголовке запроса.

Однако современные IP-камеры ведущих брендов (таких как Hikvision, HiWatch, Dahua) в последних версиях прошивок отключают базовую авторизацию из соображений безопасности, принудительно переводя устройство на авторизацию типа Digest.

У этой проблемы есть два практических решения:

  1. Изменение настроек в веб-интерфейсе камеры: Вам необходимо зайти в админ-панель камеры в раздел «Безопасность» или «Протоколы интеграции» и переключить режим авторизации веб-служб/RTSP с режима "Digest" на совмещенный режим "Digest/Basic".
  2. Программная реализация Digest-авторизации в 1С: Если изменять настройки камеры запрещено политикой безопасности, вам придется реализовать алгоритм Digest-авторизации вручную в коде. Для этого отправляется первый «пустой» запрос, в ответ на который камера присылает заголовок WWW-Authenticate с уникальными параметрами (nonce, realm, qop). На основе этих данных и ваших учетных данных с помощью объекта ХешированиеДанных (алгоритм MD5) вычисляется хэш-ответ, который передается во втором, уже авторизованном запросе.

Рассмотрим пример того, как можно вручную сформировать заголовок Basic-авторизации в коде 1С, если стандартный механизм платформы по какой-то причине отрабатывает некорректно:


// Пример ручной сборки заголовка Basic авторизации
СтрокаАвторизации = Логин + ":" + Пароль;
ДвоичныеДанныеСтроки = ПолучитьДвоичныеДанныеИзСтроки(СтрокаАвторизации, КодировкаТекста.UTF8);
КодированныйСтрокой = ПолучитьСтрокуBase64ИзДвоичныхДанных(ДвоичныеДанныеСтроки);

Запрос = Новый HTTPЗапрос("/cgi-bin/jpg/image.cgi?");
Запрос.Заголовки.Вставить("Authorization", "Basic " + КодированныйСтрокой);

Различия в адресах получения кадра у разных производителей

Путь /cgi-bin/jpg/image.cgi?, использованный в примере автора темы, индивидуален для его конкретной модели камеры. При переносе вашего программного решения на устройства других вендоров, относительный путь обязательно изменится. Рассмотрим наиболее популярные варианты:

  1. Hikvision и HiWatch: Современные линейки этих брендов работают по стандартизированному протоколу ISAPI. Для получения кадра с первого (основного) видеоканала используется путь:
    /ISAPI/Streaming/channels/101/picture?snapShotImageType=JPEG (где 101 означает 1-й канал, основной поток; для субпотока используйте 102).
  2. Dahua: Камеры этого производителя чаще всего отдают статический кадр по стандартному CGI-пути:
    /cgi-bin/snapshot.cgi
  3. Универсальный стандарт ONVIF: Если модель камеры неизвестна заранее, но устройство поддерживает протокол ONVIF, можно отправить SOAP-запрос к службе медиа-настроек камеры для динамического получения актуальной ссылки (Snapshot URI).

Оптимизация работы с двоичными данными в 1С

В кодовой базе старых конфигураций часто встречается запись полученного файла на локальный диск: ДвоичныеДанныеКартинки.Записать("C:\temp\1.jpg");.

В современных реалиях клиент-серверной архитектуры 1С этот подход содержит в себе критические уязвимости:

Разберем по шагам, как решить эту проблему оптимально и красиво с использованием механизма временных хранилищ 1С v8.3. Этот подход позволяет передавать изображение напрямую в элемент интерфейса формы без сохранения промежуточных файлов на жестком диске.


// Получаем картинку с камеры без сохранения на диск
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
    ДвоичныеДанныеКартинки = Ответ.ПолучитьТелоКакДвоичныеДанные();
    
    // Помещаем двоичные данные во временное хранилище платформы
    // УникальныйИдентификатор — это UUID текущей управляемой формы 1С
    АдресКартинкиВХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанныеКартинки, УникальныйИдентификатор);
    
    // Теперь мы можем напрямую передать этот адрес реквизиту формы, 
    // связанному с элементом управления "Поле картинки"
    Объект.ПутьККартинкеНаФорме = АдресКартинкиВХранилище;
КонецЕсли;

Если логика бизнес-процесса всё же требует физического сохранения файла на диске (например, для последующей отправки по электронной почте), воспользуйтесь платформенным методом получения уникального пути во временной директории операционной системы:


// Безопасное сохранение во временный файл системы
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("jpg");
ДвоичныеДанныеКартинки.Записать(ИмяВременногоФайла);

// Выполняем действия с файлом...

// После завершения работы обязательно удаляем временный файл
Попытка
    УдалитьФайлы(ИмяВременногоФайла);
Исключение
    // Обработка исключения, если файл занят другим процессом
КонецПопытки;

Альтернативные архитектурные решения

Полноценная интеграция систем видеонаблюдения напрямую из кода 1С посредством HTTP-опроса имеет свои архитектурные ограничения. Если камер много (более 10), а запросы кадра происходят часто, процессор IP-камеры может зависнуть от перегрузки веб-сервера.

Для крупных промышленных инсталляций рекомендуется использовать один из альтернативных вариантов:

← На главную