351 lines
4.8 KiB
Markdown
351 lines
4.8 KiB
Markdown
# 实时网关协议草案
|
||
> 文档版本:v1.0
|
||
> 最后更新:2026-04-02 08:28:05
|
||
|
||
|
||
本文档描述 `realtime-gateway` 第一版协议草案,范围只覆盖 MVP。
|
||
|
||
---
|
||
|
||
## 1. 连接方式
|
||
|
||
- 协议:WebSocket
|
||
- 地址:`/ws`
|
||
- 编码:JSON
|
||
- 通信模式:客户端主动发消息,服务端返回状态或事件
|
||
|
||
---
|
||
|
||
## 2. 消息类型
|
||
|
||
客户端上行 `type`:
|
||
|
||
- `authenticate`
|
||
- `join_channel`
|
||
- `subscribe`
|
||
- `publish`
|
||
- `snapshot`
|
||
|
||
服务端下行 `type`:
|
||
|
||
- `welcome`
|
||
- `authenticated`
|
||
- `subscribed`
|
||
- `published`
|
||
- `snapshot`
|
||
- `event`
|
||
- `error`
|
||
|
||
---
|
||
|
||
## 3. 鉴权
|
||
|
||
### 3.1 authenticate
|
||
|
||
```json
|
||
{
|
||
"type": "authenticate",
|
||
"role": "producer",
|
||
"token": "dev-producer-token"
|
||
}
|
||
```
|
||
|
||
说明:
|
||
|
||
- `role` 可选值:`producer`、`consumer`、`controller`
|
||
- 第一版 `consumer` 可允许匿名,是否启用由配置控制
|
||
|
||
### 3.2 join_channel
|
||
|
||
```json
|
||
{
|
||
"type": "join_channel",
|
||
"role": "producer",
|
||
"channelId": "ch-xxxx",
|
||
"token": "producer-token"
|
||
}
|
||
```
|
||
|
||
说明:
|
||
|
||
- `channelId` 必填
|
||
- `token` 必须和 `channelId` 对应
|
||
- `role` 不同,使用的 token 也不同
|
||
- `producerToken`
|
||
- `consumerToken`
|
||
- `controllerToken`
|
||
|
||
---
|
||
|
||
## 4. 订阅
|
||
|
||
### 4.1 subscribe
|
||
|
||
```json
|
||
{
|
||
"type": "subscribe",
|
||
"subscriptions": [
|
||
{
|
||
"deviceId": "child-001",
|
||
"topic": "telemetry.location"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
支持字段:
|
||
|
||
- `channelId`
|
||
- `deviceId`
|
||
- `groupId`
|
||
- `topic`
|
||
|
||
第一版匹配规则:
|
||
|
||
- 非空字段必须全部匹配
|
||
- 空字段视为不过滤
|
||
|
||
---
|
||
|
||
## 5. 发布
|
||
|
||
### 5.1 publish
|
||
|
||
```json
|
||
{
|
||
"type": "publish",
|
||
"envelope": {
|
||
"schemaVersion": 1,
|
||
"messageId": "msg-001",
|
||
"timestamp": 1711267200000,
|
||
"topic": "telemetry.location",
|
||
"source": {
|
||
"kind": "producer",
|
||
"id": "watch-001",
|
||
"mode": "real"
|
||
},
|
||
"target": {
|
||
"channelId": "ch-xxxx",
|
||
"deviceId": "child-001",
|
||
"groupId": "class-a"
|
||
},
|
||
"payload": {
|
||
"lat": 31.2304,
|
||
"lng": 121.4737,
|
||
"speed": 1.2,
|
||
"bearing": 90,
|
||
"accuracy": 6,
|
||
"coordSystem": "GCJ02"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
说明:
|
||
|
||
- 只有 `producer` 和 `controller` 能发布
|
||
- 第一版不做复杂 schema 校验
|
||
- 第一版缓存键为 `channelId + deviceId`
|
||
- 如果连接已经通过 `join_channel` 加入通道,服务端会自动补全 `target.channelId`
|
||
|
||
---
|
||
|
||
## 6. 快照
|
||
|
||
### 6.1 snapshot
|
||
|
||
```json
|
||
{
|
||
"type": "snapshot",
|
||
"subscriptions": [
|
||
{
|
||
"channelId": "ch-xxxx",
|
||
"deviceId": "child-001"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
服务端返回:
|
||
|
||
```json
|
||
{
|
||
"type": "snapshot",
|
||
"sessionId": "sess-2",
|
||
"state": {
|
||
"schemaVersion": 1,
|
||
"timestamp": 1711267200000,
|
||
"topic": "telemetry.location",
|
||
"source": {
|
||
"kind": "producer",
|
||
"id": "watch-001",
|
||
"mode": "real"
|
||
},
|
||
"target": {
|
||
"deviceId": "child-001"
|
||
},
|
||
"payload": {
|
||
"lat": 31.2304,
|
||
"lng": 121.4737
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 服务端消息
|
||
|
||
### 7.1 welcome
|
||
|
||
```json
|
||
{
|
||
"type": "welcome",
|
||
"sessionId": "sess-1"
|
||
}
|
||
```
|
||
|
||
### 7.2 authenticated
|
||
|
||
```json
|
||
{
|
||
"type": "authenticated",
|
||
"sessionId": "sess-1"
|
||
}
|
||
```
|
||
|
||
### 7.3 subscribed
|
||
|
||
```json
|
||
{
|
||
"type": "subscribed",
|
||
"sessionId": "sess-1"
|
||
}
|
||
```
|
||
|
||
### 7.4 joined_channel
|
||
|
||
```json
|
||
{
|
||
"type": "joined_channel",
|
||
"sessionId": "sess-1",
|
||
"state": {
|
||
"channelId": "ch-xxxx",
|
||
"deliveryMode": "cache_latest"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7.5 published
|
||
|
||
```json
|
||
{
|
||
"type": "published",
|
||
"sessionId": "sess-1"
|
||
}
|
||
```
|
||
|
||
### 7.6 event
|
||
|
||
```json
|
||
{
|
||
"type": "event",
|
||
"envelope": {
|
||
"schemaVersion": 1,
|
||
"timestamp": 1711267200000,
|
||
"topic": "telemetry.location",
|
||
"source": {
|
||
"kind": "producer",
|
||
"id": "watch-001",
|
||
"mode": "real"
|
||
},
|
||
"target": {
|
||
"channelId": "ch-xxxx",
|
||
"deviceId": "child-001"
|
||
},
|
||
"payload": {
|
||
"lat": 31.2304,
|
||
"lng": 121.4737
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7.7 error
|
||
|
||
```json
|
||
{
|
||
"type": "error",
|
||
"error": "authentication failed"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 第一版约束
|
||
|
||
- 不做历史回放协议
|
||
- 不做压缩和二进制编码
|
||
- 不做批量发布
|
||
- 不做通配符 topic
|
||
- 不做持久会话
|
||
- 不做 ACK 队列
|
||
|
||
---
|
||
|
||
## 9. 管理接口
|
||
|
||
### 9.1 创建 channel
|
||
|
||
`POST /api/channel/create`
|
||
|
||
请求:
|
||
|
||
```json
|
||
{
|
||
"label": "debug-a",
|
||
"deliveryMode": "cache_latest",
|
||
"ttlSeconds": 28800
|
||
}
|
||
```
|
||
|
||
返回:
|
||
|
||
```json
|
||
{
|
||
"snapshot": {
|
||
"id": "ch-xxxx",
|
||
"label": "debug-a",
|
||
"deliveryMode": "cache_latest"
|
||
},
|
||
"producerToken": "....",
|
||
"consumerToken": "....",
|
||
"controllerToken": "...."
|
||
}
|
||
```
|
||
|
||
### 9.2 管理台读取接口
|
||
|
||
- `GET /api/admin/overview`
|
||
- `GET /api/admin/sessions`
|
||
- `GET /api/admin/latest`
|
||
- `GET /api/admin/channels`
|
||
- `GET /api/admin/traffic`
|
||
- `GET /api/admin/live`
|
||
|
||
---
|
||
|
||
## 10. 第二阶段预留
|
||
|
||
后续协议可以增加:
|
||
|
||
- `command`
|
||
- `batch_publish`
|
||
- `rule_event`
|
||
- `plugin_status`
|
||
- `replay_control`
|
||
- `auth_refresh`
|
||
|
||
|
||
|