Analítica de la cámara mediante la API¶
La pestaña Analítica funciona con la solicitud de central POST /central/api-v4/streams/{stream}/onvif-call/analytics/{method}. Un sistema externo usa la misma solicitud. Central reenvía la llamada al streamer que captura el vídeo de la cámara, y el streamer la pasa a la cámara.
Antes de empezar¶
La solicitud está disponible para los roles superadmin y admin. El stream debe estar en marcha y la cámara preparada como se describe en Preparación del stream. Los ejemplos requieren Bash, curl y jq. Las respuestas de los ejemplos proceden de una cámara Optimus; otra cámara tiene su propio conjunto de tipos y parámetros.
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"
}
Un nombre de stream con barra se pasa codificado: cams%2Fentrance.
Métodos¶
Los nombres y cuerpos de los métodos siguen el servicio ONVIF Analytics escrito en JSON. Los atributos XML llevan el prefijo $; Optic añade por sí mismo el token de configuración de analítica.
GetSupportedRules— los tipos de regla de la cámara, su número y los escenarios incompatibles.GetRuleOptions— los límites de los parámetros de una regla.GetRules— las reglas de la cámara.CreateRules,ModifyRules,DeleteRules— crear, cambiar y eliminar reglas.GetServiceCapabilities— qué admite el servicio de analítica de la cámara.GetSupportedAnalyticsModules,GetAnalyticsModuleOptions,GetAnalyticsModules,ModifyAnalyticsModules— los módulos de analítica, por ejemplo la rejilla y la sensibilidad del detector de movimiento.
Los demás métodos de escritura se rechazan con el código unsupported_method. Cada intento de escribir reglas queda en el registro de auditoría de central con la acción stream_onvif.rules_write.
Capacidades de la cámara¶
Tipos de regla, su número máximo y escenarios incompatibles:
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"]}
Límites de los parámetros de un tipo:
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"}}]
El streamer guarda las capacidades de la cámara en memoria. Para leerlas de nuevo de la cámara, por ejemplo tras actualizar el firmware, añada el encabezado x-onvif-fresh: true.
Lectura de reglas¶
analytics GetRules '{}' | jq
En la respuesta, Extension.Executor indica el ejecutor: optimus para el adaptador Optimus, camera para ONVIF estándar. Extension.Clock.UtcOffsetMinutes es el desfase del reloj de la cámara respecto a UTC; el horario se indica en esas horas.
Crear, cambiar y eliminar¶
Cree una línea. El nombre de la regla <tipo>_<número> se asigna al crearla y se devuelve en 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"]}
Arme la línea con un horario de lunes a viernes de 9 a 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":[]}}]}}]}'
Si la cámara declaró escenarios incompatibles (Extension.Excludes) y la ventana se solapa con uno de ellos, la escritura se rechaza: la respuesta es 422 schedule_overlap, consulte Errores.
Elimine la línea:
analytics DeleteRules '{"RuleName":["LineDetector_2"]}'
La sensibilidad del detector de movimiento se indica en el módulo de analítica:
analytics ModifyAnalyticsModules '{"AnalyticsModule":[{"$Name":"CellMotionEngine_1","$Type":"tt:CellMotionEngine",
"Parameters":{"SimpleItem":[{"$Name":"Sensitivity","$Value":"6"}]}}]}'
Reglas de escritura:
- Coordenadas — de −1 a 1 en ambos ejes, origen en el centro del fotograma, el eje y apunta hacia arriba.
- Horario — un
ElementItemllamadoSchedule: los siete días (Mon…Sun), intervalos[inicio, fin)en horas enteras del reloj de la cámara. Un día vacío apaga el escenario ese día. En las cámaras Optimus, el horario es común a todas las reglas del tipo. - Reglas permanentes (tipo con
$fixed="true") —CreateRulesse rechaza;DeleteRulesdesarma la regla. ModifyRules— cambia solo los parámetros enviados.Extension.NotApplied— parámetros que la cámara aceptó pero no guardó, consulte Extensiones de la respuesta.
Extensiones de la respuesta¶
Lo que el estándar ONVIF no contempla, Optic lo transmite como extensiones:
Extension.Executor— en cada respuesta:optimuspara el adaptador Optimus,camerapara ONVIF estándar.Extension.Excludes— en la descripción de un tipo enGetSupportedRules: tipos que la cámara no mantiene activos en las mismas horas que este. Las cámaras con ONVIF estándar no los declaran.Extension.Clock.UtcOffsetMinutes— enGetRules: el desfase del reloj de la cámara respecto a UTC; el horario se indica en esas horas.Extension.NotApplied— en las respuestas de escritura: un elemento por parámetro que la cámara aceptó pero no guardó.$Rulees la regla,$Parameterel parámetro,$Sentel valor enviado y$Readel leído tras la escritura. Una lista vacía significa que la cámara lo guardó todo.$Sourcede un parámetro en la descripción de un tipo:extension— el parámetro no está en el estándar, por ejemploSensitivity,MinSizeoSchedule;by-analogy— el nombre del parámetro se tomó por analogía con una regla de tipo similar.-
$Unitde un parámetro:pixel— píxeles del fotograma;second— segundos;frame-width— fracción del ancho del fotograma.$fixed="true"de un tipo — la regla es permanente: no se puede crear ni eliminar, solo armar o desarmar.- El prefijo
cus:— un tipo o parámetro fuera del estándar ONVIF, por ejemplocus:RegionEntranceDetectorocus:HourSchedule.
Descripción de un tipo con extensiones:
{"$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"}]}}
Respuesta de escritura en la que la cámara mantuvo el interruptor de la regla a su manera:
{"Extension":{"Executor":"optimus","NotApplied":[{"$Parameter":"Armed","$Read":true,"$Rule":"LineDetector_1","$Sent":false}]}}
Activaciones¶
Las activaciones de las reglas se guardan como episodios con episode_type=trigger. El código de la regla va en episode_subtype; varios códigos se separan con comas.
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"}}
Códigos de regla:
lcd— cruce de línea;cc— conteo de cruces;enter— entrada en zona;exit— salida de zona;pid— intrusión;sod— objeto abandonado o retirado;cd— aglomeración;qd— cola;tamper— sabotaje.
El fotograma de la activación lo devuelve GET /central/api-v4/episodes/{episode_id}/images/{sha256}, con sha256 tomado de frame_preview.
Encabezados de la solicitud¶
x-onvif-fresh: true— leer de nuevo las capacidades de la cámara, sin la memoria del streamer.x-onvif-auth: user:password— credenciales de la cámara en lugar de las de la URL RTSP.x-onvif-port— el puerto HTTP de la cámara si no es el predeterminado.
Errores¶
- 400
unsupported_method— un método de escritura fuera de la lista de analítica; 400auth_error— el encabezadox-onvif-authno tiene la formauser:password. - 401 — credenciales de Optic incorrectas.
- 404
not_found— el stream no está en marcha en ningún streamer. - 409
no_camera_target— el stream no tiene una fuente RTSP con la dirección de la cámara. - 422
param_error— un valor fuera de los límites de la cámara; 422schedule_overlap— escenarios incompatibles en las mismas horas.errors[].pathindica el campo. - 502
auth_error— la cámara rechazó el usuario y la contraseña; 502onvif_error— la cámara respondió con un error o no está accesible. - 503 — la cámara está ocupada o pide esperar; repita la solicitud más tarde.
- 504 — la cámara no respondió a tiempo. La escritura puede haberse aplicado: lea las reglas con
GetRulesantes de reintentar; si no, repetirCreateRulescrea una segunda regla.
Ejemplos de respuesta 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 no repite una llamada en otro streamer tras perder la conexión: la escritura en la cámara puede haberse hecho ya, y repetirla la cambiaría dos veces.