> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoreo y filtrado de eventos de WebSocket

> Suscríbete a eventos de WebSocket en tiempo real de Rhombus — filtra y procesa alertas de políticas, cambios de estado de dispositivos, detección de movimiento y eventos de control de acceso.

<Note>
  Esta página fue traducida automáticamente. Si encuentra errores o tiene sugerencias, [contáctenos](mailto:support@rhombus.com).
</Note>

El flujo de eventos de WebSocket de Rhombus entrega notificaciones en tiempo real sobre todo lo que ocurre en tu organización. Esta guía cubre la estructura de los eventos, los tipos de entidad disponibles y los patrones para filtrar y procesar eventos.

## Tópico de eventos

Todos los eventos de la organización se publican en un único tópico:

```text theme={null}
/topic/change/{orgUuid}
```

Cada operación de creación, actualización y eliminación en tu organización de Rhombus emite un evento en este tópico.

## Estructura de la carga útil del evento

Cada frame MESSAGE contiene un cuerpo JSON con los siguientes campos:

```json theme={null}
{
  "entity": "POLICY_ALERT",
  "entityUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "update": { },
  "type": "CREATE",
  "deviceUuid": "d1e2f3a4-b5c6-7890-abcd-ef1234567890",
  "targetUsers": [],
  "targetRoles": [],
  "subLocationsHierarchyKey": ""
}
```

### Campos principales

| Campo                      | Tipo   | Descripción                                                                                                                                                                       |
| -------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity`                   | string | El tipo de entidad que cambió                                                                                                                                                     |
| `entityUuid`               | string | Identificador único de la entidad específica                                                                                                                                      |
| `update`                   | object | Carga útil específica de la entidad. Su contenido varía según el tipo de entidad y no es un esquema fijo — inspecciona las claves presentes para cada tipo de entidad que manejes |
| `type`                     | string | Tipo de cambio: `CREATE`, `UPDATE`, `DELETE` o `REFRESH`                                                                                                                          |
| `deviceUuid`               | string | UUID del dispositivo asociado (cuando corresponda)                                                                                                                                |
| `targetUsers`              | array  | Usuarios a los que se dirige este cambio                                                                                                                                          |
| `targetRoles`              | array  | Roles a los que se dirige este cambio                                                                                                                                             |
| `subLocationsHierarchyKey` | string | Clave de jerarquía de sububicaciones para el cambio                                                                                                                               |

<Note>
  El detalle específico del evento (por ejemplo, los pormenores de una alerta de política) reside dentro del objeto `update`. Su forma depende del tipo de `entity`, así que lee las claves presentes en `update` en lugar de asumir una estructura fija.
</Note>

## Tipos de cambio

| Tipo      | Descripción                                                                                                                                                                                         | Ejemplo                                                                                     |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `CREATE`  | Se creó una nueva entidad                                                                                                                                                                           | Nueva alerta de política activada                                                           |
| `UPDATE`  | Se modificó una entidad existente                                                                                                                                                                   | Cambió el estado de la alerta                                                               |
| `DELETE`  | Se eliminó una entidad                                                                                                                                                                              | Alerta descartada o resuelta                                                                |
| `REFRESH` | Una señal genérica de "vuelve a obtener esta entidad" sin semántica de cambio específica. Es el valor predeterminado cuando un productor no define un tipo más específico, así que espera recibirlo | La entidad cambió de una forma que no es una creación, actualización o eliminación discreta |

## Tipos de entidad

El campo `entity` indica qué tipo de objeto cambió. Los tipos de entidad comunes incluyen:

| Entidad        | Descripción                                  |
| -------------- | -------------------------------------------- |
| `POLICY_ALERT` | Alerta de violación de política de seguridad |
| `DEVICE`       | Cambió un dispositivo: cámara, sensor o NVR  |

<Note>
  Los tipos de entidad disponibles dependen de los dispositivos y las políticas configurados en tu organización. Suscríbete a `/topic/change/{orgUuid}` y registra el campo `entity` de cada evento para descubrir todos los tipos de evento disponibles.
</Note>

<Tip>
  Comienza filtrando los eventos `POLICY_ALERT`, que son el caso de uso más común. Todos los tipos de entidad se entregan en el mismo tópico `/topic/change/{orgUuid}` — no hay un filtro de entidad del lado del servidor en la suscripción, así que filtra del lado del cliente inspeccionando el campo `entity` en tu manejador de mensajes e ignorando los tipos que no necesites.
</Tip>

## Inspección de alertas de política

Cuando un evento tiene `entity: "POLICY_ALERT"`, el detalle específico de la alerta se transporta dentro del objeto `update`. La forma de `update` depende del tipo de entidad y no es un esquema público fijo, así que inspecciona las claves presentes en cada alerta en lugar de asumir campos particulares:

```python theme={null}
def inspect_alert(payload):
    if payload.get("entity") != "POLICY_ALERT":
        return
    update = payload.get("update", {})
    # `update` is entity-specific. Discover its keys at runtime
    # instead of assuming a fixed structure.
    print(f"Alert {payload.get('entityUuid')} update keys: {list(update.keys())}")
```

<Tip>
  Para conocer la estructura de `update` de los tipos de entidad que te interesan, conéctate, suscríbete y registra algunos eventos reales. Las claves presentes dependen del tipo de entidad y pueden evolucionar, así que trata `update` de forma defensiva.
</Tip>

## Filtrado de eventos

### Por tipo de entidad

Filtra tipos de evento específicos para reducir el ruido:

```python theme={null}
def handle_message(payload):
    entity = payload.get("entity")

    if entity == "POLICY_ALERT":
        handle_alert(payload)
    elif entity == "DEVICE":
        handle_device_change(payload)
    else:
        # Log or ignore other entity types
        pass
