2026-04-27 14:23:41 +08:00
|
|
|
|
```markdown
|
|
|
|
|
|
# 状态机与 `device-bootstrap` 术语说明
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
## 一、核心结论
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
**状态机**:用于管理一次视频会话或设备流程的状态变化,明确规定当前处于什么状态、下一步能进入什么状态、异常时如何处理。
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
**`device-bootstrap`**:设备启动或上线时访问的接入服务,用于完成设备认证,并下发 MQTT 临时凭证、topic 权限、连接配置和设备能力配置。
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
---
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
## 二、状态机是什么意思
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
### 1. 通俗理解
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
状态机可以理解成一张**流程规则表**。
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
比如一次智能锁视频通话,不应该只有:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
|
|
|
|
|
开始通话
|
|
|
|
|
|
结束通话
|
|
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
而应该有完整流程:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
|
|
|
|
|
待创建 -> 呼叫中 -> 已接听 -> 连接中 -> 已连接 -> 已结束
|
|
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
每个状态只能按照规则进入下一个状态。
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
例如:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
|
|
|
|
|
pending -> ringing -> accepted -> connecting -> connected -> ended
|
|
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
不能随意跳转,例如:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
|
|
|
|
|
pending -> connected
|
|
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
通常是不合理的,因为中间还没有经过设备接听、媒体连接等步骤。
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
---
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
## 三、状态机在智能锁项目中的作用
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
旧方案里,可能通过 UDP 字段直接通知 APP 或锁:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
|
|
|
|
|
开始视频
|
|
|
|
|
|
结束视频
|
|
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
这种方式简单,但容易出现以下问题:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
- APP 以为开始了,设备没收到
|
|
|
|
|
|
- 设备接听了,APP 已经取消
|
|
|
|
|
|
- 网络抖动导致消息重复
|
|
|
|
|
|
- 云端不知道当前到底是“呼叫中”还是“已连接”
|
|
|
|
|
|
- 通话失败后不好追踪原因
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
新方案中,由 `session-orchestrator` 统一管理状态机。
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
也就是云端统一记录:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
|
|
|
|
|
这个 sessionId 当前到底处于什么状态
|
|
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
---
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
## 四、视频会话状态机示例
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
### 1. 推荐状态
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
| 状态 | 中文含义 |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| `pending` | 会话刚创建,等待发起呼叫 |
|
|
|
|
|
|
| `ringing` | 正在呼叫设备 / 设备响铃 |
|
|
|
|
|
|
| `accepted` | 设备已接听 |
|
|
|
|
|
|
| `connecting` | APP 和设备正在建立媒体连接 |
|
|
|
|
|
|
| `connected` | 音视频已连通 |
|
|
|
|
|
|
| `degraded` | 通话质量下降 |
|
|
|
|
|
|
| `switching_route` | 正在切换媒体线路 |
|
|
|
|
|
|
| `recovered` | 切换后恢复正常 |
|
|
|
|
|
|
| `ended` | 正常结束 |
|
|
|
|
|
|
| `rejected` | 被拒接 |
|
|
|
|
|
|
| `timeout` | 超时未响应 |
|
|
|
|
|
|
| `failed` | 异常失败 |
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
---
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
### 2. 正常通话流程
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
pending
|
|
|
|
|
|
-> ringing
|
|
|
|
|
|
-> accepted
|
|
|
|
|
|
-> connecting
|
|
|
|
|
|
-> connected
|
|
|
|
|
|
-> ended
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
对应中文流程:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
创建会话
|
|
|
|
|
|
-> 呼叫设备
|
|
|
|
|
|
-> 设备接听
|
|
|
|
|
|
-> 建立 WebRTC / ZLM 连接
|
|
|
|
|
|
-> 通话成功
|
|
|
|
|
|
-> 挂断结束
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 异常流程示例
|
|
|
|
|
|
|
|
|
|
|
|
#### 设备不在线
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
pending -> failed
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
失败原因:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
device_offline
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 设备没有响应
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
pending -> ringing -> timeout
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
失败原因:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
invite_timeout
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 用户取消
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
pending -> ringing -> ended
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
结束原因:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
caller_cancelled
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 设备拒接
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
pending -> ringing -> rejected
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
失败原因:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
device_rejected
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### WebRTC 连接失败后切换 ZLMediaKit
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
pending
|
|
|
|
|
|
-> ringing
|
|
|
|
|
|
-> accepted
|
|
|
|
|
|
-> connecting
|
|
|
|
|
|
-> degraded
|
|
|
|
|
|
-> switching_route
|
|
|
|
|
|
-> recovered
|
|
|
|
|
|
-> connected
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 五、为什么需要状态机
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 保证流程不乱
|
|
|
|
|
|
|
2026-04-27 14:10:24 +08:00
|
|
|
|
没有状态机时,可能出现:
|
|
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
已经挂断了,又收到设备 accept
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
|
|
|
|
|
有状态机后可以规定:
|
|
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
ended 状态下收到 accept,直接忽略或记录为迟到事件
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 方便排查问题
|
|
|
|
|
|
|
|
|
|
|
|
有状态机后,可以按 `sessionId` 查完整流程:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
sessionId = abc123
|
|
|
|
|
|
pending at 10:00:01
|
|
|
|
|
|
ringing at 10:00:02
|
|
|
|
|
|
accepted at 10:00:05
|
|
|
|
|
|
connecting at 10:00:06
|
|
|
|
|
|
timeout at 10:00:16
|
|
|
|
|
|
reason = ice_timeout
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
这样可以明确知道失败原因是:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```text
|
|
|
|
|
|
设备接听了,但 WebRTC 没连上
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
而不是笼统地显示:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-04-27 14:10:24 +08:00
|
|
|
|
通话失败
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 方便做超时和重试
|
|
|
|
|
|
|
|
|
|
|
|
状态机可以支持:
|
|
|
|
|
|
|
|
|
|
|
|
- 呼叫设备 15 秒没响应,自动超时
|
|
|
|
|
|
- WebRTC 10 秒没连上,切换 ZLMediaKit
|
|
|
|
|
|
- 设备 ACK 没回来,重发 invite
|
|
|
|
|
|
- 通话结束后清理 token 和流媒体资源
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 六、`device-bootstrap` 是什么意思
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 通俗理解
|
|
|
|
|
|
|
|
|
|
|
|
`device-bootstrap` 可以理解为:
|
|
|
|
|
|
|
|
|
|
|
|
> 设备上线入口 / 设备启动接入服务 / 设备报到服务
|
|
|
|
|
|
|
|
|
|
|
|
设备开机后,不应该直接随便连接 MQTT,也不应该把固定账号密码写死在固件里。
|
|
|
|
|
|
|
|
|
|
|
|
更安全的做法是:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
设备开机
|
|
|
|
|
|
-> 调用 device-bootstrap
|
|
|
|
|
|
-> 云端验证设备身份
|
|
|
|
|
|
-> 云端返回 MQTT 地址、临时账号、topic 权限、配置
|
|
|
|
|
|
-> 设备再连接 BifroMQ
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 七、`device-bootstrap` 在项目中的作用
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 设备启动时的流程
|
|
|
|
|
|
|
|
|
|
|
|
设备,也就是 WiFi 网关锁,启动后先请求:
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
POST /device/bootstrap
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
请求中通常携带:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"deviceId": "device_001",
|
|
|
|
|
|
"firmwareVersion": "1.0.0",
|
|
|
|
|
|
"timestamp": 1710000000,
|
|
|
|
|
|
"signature": "xxxxx",
|
|
|
|
|
|
"capabilities": {
|
|
|
|
|
|
"webrtc": true,
|
|
|
|
|
|
"zlm": true,
|
|
|
|
|
|
"ai": true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
云端验证通过后返回:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"mqtt": {
|
|
|
|
|
|
"host": "mqtt.example.com",
|
|
|
|
|
|
"port": 8883,
|
|
|
|
|
|
"clientId": "lock_xxx",
|
|
|
|
|
|
"username": "tmp_user",
|
|
|
|
|
|
"password": "tmp_password",
|
|
|
|
|
|
"expiresIn": 3600
|
|
|
|
|
|
},
|
|
|
|
|
|
"topics": {
|
|
|
|
|
|
"subscribe": [
|
|
|
|
|
|
"tenant/t1/device/d1/control",
|
|
|
|
|
|
"tenant/t1/session/+/signal/device"
|
|
|
|
|
|
],
|
|
|
|
|
|
"publish": [
|
|
|
|
|
|
"tenant/t1/device/d1/status",
|
|
|
|
|
|
"tenant/t1/device/d1/event",
|
|
|
|
|
|
"tenant/t1/session/+/signal/app"
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
"config": {
|
|
|
|
|
|
"heartbeatInterval": 30,
|
|
|
|
|
|
"webrtcEnabled": true,
|
|
|
|
|
|
"zlmEnabled": true,
|
|
|
|
|
|
"aiEnabled": true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
含义是:
|
|
|
|
|
|
|
|
|
|
|
|
- 设备认证通过
|
|
|
|
|
|
- 返回 MQTT 连接地址
|
|
|
|
|
|
- 返回临时账号密码
|
|
|
|
|
|
- 返回允许订阅的 topic
|
|
|
|
|
|
- 返回允许发布的 topic
|
|
|
|
|
|
- 返回心跳周期
|
|
|
|
|
|
- 返回设备功能开关配置
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 八、`device-bootstrap` 解决的问题
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 避免设备写死 MQTT 密码
|
|
|
|
|
|
|
|
|
|
|
|
不推荐:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
所有设备固件里写同一个 MQTT 用户名和密码
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
风险是:一旦泄露,所有设备都会受影响。
|
|
|
|
|
|
|
|
|
|
|
|
推荐:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
每台设备启动时领取自己的临时凭证
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 控制设备权限
|
|
|
|
|
|
|
|
|
|
|
|
例如设备 `device_001` 只能访问:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
tenant/t1/device/device_001/...
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
不能访问:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
tenant/t1/device/device_002/...
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 支持设备配置下发
|
|
|
|
|
|
|
|
|
|
|
|
例如某个设备支持 WebRTC:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"webrtcEnabled": true
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
另一个旧设备不支持:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"webrtcEnabled": false
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
系统就可以按设备能力下发不同策略。
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
---
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
### 4. 支持灰度升级
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
例如只让 10% 的设备启用 ZLMediaKit:
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"zlmEnabled": true
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
2026-04-27 14:10:24 +08:00
|
|
|
|
|
2026-04-27 14:23:41 +08:00
|
|
|
|
其它设备暂时不开启。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 九、`device-bootstrap` 和 `session-orchestrator` 的区别
|
|
|
|
|
|
|
|
|
|
|
|
| 模块 | 作用 | 类比 |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| `device-bootstrap` | 设备上线认证、领取 MQTT 凭证、获取配置 | 门卫 / 报到处 |
|
|
|
|
|
|
| `session-orchestrator` | 管理一次视频会话的创建、呼叫、接听、连接、切路、挂断 | 调度员 / 指挥中心 |
|
|
|
|
|
|
| BifroMQ | 负责消息通道 | 对讲机频道 / 消息总线 |
|
|
|
|
|
|
| ZLMediaKit / WebRTC | 负责音视频传输 | 真正的视频通话线路 |
|
|
|
|
|
|
|
|
|
|
|
|
简单理解:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
device-bootstrap 管设备怎么接入系统
|
|
|
|
|
|
session-orchestrator 管一次通话怎么开始、进行、结束
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 十、完整流程<E6B581><E7A88B><EFBFBD>例
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 设备上线流程
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
WiFi锁开机
|
|
|
|
|
|
-> 调用 device-bootstrap
|
|
|
|
|
|
-> bootstrap 验证设备身份
|
|
|
|
|
|
-> 返回 MQTT 临时凭证
|
|
|
|
|
|
-> WiFi锁连接 BifroMQ
|
|
|
|
|
|
-> WiFi锁上报 online
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这部分由 `device-bootstrap` 负责。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 用户发起视频通话流程
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
APP 点击视频通话
|
|
|
|
|
|
-> 调用 starlock
|
|
|
|
|
|
-> starlock 校验用户是否有权限访问这把锁
|
|
|
|
|
|
-> starlock 调用 session-orchestrator 创建 session
|
|
|
|
|
|
-> session-orchestrator 通过 BifroMQ 给设备发 invite
|
|
|
|
|
|
-> 设备响铃并返回 accept
|
|
|
|
|
|
-> APP 和设备交换 WebRTC signaling
|
|
|
|
|
|
-> 建立 P2P / TURN / ZLM 媒体链路
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这部分由 `session-orchestrator` 负责。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 通话中弱网切换流程
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
APP 上报丢包高
|
|
|
|
|
|
设备上报 RTT 高
|
|
|
|
|
|
session-orchestrator 判断质量差
|
|
|
|
|
|
-> 下发 switch-route
|
|
|
|
|
|
-> APP 和设备切到 ZLMediaKit
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这仍然属于状态机控制。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 十一、<E4B880><E38081><EFBFBD>团队的简短解释
|
|
|
|
|
|
|
|
|
|
|
|
### 状态机一句话
|
|
|
|
|
|
|
|
|
|
|
|
> 状态机就是云端统一管理“这次通话现在进行到哪一步、下一步允许做什么、超时或异常怎么处理”的规则系统。
|
|
|
|
|
|
|
|
|
|
|
|
### `device-bootstrap` 一句话
|
|
|
|
|
|
|
|
|
|
|
|
> `device-bootstrap` 就是设备开机后的接入报到服务,负责认证设备,并给设备下发 MQTT 临时凭证、topic 权限和能力配置。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 十二、项目落地建议
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 状态机第一版建议
|
|
|
|
|
|
|
|
|
|
|
|
第一版状态不要太复杂,建议先支持:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
created
|
|
|
|
|
|
ringing
|
|
|
|
|
|
accepted
|
|
|
|
|
|
connecting
|
|
|
|
|
|
connected
|
|
|
|
|
|
ended
|
|
|
|
|
|
rejected
|
|
|
|
|
|
timeout
|
|
|
|
|
|
failed
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
后续稳定后再增加:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
degraded
|
|
|
|
|
|
switching_route
|
|
|
|
|
|
recovered
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. `device-bootstrap` 第一版必须返回
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
mqttHost
|
|
|
|
|
|
mqttPort
|
|
|
|
|
|
clientId
|
|
|
|
|
|
username
|
|
|
|
|
|
password
|
|
|
|
|
|
expiresIn
|
|
|
|
|
|
subscribeTopics
|
|
|
|
|
|
publishTopics
|
|
|
|
|
|
heartbeatInterval
|
|
|
|
|
|
capabilities
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
不要让设备直接写死 MQTT 账号密码。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 十三、最简对照表
|
|
|
|
|
|
|
|
|
|
|
|
| 模块 | 负责内容 |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| 状态机 | 管“通话流程” |
|
|
|
|
|
|
| `device-bootstrap` | 管“设备上线接入” |
|
|
|
|
|
|
| BifroMQ | 管“消息通道” |
|
|
|
|
|
|
| WebRTC / ZLM | 管“视频声音怎么传” |
|
|
|
|
|
|
| `starlock` | 管“用户有没有权限” |
|
|
|
|
|
|
| `starcloud` | 管“共享业务能力” |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 十四、总结
|
|
|
|
|
|
|
|
|
|
|
|
在智能锁实时系统中:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
用户有没有权限开视频:starlock / starcloud 判断
|
|
|
|
|
|
设备怎么连上云:device-bootstrap
|
|
|
|
|
|
控制消息怎么传:BifroMQ
|
|
|
|
|
|
这次通话现在到哪一步:session-orchestrator 状态机
|
|
|
|
|
|
视频音频怎么传:WebRTC / TURN / ZLMediaKit
|
|
|
|
|
|
```
|
|
|
|
|
|
```
|