Аналитика камеры через API¶
Вкладка Аналитика работает через запрос central POST /central/api-v4/streams/{stream}/onvif-call/analytics/{method}. Тот же запрос использует внешняя система. Central передаёт вызов стримеру, который принимает видео камеры, а стример — камере.
Перед началом¶
Запрос доступен ролям superadmin и admin. Стрим должен быть запущен, а камера подготовлена, как описано в разделе Подготовка стрима. Для примеров нужны Bash, curl и jq. Ответы в примерах получены от камеры Optimus; набор типов и параметров у другой камеры свой.
export CENTRAL_URL='https://central.example.com'
export API_LOGIN='admin'
export API_PASSWORD='your-password'
export STREAM='entrance'
analytics() {
curl --fail-with-body --silent --show-error \
--user "$API_LOGIN:$API_PASSWORD" \
--header 'Content-Type: application/json' \
--data "$2" \
"$CENTRAL_URL/central/api-v4/streams/$STREAM/onvif-call/analytics/$1"
}
Имя стрима со слэшем передаётся в кодированном виде: cams%2Fentrance.
Методы¶
Имена и тела методов повторяют сервис ONVIF Analytics, записанный в JSON. Атрибуты XML передаются с префиксом $, токен конфигурации аналитики Optic подставляет сам.
GetSupportedRules— типы правил камеры, их число и несовместимые сценарии.GetRuleOptions— пределы параметров правила.GetRules— правила камеры.CreateRules,ModifyRules,DeleteRules— создание, изменение и удаление правил.GetServiceCapabilities— что поддерживает сервис аналитики камеры.GetSupportedAnalyticsModules,GetAnalyticsModuleOptions,GetAnalyticsModules,ModifyAnalyticsModules— модули аналитики, например сетка и чувствительность детектора движения.
Другие методы записи отвергаются с кодом unsupported_method. Каждая попытка записи правил попадает в журнал аудита central с действием stream_onvif.rules_write.
Возможности камеры¶
Типы правил, их предельное число и несовместимые сценарии:
analytics GetSupportedRules '{}' | jq '.SupportedRules.RuleDescription[]
| {type: ."$Name", max: ."$maxInstances", excludes: .Extension.Excludes}'
{"type":"tt:LineDetector","max":"4","excludes":["tt:LineCounting","tt:ObjectAbandoned","tt:ObjectRemoved","cus:CrowdDetector","cus:QueueDetector","tt:ObjectDetection","tt:LicensePlateRecognition"]}
Пределы параметров одного типа:
analytics GetRuleOptions '{"RuleType":"tt:LineDetector"}' | jq '.RuleOptions'
[{"$Name":"Direction","$RuleType":"tt:LineDetector","StringList":"Right Left Any"},
{"$MaxItems":"3","$Name":"ClassFilter","$RuleType":"tt:LineDetector","StringList":"Human Vehicle NonMotorVehicle"},
{"$Name":"Sensitivity","$RuleType":"tt:LineDetector","IntRange":{"Max":"100","Min":"1"}}]
Возможности камеры стример держит в памяти. Чтобы прочитать их с камеры заново, например после обновления прошивки, добавьте заголовок x-onvif-fresh: true.
Чтение правил¶
analytics GetRules '{}' | jq
В ответе Extension.Executor называет исполнителя: optimus для адаптера Optimus, camera для стандартного ONVIF. Extension.Clock.UtcOffsetMinutes — смещение часов камеры от UTC, в этих часах задаётся расписание.
Создание, изменение и удаление¶
Создайте линию. Имя правила <тип>_<номер> назначается при создании и возвращается в RuleName:
analytics CreateRules '{"Rule":[{"$Type":"tt:LineDetector","Parameters":{
"SimpleItem":[{"$Name":"Armed","$Value":"false"},{"$Name":"Direction","$Value":"Any"}],
"ElementItem":[{"$Name":"Segments","Polyline":{"Point":[{"$x":-0.5,"$y":0},{"$x":0.5,"$y":0}]}}]}}]}'
{"Extension":{"Executor":"optimus","NotApplied":[]},"RuleName":["LineDetector_2"]}
Поставьте линию на охрану с расписанием по будням с 9 до 14:
analytics ModifyRules '{"Rule":[{"$Name":"LineDetector_2","$Type":"tt:LineDetector","Parameters":{
"SimpleItem":[{"$Name":"Armed","$Value":"true"}],
"ElementItem":[{"$Name":"Schedule","HourSchedule":{
"Mon":[[9,14]],"Tue":[[9,14]],"Wed":[[9,14]],"Thu":[[9,14]],"Fri":[[9,14]],"Sat":[],"Sun":[]}}]}}]}'
Если камера объявила несовместимые сценарии (Extension.Excludes) и окно пересекается с одним из них, запись отвергается: ответ — 422 schedule_overlap, см. Ошибки.
Удалите линию:
analytics DeleteRules '{"RuleName":["LineDetector_2"]}'
Чувствительность детектора движения задаётся в модуле аналитики:
analytics ModifyAnalyticsModules '{"AnalyticsModule":[{"$Name":"CellMotionEngine_1","$Type":"tt:CellMotionEngine",
"Parameters":{"SimpleItem":[{"$Name":"Sensitivity","$Value":"6"}]}}]}'
Правила записи:
- Координаты — от −1 до 1 по обеим осям, начало в центре кадра, ось y направлена вверх.
- Расписание —
ElementItemс именемSchedule: все семь дней (Mon…Sun), интервалы[начало, конец)в целых часах по часам камеры. Пустой день — сценарий в этот день выключен. У камер Optimus расписание общее для всех правил типа. - Постоянные правила (тип с
$fixed="true") —CreateRulesотвергается,DeleteRulesснимает правило с охраны. ModifyRules— меняет только переданные параметры.Extension.NotApplied— параметры, которые камера приняла, но не сохранила, см. Расширения ответа.
Расширения ответа¶
То, чего нет в стандарте ONVIF, Optic передаёт расширениями:
Extension.Executor— в каждом ответе:optimusдля адаптера Optimus,cameraдля стандартного ONVIF.Extension.Excludes— в описании типа вGetSupportedRules: типы, которые камера не держит включёнными в одни часы с этим. Камеры на стандартном ONVIF их не объявляют.Extension.Clock.UtcOffsetMinutes— вGetRules: смещение часов камеры от UTC, в этих часах задаётся расписание.Extension.NotApplied— в ответах записи: по элементу на параметр, который камера приняла, но не сохранила.$Rule— правило,$Parameter— параметр,$Sent— отправленное значение,$Read— прочитанное после записи. Пустой список — камера сохранила всё.$Sourceу параметра в описании типа:extension— параметра нет в стандарте, напримерSensitivity,MinSizeилиSchedule;by-analogy— имя параметра взято по аналогии с однотипным правилом.-
$Unitу параметра:pixel— пиксели кадра;second— секунды;frame-width— доля ширины кадра.$fixed="true"у типа — правило постоянное: его нельзя создать или удалить, только поставить на охрану или снять с неё.- Префикс
cus:— тип или параметр вне стандарта ONVIF, напримерcus:RegionEntranceDetectorилиcus:HourSchedule.
Описание типа с расширениями:
{"$Name":"cus:RegionEntranceDetector","$maxInstances":"4","Extension":{"Excludes":["tt:LineCounting","tt:ObjectAbandoned","tt:ObjectRemoved","cus:CrowdDetector","cus:QueueDetector","tt:ObjectDetection","tt:LicensePlateRecognition"]},
"Parameters":{"SimpleItemDescription":[{"$Name":"MinSize","$Type":"xs:int","$Source":"extension","$Unit":"pixel"}],
"ElementItemDescription":[{"$Name":"Schedule","$Type":"cus:HourSchedule","$Source":"extension"}]}}
Ответ записи, в котором камера оставила выключатель правила по-своему:
{"Extension":{"Executor":"optimus","NotApplied":[{"$Parameter":"Armed","$Read":true,"$Rule":"LineDetector_1","$Sent":false}]}}
Срабатывания¶
Срабатывания правил хранятся как эпизоды с episode_type=trigger. Код правила передаётся в episode_subtype, несколько кодов — через запятую.
curl --fail-with-body --silent --show-error \
--user "$API_LOGIN:$API_PASSWORD" \
"$CENTRAL_URL/central/api-v4/episodes?media=$STREAM&episode_type=trigger&episode_subtype=lcd,enter" | jq
{"episode_id":"7701038866144167249","media":"entrance","opened_at":1793037836008,"closed_at":1793037836008,
"frame_preview":{"sha256":"5c43636115c17e9cdd6810added59741109f637ce529f4d38e06fd2f341e954a","mime_type":"image/jpeg"},
"detections":[],"details":{"type":"trigger","rule":"lcd"}}
Коды правил:
lcd— пересечение линии;cc— подсчёт пересечений;enter— вход в зону;exit— выход из зоны;pid— вторжение;sod— оставленный или унесённый предмет;cd— скопление;qd— очередь;tamper— саботаж.
Кадр срабатывания отдаёт GET /central/api-v4/episodes/{episode_id}/images/{sha256}, где sha256 берётся из frame_preview.
Заголовки запроса¶
x-onvif-fresh: true— прочитать возможности камеры заново, без памяти стримера.x-onvif-auth: user:password— учётные данные камеры вместо взятых из RTSP-адреса.x-onvif-port— HTTP-порт камеры, если он отличается от стандартного.
Ошибки¶
- 400
unsupported_method— метод записи вне списка аналитики; 400auth_error— заголовокx-onvif-authне видаuser:password. - 401 — неверные учётные данные Optic.
- 404
not_found— стрим не запущен ни на одном стримере. - 409
no_camera_target— у стрима нет RTSP-источника с адресом камеры. - 422
param_error— значение вне пределов камеры; 422schedule_overlap— несовместимые сценарии в одни часы. Вerrors[].pathуказан путь к полю. - 502
auth_error— камера отвергла логин и пароль; 502onvif_error— камера ответила ошибкой или недоступна. - 503 — камера занята или просит подождать; повторите запрос позже.
- 504 — камера не ответила вовремя. Запись при этом могла примениться: перед повтором прочитайте правила
GetRules, иначе повторCreateRulesсоздаст второе правило.
Примеры ответа 422:
{"error":{"code":"param_error","message":"tt:LineDetector: MinSize is 8 px, the camera takes 64..1080 px",
"errors":[{"path":["Rule",0,"Parameters","SimpleItem",4,"$Value"],"message":"tt:LineDetector: MinSize is 8 px, the camera takes 64..1080 px"}]}}
{"error":{"code":"schedule_overlap","message":"tt:LineDetector and tt:LicensePlateRecognition are both active on day 0 from 14:00 to 18:00 by the camera clock; the camera keeps only one of them at a time",
"errors":[{"path":["Rule",0,"Parameters","ElementItem",0,"HourSchedule"],"message":"…"}]}}
Central не повторяет вызов на другом стримере после обрыва связи: запись в камеру может уже выполниться, и повтор изменил бы её дважды.