Ir al contenido

Informes y analíticas

Obtén analíticas de conteo y series temporales desde la API de Rhombus: conteos de personas y vehículos, tendencias de ocupación, conteos de cruce de línea (umbral) y exportación a CSV.

En esta página

Descripción general

El Report Webservice de Rhombus convierte las detecciones de tus cámaras en analíticas agregadas y agrupadas por tiempo. En lugar de recorrer eventos individuales, solicitas un informe de conteo para un rango de tiempo y un intervalo, y Rhombus devuelve un punto de datos por cada segmento (bucket) con un conteo por tipo.

A través de la API, puedes:

  • Crear series temporales de conteo de personas, vehículos, movimiento, rostros y otros tipos de detección a nivel de organización, ubicación o dispositivo
  • Seguir conteos de personas y ocupación con las lecturas más recientes y tendencias de ocupación agrupadas
  • Medir conteos de cruce de línea (umbral) de personas o vehículos que cruzan una línea configurada
  • Exportar datos de informes como CSV para hojas de cálculo, herramientas de BI e informes de cumplimiento

Se aplican algunas convenciones en toda esta API:

  • Las marcas de tiempo están en milisegundos epoch en los endpoints V2, de ocupación y de umbral (startTimeMs / endTimeMs). El endpoint heredado v1 getCountReport usa cadenas de fecha "YYYY-MM-DD" en su lugar.
  • Los informes se describen con tres enumeraciones: un tipo de informe (qué contar), un intervalo (tamaño del segmento) y un alcance (organización, ubicación o dispositivo). Consulta las tablas de referencia más abajo.
  • No existe un endpoint para "listar tipos de informe". Los tipos disponibles son fijos y están documentados en la tabla ReportType.

Requisitos previos

Todas las solicitudes son POST, envían un cuerpo JSON y usan la URL base https://api2.rhombussystems.com con estos encabezados:

x-auth-scheme: api-token
x-auth-apikey: YOUR_API_KEY
Content-Type: application/json

Crear una serie temporal de conteo

getCountReportV2 es el endpoint principal de informes. Proporciona un rango de tiempo en milisegundos epoch, un intervalo, un alcance y uno o más tipos de informe. Rhombus devuelve un punto de datos por cada segmento del intervalo, cada uno con un eventCountMap indexado por tipo de informe.

Este ejemplo obtiene conteos horarios de personas y vehículos para una sola ubicación durante las últimas 24 horas.

import requests
import time

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

now_ms = int(time.time() * 1000)
one_day_ago_ms = now_ms - (24 * 60 * 60 * 1000)

response = requests.post(
    "https://api2.rhombussystems.com/api/report/getCountReportV2",
    headers=headers,
    json={
        "scope": "LOCATION",
        "uuid": "YOUR_LOCATION_UUID",
        "types": ["PEOPLE", "VEHICLES"],
        "interval": "HOURLY",
        "startTimeMs": one_day_ago_ms,
        "endTimeMs": now_ms,
        "timeZone": "America/Los_Angeles"
    }
)

data = response.json()
for point in data.get("timeSeriesDataPoints", []):
    counts = point.get("eventCountMap", {})
    print(f"{point.get('dateLocal')}: "
          f"people={counts.get('PEOPLE', 0)}, "
          f"vehicles={counts.get('VEHICLES', 0)}")

Campos de la solicitud

scopestringbodyobligatorio

Nivel de agregación. Uno de ORG, LOCATION, DEVICE o REGION. Consulta la tabla ReportScope.

uuidstringbody

El UUID de la ubicación o dispositivo que coincide con tu scope. Omítelo con scope: "ORG" para informar sobre toda la organización.

typesstring[]bodyobligatorio

Uno o más tipos de informe a contar. Consulta la tabla ReportType.

intervalstringbodyobligatorio

Tamaño del segmento de cada punto de datos. Uno de MINUTELY, QUARTERHOURLY, HOURLY, DAILY, WEEKLY, MONTHLY. Consulta la tabla ReportInterval.

startTimeMsintegerbodyobligatorio

Inicio del rango, en milisegundos epoch.

endTimeMsintegerbodyobligatorio

Fin del rango, en milisegundos epoch.

timeZonestringbody

Zona horaria IANA opcional (por ejemplo, America/New_York). Controla dónde caen los límites de los segmentos del intervalo y rellena dateLocal. Por defecto es UTC cuando se omite.

Advertencia

El endpoint V2 acepta los campos heredados startDate / endDate como cadenas, pero están obsoletos. Usa en su lugar los campos en milisegundos epoch startTimeMs / endTimeMs.

Campos de la respuesta

timeSeriesDataPointsobject[]

Una entrada por cada segmento del intervalo.

Mostrar TimeSeriesDataPointV2Type
dateUtcstring
Inicio del segmento expresado en UTC.
dateLocalstring
Inicio del segmento expresado en la timeZone solicitada.
eventCountMapobject
Mapa de tipo de informe a conteo para este segmento, por ejemplo {"PEOPLE": 42, "VEHICLES": 7}.
reportingDevicesMapobject
Mapa de tipo de informe a la lista de UUID de dispositivos que aportaron conteos en este segmento.
Consejo

