Files
cmr-mini/doc/gateway/网关协议规范.md

350 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 实时网关协议草案
> 文档版本v1.0
> 最后更新2026-04-02
本文档描述 `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`