167 lines
5.3 KiB
Markdown
167 lines
5.3 KiB
Markdown
# Aether API V3 WebSocket Integration Guide
|
|
|
|
This guide explains how to implement real-time communication using the **Aether API V3 WebSocket** protocol. V3 introduces granular routing, strict message schemas, and improved multi-tenant isolation compared to previous versions.
|
|
|
|
---
|
|
|
|
## 1. Key Improvements (V2 vs V3)
|
|
|
|
| Feature | WebSocket V2 (Legacy) | WebSocket V3 (Modern) |
|
|
| :--- | :--- | :--- |
|
|
| **URL Prefix** | `/ws/` or `/ws_redis/` | `/v3/ws/` |
|
|
| **Routing** | **Global**: Every client receives every message. | **Granular**: Redis filters messages before sending. |
|
|
| **Performance**| Low efficiency at scale (Python filtering). | High efficiency (Redis native pub/sub). |
|
|
| **Schema** | Loose JSON objects. | Strict Pydantic-validated models. |
|
|
| **Presence** | None / Manual. | Automatic Redis-backed presence sets. |
|
|
|
|
---
|
|
|
|
## 2. Connection Strategy
|
|
|
|
### A. Endpoint URL
|
|
The V3 WebSocket path requires both a `group_id` and a `client_id` (using **Vision ID** random strings).
|
|
|
|
```text
|
|
ws://[api_domain]/v3/ws/group/{group_id}/client/{client_id}
|
|
```
|
|
|
|
### B. Connection Example (TypeScript)
|
|
```ts
|
|
const group_id = "group_abc123"; // Random ID
|
|
const client_id = "device_xyz789"; // Random ID
|
|
const ws_url = `ws://api.oneskyit.com/v3/ws/group/${group_id}/client/${client_id}`;
|
|
|
|
const socket = new WebSocket(ws_url);
|
|
|
|
socket.onopen = () => {
|
|
console.log("Connected to Aether WS V3");
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 3. The V3 Message Schema
|
|
|
|
All messages sent and received over V3 must follow the standardized **WS_Message_V3** structure.
|
|
|
|
### Message Fields
|
|
| Field | Type | Required | Description |
|
|
| :--- | :--- | :--- | :--- |
|
|
| `version` | string | Auto | Always `"3"`. |
|
|
| `msg_type` | string | Yes | `'msg'`, `'cmd'`, `'heartbeat'`, `'presence'` |
|
|
| `target` | string | Yes | `'direct'`, `'group'`, `'broadcast'`, `'echo'` |
|
|
| `from_id` | string | No* | Client ID of sender (Auto-filled by server if omitted). |
|
|
| `to_id` | string | No | Target Client ID (Required for `target: 'direct'`). |
|
|
| `group_id` | string | No* | Target Group ID (Auto-filled by server if omitted). |
|
|
| `cmd` | string | No | Specific action keyword (e.g., `'RELOAD'`). |
|
|
| `msg` | string | No | Human-readable text content. |
|
|
| `payload` | object | No | Flexible key-value data. |
|
|
| `sent_at` | string | Auto | ISO 8601 Timestamp. |
|
|
|
|
---
|
|
|
|
## 4. Message Targeting Logic
|
|
|
|
V3 uses the `target` field to determine which Redis channel to use, ensuring only the intended recipients receive the data.
|
|
|
|
### A. Group Broadcast
|
|
Sends the message to every client connected to the same `group_id`.
|
|
```json
|
|
{
|
|
"msg_type": "msg",
|
|
"target": "group",
|
|
"msg": "Hello team!"
|
|
}
|
|
```
|
|
|
|
### B. Direct Message (DM)
|
|
Sends the message to one specific client ID, regardless of their group.
|
|
```json
|
|
{
|
|
"msg_type": "msg",
|
|
"target": "direct",
|
|
"to_id": "target_client_random_id",
|
|
"msg": "Private message just for you."
|
|
}
|
|
```
|
|
|
|
### C. System Broadcast
|
|
Sends the message to **every** connected client on the platform (use sparingly).
|
|
```json
|
|
{
|
|
"msg_type": "cmd",
|
|
"target": "broadcast",
|
|
"cmd": "MAINTENANCE_WARNING"
|
|
}
|
|
```
|
|
|
|
### D. Echo
|
|
Sends the message back only to the sender (useful for testing round-trip latency).
|
|
```json
|
|
{
|
|
"msg_type": "msg",
|
|
"target": "echo",
|
|
"msg": "Ping!"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Specialized Message Types
|
|
|
|
### Commands (`cmd`)
|
|
Used for remote control or orchestration.
|
|
```json
|
|
{
|
|
"msg_type": "cmd",
|
|
"target": "group",
|
|
"cmd": "RELOAD_UI",
|
|
"payload": { "force": true }
|
|
}
|
|
```
|
|
|
|
### Heartbeats (`heartbeat`)
|
|
Keep the connection alive and refresh presence in the backend. Should be sent every 30-60 seconds.
|
|
```json
|
|
{
|
|
"msg_type": "heartbeat",
|
|
"target": "echo"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Infrastructure Requirements (Nginx)
|
|
|
|
Unlike standard REST endpoints, WebSockets require explicit "Upgrade" handling in the Nginx gateway. If you are deploying to a new server, ensure the following block is present in your Nginx configuration:
|
|
|
|
```nginx
|
|
location /v3/ws {
|
|
proxy_pass http://fastapi_backend;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Host $http_host;
|
|
proxy_read_timeout 2100s; # Match your app's max heartbeat/session time
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Common Pitfalls & Troubleshooting
|
|
|
|
- **HTTP 404 Errors**: This almost always means Nginx is missing the `location /v3/ws` block and is trying to serve the request as a static file from the disk.
|
|
- **HTTP 400 Errors**: Check your `Host` header. Nginx routes requests based on the `server_name` directive. If you connect to an IP or a non-standard hostname (like `localhost`), ensure it is explicitly listed in your Nginx config.
|
|
- **Connection Drops**: If the connection drops exactly after 60 seconds, check your Nginx `proxy_read_timeout`. It should be set high (e.g., `2100s`) to allow for long-lived WebSocket sessions.
|
|
|
|
---
|
|
|
|
## 8. Migration Guide (V2 to V3)
|
|
|
|
If you are upgrading from the legacy V2 WebSocket (`/ws/group/...`):
|
|
|
|
1. **Change the URL**: Prepend `/v3/` to your WebSocket path.
|
|
2. **Wrap your JSON**: In V2, you might have sent `{"msg": "hi"}`. In V3, this must be `{"msg_type": "msg", "target": "group", "msg": "hi"}`.
|
|
3. **Use Vision IDs**: Ensure all IDs passed in the path and `to_id` fields are the random string IDs (`id_random`), not database integers.
|
|
4. **Listen for `msg_type`**: Update your frontend handlers to switch logic based on the `msg_type` field instead of proprietary keys.
|