```

### Por tipo de cambio

Reacciona de forma diferente según si un evento fue creado, actualizado o eliminado:

```python theme={null}
def handle_alert(payload):
    change_type = payload.get("type")

    if change_type == "CREATE":
        # New alert - send notification
        send_notification(payload)
    elif change_type == "UPDATE":
        # Alert updated - refresh dashboard
        refresh_dashboard(payload)
    elif change_type == "DELETE":
        # Alert cleared - close ticket
        close_ticket(payload)
```

### Por dispositivo

Filtra los eventos de una cámara o sensor específico:

```python theme={null}
WATCHED_DEVICES = {
    "camera-uuid-lobby",
    "camera-uuid-parking-lot",
}

def handle_message(payload):
    device_uuid = payload.get("deviceUuid")
    if device_uuid in WATCHED_DEVICES:
        process_event(payload)
```

### Por entidad y tipo de cambio

Reacciona a tipos específicos de eventos de seguridad combinando los campos `entity` y `type`:

```python theme={null}
def handle_alert(payload):
    if payload.get("entity") == "POLICY_ALERT" and payload.get("type") == "CREATE":
        # A new policy alert was raised. Alert-specific detail is in `update`;
        # inspect its keys to decide how to route the notification.
        send_urgent_notification(payload)
```

## Enriquecimiento de eventos con datos de la API REST

Los eventos de WebSocket contienen datos mínimos por eficiencia. Usa la API REST para obtener detalles adicionales cuando sea necesario:

### Obtener el nombre de la cámara a partir del UUID del dispositivo

```python theme={null}
import requests

def get_camera_name(api_token, device_uuid):
    """Fetch camera name for display purposes."""
    response = requests.post(
        "https://api2.rhombussystems.com/api/camera/getMinimalCameraStateList",
        headers={
            "x-auth-apikey": api_token,
            "Content-Type": "application/json"
        },
        json={}
    )
    cameras = response.json().get("cameraStates", [])
    for camera in cameras:
        if camera.get("uuid") == device_uuid:
            return camera.get("name", "Unknown Camera")
    return "Unknown Camera"
```

### Obtener detalles de la alerta

```python theme={null}
def get_alert_details(api_token, alert_uuid):
    """Fetch full policy-alert details from the REST API."""
    response = requests.post(
        "https://api2.rhombussystems.com/api/event/getPolicyAlertDetails",
        headers={
            "x-auth-apikey": api_token,
            "Content-Type": "application/json"
        },
        json={"policyAlertUuid": alert_uuid}
    )
    return response.json().get("policyAlert")
```

<Note>
  Almacena en caché los nombres de las cámaras localmente para evitar llamadas excesivas a la API REST. Los nombres de las cámaras cambian con poca frecuencia, así que una caché con un TTL de 5 minutos funciona bien.
</Note>

## Formatos de salida

### Visualización de alerta con formato

```python theme={null}
def display_alert(payload, camera_name=""):
    entity = payload.get("entity", "UNKNOWN")
    change = payload.get("type", "UNKNOWN")
    update = payload.get("update", {})

    print(f"{change} {entity}  camera={camera_name}")
    print(f"  device={payload.get('deviceUuid', 'N/A')}")
    print(f"  uuid={payload.get('entityUuid', 'N/A')}")
    # `update` is entity-specific; print its keys to discover available detail.
    if update:
        print(f"  update keys={list(update.keys())}")
    print()
```

### Salida JSON sin procesar

Para canalizar a otras herramientas o sistemas de registro:

```python theme={null}
import json

def output_json(payload):
    print(json.dumps(payload, indent=2))
```

## Patrones de integración

### Relé de webhook

Reenvía los eventos de Rhombus a tu propio endpoint de webhook:

```python theme={null}
import requests

WEBHOOK_URL = "https://your-server.com/webhooks/rhombus"

def relay_to_webhook(payload):
    try:
        requests.post(WEBHOOK_URL, json=payload, timeout=5)
    except requests.RequestException as e:
        print(f"Webhook relay failed: {e}")
```

### Notificaciones de Slack

Envía alertas de alta prioridad a un canal de Slack:

```python theme={null}
def send_slack_alert(payload, webhook_url):
    entity = payload.get("entity", "UNKNOWN")
    change = payload.get("type", "UNKNOWN")
    message = {
        "text": f":rotating_light: *Security Alert*\n"
                f"{change} {entity}\n"
                f"Entity: {payload.get('entityUuid', 'N/A')}  "
                f"Device: {payload.get('deviceUuid', 'N/A')}"
    }
    try:
        requests.post(webhook_url, json=message, timeout=5)
    except requests.RequestException as e:
        print(f"Slack notification failed: {e}")
```

### Registro en base de datos

Persiste los eventos para análisis histórico:

```python theme={null}
import sqlite3
import json

def log_event(db_path, payload):
    conn = sqlite3.connect(db_path)
    conn.execute("""
        INSERT INTO events (entity, entity_uuid, change_type, device_uuid, payload)
        VALUES (?, ?, ?, ?, ?)
    """, (
        payload.get("entity"),
        payload.get("entityUuid"),
        payload.get("type"),
        payload.get("deviceUuid"),
        json.dumps(payload)
    ))
    conn.commit()
    conn.close()
```