¿Necesitas un total único en lugar de una serie por segmentos? Llama a /api/report/getSummaryCountReport con los mismos startTimeMs, endTimeMs, interval, scope y un solo type.

Informes heredados con cadenas de fecha

El endpoint v1 /api/report/getCountReport es anterior a las marcas de tiempo en milisegundos epoch. Toma startDate y endDate como cadenas "YYYY-MM-DD" y un único type en lugar de un arreglo types. Prefiere getCountReportV2 para nuevas integraciones; usa v1 solo si ya dependes de su comportamiento con cadenas de fecha.

cURLbash
curl -X POST https://api2.rhombussystems.com/api/report/getCountReport \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{
    "scope": "LOCATION",
    "uuid": "YOUR_LOCATION_UUID",
    "type": "PEOPLE",
    "interval": "DAILY",
    "startDate": "2024-01-01",
    "endDate": "2024-01-31"
  }'

Crear un panel de conteo de personas y ocupación

Para un panel de ocupación, usa getOccupancyCountsV2 para una tendencia de ocupación agrupada en el tiempo y grafica junto a ella getCountReportV2 con types: ["PEOPLE"] para el tráfico de personas (consulta Crear una serie temporal de conteo).

Tendencia de ocupación en el tiempo

getOccupancyCountsV2 devuelve la ocupación agrupada de un dispositivo a lo largo de un rango de tiempo, usando el mismo modelo de intervalos que los informes de conteo.

import requests
import time

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

now_ms = int(time.time() * 1000)
one_day_ago_ms = now_ms - (24 * 60 * 60 * 1000)

response = requests.post(
    "https://api2.rhombussystems.com/api/report/getOccupancyCountsV2",
    headers=headers,
    json={
        "deviceUuid": "YOUR_CAMERA_UUID",
        "startTimeMs": one_day_ago_ms,
        "endTimeMs": now_ms,
        "interval": "HOURLY"
    }
)

data = response.json()
for point in data.get("timeSeriesDataPoints", []):
    print(f"{point.get('dateLocal')}: {point.get('eventCountMap')}")

Los timeSeriesDataPoints de la respuesta llevan los mismos campos dateUtc, dateLocal, eventCountMap y reportingDevicesMap que los informes de conteo, además de un timestampMs (inicio del segmento en milisegundos epoch) y un approximateTimestampMsMap.

Contar cruces de línea (conteos de umbral)

Cuando una cámara tiene configurada una línea de cruce, Rhombus cuenta los objetos que la cruzan. getThresholdCrossingCounts devuelve esos conteos agrupados en el tiempo para uno o más dispositivos, filtrados a una sola clase de objeto.

El campo dailyResetTimeMinute establece el minuto del día (0–1439, en la hora local del dispositivo) en el que el conteo diario acumulado se reinicia: útil para alinear los conteos a una jornada comercial en lugar de a la medianoche.

import requests
import time

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

now_ms = int(time.time() * 1000)
one_week_ago_ms = now_ms - (7 * 24 * 60 * 60 * 1000)

response = requests.post(
    "https://api2.rhombussystems.com/api/report/getThresholdCrossingCounts",
    headers=headers,
    json={
        "devices": ["YOUR_CAMERA_UUID"],
        "startTimeMs": one_week_ago_ms,
        "endTimeMs": now_ms,
        "crossingObject": "HUMAN",
        "dailyResetTimeMinute": 0
    }
)

data = response.json()
for entry in data.get("counts", []):
    print(f"[{entry.get('timestampMs')}] crossings={entry.get('count')}")

Campos de la solicitud

devicesstring[]body

Uno o más UUID de cámaras a incluir en los conteos.

startTimeMsintegerbody

Inicio del rango, en milisegundos epoch.

endTimeMsintegerbody

Fin del rango, en milisegundos epoch.

crossingObjectstringbody

La clase de objeto a contar. Los valores comunes son HUMAN y VEHICLE. Consulta la tabla CrossingObject.

dailyResetTimeMinuteintegerbody

Minuto del día (0–1439) en el que se reinicia el conteo diario, en la hora local del dispositivo.

Campos de la respuesta

countsobject[]
Mostrar ThresholdCrossingCountType
countinteger
Número de cruces en este segmento.
timestampMsinteger
Inicio del segmento en milisegundos epoch.

Exportar datos de informes como CSV

El Export Webservice transmite los datos de informes como CSV (text/csv) en lugar de JSON. No existe exportación a PDF: CSV es el único formato de exportación.

Advertencia

Los endpoints de exportación (y los feeds de auditoría/diagnóstico) requieren el permiso REPORT_ADMINISTRATION en tu clave de API. Sin él, estas llamadas se rechazan.

/api/export/countReports refleja los parámetros del informe de conteo pero devuelve un flujo CSV. Ten en cuenta que la exportación toma un único campo type, no un arreglo types, y tanto startTimeMs como endTimeMs son obligatorios.

