> ## Índice de la documentación
> Consulta el índice completo de la documentación en: https://developer.rhombus.com/llms.txt
> Úsalo para descubrir todas las páginas disponibles antes de seguir explorando.

# 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 se tradujo automáticamente. Si encuentras errores o tienes sugerencias, [escríbenos](mailto:support@rhombus.com).

El flujo de eventos de WebSocket de Rhombus entrega notificaciones en tiempo real sobre la actividad de tu organización que puede ver el rol de tu credencial. 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
/topic/change/{orgUuid}
```

Los cambios en muchos tipos de objetos de tu organización emiten un evento en este tópico, desde nuevas alertas de políticas hasta el estado de las cámaras y los componentes de puertas; la [referencia de eventos](https://developer.rhombus.com/es/websocket/event-reference) los enumera. Una conexión recibe los eventos que cubre el rol de su credencial, incluidas las alertas de políticas; los eventos de otros dispositivos y ubicaciones se descartan sin error (consulta [Qué recibe una conexión](https://developer.rhombus.com/es/websocket/authentication#qué-recibe-una-conexión)).

## Estructura de la carga útil del evento

Cada trama `MESSAGE` lleva un cuerpo JSON. Una nueva alerta de política se ve así (abreviada):

```json
{
  "entity": "POLICY_ALERT",
  "type": "CREATE",
  "update": {
    "uuid": "Xq3vT1bKQ2m8c9Zr0aLwYg",
    "type": "POLICY_ALERT_V2",
    "deviceUuid": "ItkwWv1qT7Wy8-pY8KDesw",
    "locationUuid": "Rk2pQ7yLT0qX4b1nVt8sJw",
    "timestampMs": 1791367200000,
    "policyAlertTriggers": ["MOTION_HUMAN"],
    "textDescription": "Human detected at Front Lobby"
  }
}
```

### Campos principales

| Campo                      | Tipo   | Descripción                                                                                                   |
| -------------------------- | ------ | ------------------------------------------------------------------------------------------------------------- |
| `entity`                   | string | El tipo de objeto que cambió                                                                                  |
| `type`                     | string | `CREATE`, `UPDATE`, `DELETE` o `REFRESH`                                                                      |
| `entityUuid`               | string | El objeto que cambió. No aparece en una nueva alerta de política: usa `update.uuid`                           |
| `update`                   | object | El nuevo estado del objeto o los campos que cambiaron; falta en muchos mensajes. Su forma depende de `entity` |
| `deviceUuid`               | string | El dispositivo involucrado, en los pocos mensajes que lo incluyen                                             |
| `subLocationsHierarchyKey` | string | La ruta de sububicaciones, en algunos mensajes de monitoreo de alarmas                                        |

La organización no está en el cuerpo: está en el destino y en el encabezado `ORG_UUID` de la trama. La [referencia de eventos](https://developer.rhombus.com/es/websocket/event-reference) documenta cada campo, incluida la alerta de política completa.

## Tipos de cambio

| Tipo      | Significado                                              | Ejemplo                               |
| --------- | -------------------------------------------------------- | ------------------------------------- |
| `CREATE`  | Algo nuevo, enviado con el objeto completo               | Una nueva alerta de política          |
| `UPDATE`  | Un objeto existente cambió                               | Cambió el estado de una cámara        |
| `REFRESH` | El objeto cambió; vuelve a leerlo si necesitas su estado | Un sensor de puerta informó un cambio |
| `DELETE`  | El objeto se eliminó, sin `update`                       | Una alerta se eliminó o se archivó    |

## Tipos de entidad

El campo `entity` indica qué tipo de objeto cambió. Los que más usan las integraciones:

| Entidad                                                             | Se envía cuando                                                                                                  |
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `POLICY_ALERT`                                                      | Se crea una alerta (`CREATE`, con la alerta), se vincula a un caso de amenaza (`UPDATE`) o se elimina (`DELETE`) |
| `CAMERA_STATE`, `AUDIO_STATE`                                       | Cambia el estado de una cámara o de un gateway de audio (`UPDATE`, con el nuevo estado)                          |
| `DOOR_STATE`, `CLIMATE_STATE`, `OCCUPANCY_STATE`, `PROXIMITY_STATE` | Un sensor informa un cambio (`REFRESH`, con los campos que cambiaron)                                            |
| `CAMERA`, `DOOR_SENSOR`, `CLIMATE_SENSOR`, `PROXIMITY_SENSOR`       | Se agrega un dispositivo (`REFRESH`)                                                                             |
| `ACCESS_CONTROLLED_DOOR`, `COMPONENT_*_SHADOW`                      | Cambia una puerta con control de acceso o uno de sus componentes                                                 |
| `POLICY`, `SCHEDULE`                                                | Se modifica una política o un horario                                                                            |
| `SAVED_CLIPS`                                                       | Cambia un clip guardado (`REFRESH`)                                                                              |

La [referencia de eventos](https://developer.rhombus.com/es/websocket/event-reference) enumera todos los tipos de entidad. Todos llegan al mismo destino y no hay filtro del lado del servidor, así que filtra por `entity` en tu controlador.

## Inspección de alertas de política

Una alerta nueva llega como `CREATE` con la alerta completa en `update`: su `uuid`, la cámara (`deviceUuid`), `timestampMs`, los `policyAlertTriggers` que se activaron y más. Se envía una sola vez, cuando la alerta se guarda por primera vez, así que los campos que Rhombus completa después (como las ubicaciones de clips y `finalized`) pueden tener todavía sus valores iniciales; obtén la alerta con la API REST cuando necesites su estado final.

```python
def inspect_alert(payload):
    if payload.get("entity") != "POLICY_ALERT" or payload.get("type") != "CREATE":
        return
    alert = payload["update"]
    print(alert["uuid"], alert.get("deviceUuid"), alert["timestampMs"], alert.get("policyAlertTriggers"))
```

## Filtrado de eventos

### Por tipo de entidad

```python
def handle_message(payload):
    entity = payload.get("entity")

    if entity == "POLICY_ALERT":
        handle_alert(payload)
    elif entity == "CAMERA_STATE":
        handle_camera_state(payload)
    else:
        pass  # ignora los tipos que no usas
```

### Por tipo de cambio

```python
def handle_alert(payload):
    change_type = payload.get("type")

    if change_type == "CREATE":
        send_notification(payload["update"])        # una alerta nueva
    elif change_type == "UPDATE":
        refresh_alert(payload["entityUuid"])        # vinculada a un caso de amenaza
    elif change_type == "DELETE":
        remove_alert(payload["entityUuid"])         # eliminada o archivada
```

No dependas de los mensajes `DELETE` para seguir cada alerta eliminada: están limitados a uno por organización cada 10 minutos.

### Por dispositivo

Dónde está el dispositivo depende de la entidad: una alerta de política lo indica en `update.deviceUuid`, y un mensaje de estado de dispositivo trata del dispositivo de `entityUuid`.

```python
WATCHED_DEVICES = {"ItkwWv1qT7Wy8-pY8KDesw"}

def device_of(payload):
    if payload.get("entity") == "POLICY_ALERT":
        return (payload.get("update") or {}).get("deviceUuid")
    return payload.get("deviceUuid") or payload.get("entityUuid")

def handle_message(payload):
    if device_of(payload) in WATCHED_DEVICES:
        process_event(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
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-scheme": "api-token",
            "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
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-scheme": "api-token",
            "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.

## Formatos de salida

### Visualización de alerta con formato

```python
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
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
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
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
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()
```
