> ## Í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.

# Solución de problemas de WebSocket

> Diagnostica y resuelve problemas comunes del WebSocket de Rhombus: fallos de conexión, errores de STOMP, heartbeats perdidos, problemas de autenticación y eventos descartados.

> **Note**: Esta página se tradujo automáticamente. Si encuentras errores o tienes sugerencias, [escríbenos](mailto:support@rhombus.com).

Esta guía cubre los problemas comunes al trabajar con conexiones WebSocket de Rhombus y cómo resolverlos.

## Problemas de conexión

### No se puede conectar (conexión rechazada)

**Síntomas**: el handshake de WebSocket falla de inmediato con un error de conexión.

**Causas posibles**:

- Un firewall bloquea las conexiones salientes en el puerto 8443
- Hostname incorrecto

**Soluciones**:

1. Verifica el acceso saliente a `ws.rhombussystems.com` en el puerto `8443`:
   ```bash
   # Test connectivity
   curl -v https://ws.rhombussystems.com:8443/websocket

   # Test TCP connectivity directly
   nc -zv ws.rhombussystems.com 8443
   ```
2. Comprueba que tu red/firewall permita WSS saliente en el puerto 8443
3. Si estás detrás de un proxy corporativo, asegúrate de que se permitan las solicitudes de actualización (upgrade) de WebSocket

### HTTP 401 Unauthorized

**Síntomas**: el handshake de WebSocket falla con HTTP 401. El `errorCode` del cuerpo JSON indica el motivo.

**Causas posibles**:

- `UNAUTHENTICATED`: no llegó ninguna credencial al servidor. Falta `x-auth-scheme` o está mal escrito, la clave de API o el token de OAuth se enviaron como parámetro de query (solo un token federado puede ir ahí), o el esquema es de certificado (`api`, `partner-api`), que esta conexión no acepta
- `INVALID_CREDENTIAL`: la clave o el token están mal formados, son desconocidos (por ejemplo, una clave de API eliminada) o son de la otra región
- `CREDENTIAL_EXPIRED` o `CREDENTIAL_REVOKED`: la clave o el token expiraron, o se revocaron (por ejemplo, un token de OAuth cuyo grant se revocó). Un token federado también deja de funcionar cuando se elimina o revoca la clave, el grant de OAuth o la sesión que lo generó
- `CERTIFICATE_MISMATCH`: una clave de certificado enviada con `api-token`

**Soluciones**:

1. Envía el esquema y la credencial como indica [Autenticación de WebSocket](https://developer.rhombus.com/es/websocket/authentication#parámetros-de-autenticación): `x-auth-scheme=api-token` con la clave en el encabezado `x-auth-apikey`, `Authorization: Bearer <token>` para un access token de OAuth, o `x-auth-scheme=federated-token&x-auth-ft=<token>` para un token federado
2. Verifica que la clave funcione con la API REST de la misma región:
   ```bash
   curl -X POST https://api2.rhombussystems.com/api/org/getOrgV2 \
     -H "x-auth-scheme: api-token" \
     -H "x-auth-apikey: YOUR_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{}'
   ```
3. Reemplaza una credencial expirada o revocada: crea una clave nueva, renueva el token de OAuth o genera un token federado nuevo

### HTTP 403 Forbidden

**Síntomas**: el handshake de WebSocket falla con HTTP 403. La credencial es válida pero no está permitida en esta conexión; el `errorCode` del cuerpo JSON indica el motivo.

**Causas posibles**:

- `PERMISSION_REQUIRED`: una credencial de partner sin el encabezado `x-auth-org`, o un access token de OAuth cuyo grant no incluye el scope `read` (la respuesta también incluye `WWW-Authenticate: Bearer error="insufficient_scope", scope="read"`)
- `PARTNER_CLIENT_ACCESS_DENIED`: una credencial de partner sin autorización para la organización indicada en `x-auth-org`
- `DOMAIN_NOT_ALLOWED`: un token federado generado con `domain`, abierto desde una página cuyo `Origin` es otro origen

**Soluciones**:

1. Si usas una credencial de partner, envía el UUID de la organización destino en el **encabezado** `x-auth-org` (el servidor lee `x-auth-org` de los encabezados de la solicitud, no de la cadena de query):

```text
   Encabezado: x-auth-org: CLIENT_ORG_UUID
   URL:        wss://ws.rhombussystems.com:8443/websocket?x-auth-scheme=api-token
```

2. En una app OAuth, solicita el scope `read` cuando el usuario la autorice
3. Genera los tokens federados con el origen exacto de tu página como `domain` (esquema, host y puerto), o sin `domain`

### La autenticación basada en certificados no funciona

**Síntomas**: la conexión falla al usar una clave de certificado mTLS: 401 `UNAUTHENTICATED` con el esquema `api`, o 401 `CERTIFICATE_MISMATCH` cuando la clave de certificado se envía con `api-token`.

**Causa**: el WebSocket de eventos no acepta claves de certificado.

**Solución**: conéctate con una clave de API estándar (Tipo de autenticación **Token de API**), un access token de OAuth o un token federado. Las claves de certificado funcionan en la API REST.

## Problemas del protocolo STOMP

### El frame CONNECTED nunca se recibe

**Síntomas**: el WebSocket se conecta correctamente, pero no se recibe ninguna respuesta STOMP `CONNECTED` después de enviar `CONNECT`.

**Causas posibles**:

- Frame STOMP `CONNECT` mal formado
- Falta el terminador nulo (`\x00`)
- Valor de `accept-version` incorrecto

**Soluciones**:

1. Verifica que tu frame incluya el terminador de byte nulo:
   ```python
   # Correct
   frame = "CONNECT\naccept-version:1.2\nheart-beat:10000,10000\n\n\x00"

   # Wrong - missing \x00
   frame = "CONNECT\naccept-version:1.2\nheart-beat:10000,10000\n\n"
   ```
2. Asegúrate de que haya una línea vacía (`\n\n`) entre los encabezados y el cuerpo
3. Usa `accept-version:1.2` (no `1.0` ni `1.1`)

### No se reciben mensajes después de suscribirse

**Síntomas**: la conexión y la suscripción se realizan correctamente, pero no llegan frames MESSAGE.

**Causas posibles**:

- El rol de la credencial no cubre los dispositivos o ubicaciones que generan los eventos. Los eventos fuera del rol se descartan sin error, incluidas las alertas de políticas: una alerta solo se entrega a un rol que tiene acceso a su dispositivo o ubicación.
- No ocurren eventos en la organización
- Frame de suscripción mal formado

Un UUID de organización incorrecto no produce silencio: al suscribirte al tópico de otra organización recibes un frame STOMP `ERROR` y el servidor cierra el socket con el código `1002`.

**Soluciones**:

1. Revisa el rol en la Consola de Rhombus (para una clave de API, el rol de la clave; para un token de OAuth, el rol del usuario; para un token federado, el rol de la credencial que lo generó): un rol con acceso completo recibe todos los eventos de la organización. Consulta [Qué recibe una conexión](https://developer.rhombus.com/es/websocket/authentication#qué-recibe-una-conexión).
2. Verifica el UUID de tu organización llamando a la API REST:
   ```bash
   curl -X POST https://api2.rhombussystems.com/api/org/getOrgV2 \
     -H "x-auth-scheme: api-token" \
     -H "x-auth-apikey: YOUR_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{}'
   ```
3. Dispara un evento de prueba (por ejemplo, ajusta una configuración de cámara) para confirmar que el flujo está activo
4. Verifica que el formato del tópico sea exactamente `/topic/change/{orgUuid}` sin barras finales ni espacios

## Problemas de estabilidad de la conexión

### La conexión se cae cada \~30 segundos

**Síntomas**: la conexión WebSocket se cierra después de aproximadamente 30 segundos de inactividad.

**Causa**: no se están enviando heartbeats.

**Solución**: implementa el emisor de heartbeats que envía `\n` cada 10 segundos:

```python
import threading

def heartbeat_sender(ws, stop_event):
    while not stop_event.is_set():
        ws.send("\n")
        stop_event.wait(10)

stop = threading.Event()
thread = threading.Thread(target=heartbeat_sender, args=(ws, stop), daemon=True)
thread.start()
```

### La conexión se cierra con el código 1008

**Síntomas**: el servidor envía un frame STOMP `ERROR` y cierra la conexión con el código `1008`.

**Causa**: la credencial se eliminó o revocó, o su rol cambió, mientras la conexión estaba abierta. El servidor vuelve a verificar la credencial aproximadamente una vez por minuto, así que esto ocurre en 60 segundos o menos después del cambio. Revocar un grant de OAuth, o la clave o la sesión que generó un token federado, tiene el mismo efecto.

**Solución**: revisa la credencial antes de reconectarte. Después de un cambio de rol, una conexión nueva aplica el nuevo rol; después de una eliminación o revocación, todo handshake con esa credencial falla con 401, así que reemplázala en lugar de reintentar.

### La conexión se cae de forma intermitente

**Síntomas**: la conexión funciona durante un tiempo y luego se cae de forma impredecible.

**Causas posibles**:

- Inestabilidad de la red
- Mantenimiento del lado del servidor
- Timeout del balanceador de carga

**Soluciones**:

1. Implementa la reconexión automática con backoff:
   ```python
   while True:
       try:
           run_websocket_monitor()
       except ConnectionError:
           print("Reconnecting in 5 seconds...")
           time.sleep(5)
   ```
2. Registra los motivos de desconexión para identificar patrones
3. Monitorea la recepción de heartbeats para detectar conexiones muertas de forma proactiva

### Alto uso de memoria con el tiempo

**Síntomas**: la memoria de la aplicación crece de forma constante mientras está conectada.

**Causas posibles**:

- Los eventos se acumulan en una cola sin límite
- No se procesan los mensajes con suficiente rapidez

**Soluciones**:

1. Usa buffers de mensajes con límite:
   ```python
   # Use a bounded queue
   from queue import Queue
   event_queue = Queue(maxsize=1000)
   ```
2. Procesa los eventos de forma asíncrona para evitar la contrapresión (backpressure)
3. Descarta o registra los eventos si la cola de procesamiento está llena

## Problemas de procesamiento de eventos

### Eventos faltantes

**Síntomas**: algunos eventos que aparecen en la consola de Rhombus no aparecen en el flujo de WebSocket.

**Causas posibles**:

- El rol de la credencial no cubre esos dispositivos o ubicaciones (los eventos fuera del rol se descartan sin error)
- El rol es limitado y el tipo de entidad no tiene verificación de acceso: esos tipos solo llegan a roles de acceso completo
- El filtrado de eventos es demasiado agresivo
- Una breve desconexión causó la pérdida de eventos
- El evento ocurrió antes de que se estableciera la suscripción

**Soluciones**:

1. Habilita temporalmente todos los eventos para verificar el flujo:
   ```python
   # Don't filter by entity type
   if frame["command"] == "MESSAGE":
       print(json.loads(frame["body"]))
   ```
2. Los eventos de WebSocket son solo en tiempo real. Para eventos históricos, usa la API REST
3. Asegúrate de que SUBSCRIBE se envíe antes de esperar eventos

### JSON mal formado en el cuerpo del evento

**Síntomas**: `json.loads()` falla con el cuerpo de MESSAGE.

**Causas posibles**:

- El parser de frames no separa correctamente el cuerpo de los encabezados
- Bytes nulos o espacios en blanco adicionales en el cuerpo

**Soluciones**:

1. Elimina los bytes nulos antes de parsear:
   ```python
   body = frame["body"].strip("\x00").strip()
   payload = json.loads(body)
   ```
2. Verifica que tu parser de frames divida en `\n\n` correctamente (solo la primera ocurrencia)

## Herramientas de depuración

### Habilitar el registro de frames sin procesar

Agrega registro (logging) para ver exactamente qué se envía y se recibe:

```python
import logging

logging.basicConfig(level=logging.DEBUG)

# In your message loop:
raw = ws.recv()
logging.debug(f"Received: {repr(raw)}")
```

### Probar con websocat

Usa `wscat` para interactuar manualmente con el endpoint de WebSocket:

```bash
# Install
npm install -g wscat

# Connect (note: wscat does not support custom headers natively,
# so use a tool like websocat for full header support)
websocat -H "x-auth-apikey: YOUR_TOKEN" \
  "wss://ws.rhombussystems.com:8443/websocket?x-auth-scheme=api-token"

# Then manually type STOMP frames:
CONNECT
accept-version:1.2
heart-beat:10000,10000

^@
```

> **Note**: `^@` representa el byte nulo (`\x00`). En la mayoría de las terminales, escribe `Ctrl+@` o `Ctrl+Shift+2` para producirlo.

### Monitor de la CLI de Rhombus

Usa la [CLI de Rhombus](https://developer.rhombus.com/es/rhombus-cli) para verificar que tu cuenta y el endpoint de WebSocket funcionen:

```bash
# Install the CLI (macOS/Linux)
brew install RhombusSystems/tap/rhombus

# Authenticate
rhombus login

# Test WebSocket monitoring
rhombus monitor --all-events --json
```

Si la CLI funciona pero tu código no, compara los parámetros de conexión que usa tu código con el comportamiento de la CLI. Consulta la [documentación de la CLI de Rhombus](https://developer.rhombus.com/es/rhombus-cli) para conocer todos los detalles de instalación y uso.

## Cómo obtener ayuda

Si has probado los pasos anteriores y sigues experimentando problemas:

1. Consulta el [registro de cambios](https://developer.rhombus.com/es/changelog) para ver los cambios recientes
2. Contacta al Soporte de Rhombus en <support@rhombus.com> con:
   - El UUID de tu organización
   - El mensaje de error o el código de estado HTTP
   - La marca de tiempo del intento de conexión fallido
   - Tu lenguaje de cliente y la versión de la biblioteca de WebSocket