import requests
import time

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

now_ms = int(time.time() * 1000)
thirty_days_ago_ms = now_ms - (30 * 24 * 60 * 60 * 1000)

response = requests.post(
    "https://api2.rhombussystems.com/api/export/countReports",
    headers=headers,
    json={
        "scope": "LOCATION",
        "uuidList": ["YOUR_LOCATION_UUID"],
        "type": "PEOPLE",
        "interval": "DAILY",
        "startTimeMs": thirty_days_ago_ms,
        "endTimeMs": now_ms,
        "timeZone": "America/Los_Angeles"
    }
)

# La respuesta es texto CSV, no JSON
with open("people_count_report.csv", "w") as f:
    f.write(response.text)
print("Informe exportado a people_count_report.csv")

Para exportar lecturas de conteo de personas sin agregar en lugar de informes agregados, usa /api/export/peopleCountEvents con un startInterval y un endInterval (milisegundos epoch). Devuelve CSV de la misma manera.

Referencia de enumeraciones

Los informes se describen con un pequeño conjunto de enumeraciones fijas. No hay ningún endpoint que las liste en tiempo de ejecución: los valores siguientes son el conjunto completo.

ReportType

Valores aceptados por el arreglo types (V2) y el campo único type (v1 y exportación).

ValorCuenta
CROWDDetecciones de densidad de multitud
PEOPLEDetecciones de personas / conteo de personas
FACESDetecciones de rostros
MOTIONEventos de movimiento
BANDWIDTHUso de ancho de banda del dispositivo
VEHICLESDetecciones de vehículos
LICENSEPLATESLecturas de matrículas
ALERTSEventos de alerta / política
AM_VERIFICATIONVerificaciones de monitoreo de alarmas
DWELLDetecciones de tiempo de permanencia

ReportInterval

Tamaño del segmento de cada punto de datos.

ValorSegmento
MINUTELYPor minuto
QUARTERHOURLYCada 15 minutos
HOURLYPor hora
DAILYPor día
WEEKLYPor semana
MONTHLYPor mes

ReportScope

Nivel de agregación de un informe de conteo. Proporciona un uuid correspondiente para LOCATION, DEVICE o REGION; omítelo para ORG.

ValorAgrega sobre
ORGToda la organización
LOCATIONUna sola ubicación
DEVICEUn solo dispositivo
REGIONUna región configurada

CrossingObject

Clase de objeto para getThresholdCrossingCounts.

ValorObjeto
HUMANPersonas
VEHICLEVehículos
FACERostros
LPRMatrículas
POSEDetecciones de pose
CLIP_EMBEDCoincidencias por embedding visual
UNKNOWNSin clasificar

Casos de uso

  • Paneles de tráfico peatonal: grafica conteos horarios o diarios de PEOPLE por ubicación con getCountReportV2 para comparar tiendas o seguir tendencias en el tiempo.
  • Monitoreo de ocupación: grafica los intervalos de getOccupancyCountsV2 para mostrar la ocupación a lo largo del día y compararla con periodos anteriores.
  • Conteo de entradas y carriles: usa getThresholdCrossingCounts con crossingObject: "HUMAN" o "VEHICLE" para contar personas por una puerta o vehículos por un carril.
  • Informes programados: ejecuta /api/export/countReports con un cron y coloca el CSV en una herramienta de BI o un almacén de datos para informes semanales y mensuales.

Avanzado: analíticas con AI Scene Query

Rhombus también ofrece Scene Query, una función de IA que cuenta eventos personalizados definidos en lenguaje natural (por ejemplo, "montacargas sin señalador"). Scene Query se configura mediante los endpoints /api/scenequery/* y se informa a través de /api/report/getCustomEventsReport. Es una capacidad distinta y con licencia, más que parte del flujo de trabajo principal de informes anterior: trátala como una extensión opcional cuando los tipos de informe estándar no capturen lo que necesitas medir.

Solución de problemas

timeSeriesDataPoints vacío o conteos todos en cero

Confirma que el dispositivo realmente produce la analítica que solicitaste: una cámara sin conteo de personas habilitado no devuelve datos de PEOPLE. Verifica también que tu rango de tiempo esté en milisegundos epoch (no segundos) y que el par scope/uuid sea correcto.

Los segmentos están desfasados respecto a la hora local

Establece el campo timeZone en la zona IANA correspondiente (por ejemplo, America/Chicago). Sin él, los límites de los segmentos y dateLocal caen en UTC.

La solicitud de exportación es rechazada

La exportación a CSV requiere el permiso REPORT_ADMINISTRATION. Revisa los permisos de la clave de API en la Consola de Rhombus y recuerda que el cuerpo de la exportación usa un único campo type en lugar del arreglo types que usa getCountReportV2.

La respuesta de exportación parece JSON corrupto

Los endpoints de exportación devuelven text/csv, no JSON. Lee la respuesta como texto o escríbela en un archivo en lugar de llamar a .json().

Próximos pasos