AllStar2.0/术语:状态机.md

556 lines
9.6 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.

```markdown
# 状态机与 `device-bootstrap` 术语说明
## 一、核心结论
**状态机**:用于管理一次视频会话或设备流程的状态变化,明确规定当前处于什么状态、下一步能进入什么状态、异常时如何处理。
**`device-bootstrap`**:设备启动或上线时访问的接入服务,用于完成设备认证,并下发 MQTT 临时凭证、topic 权限、连接配置和设备能力配置。
---
## 二、状态机是什么意思
### 1. 通俗理解
状态机可以理解成一张**流程规则表**。
比如一次智能锁视频通话,不应该只有:
```text
开始通话
结束通话
```
而应该有完整流程:
```text
待创建 -> 呼叫中 -> 已接听 -> 连接中 -> 已连接 -> 已结束
```
每个状态只能按照规则进入下一个状态。
例如:
```text
pending -> ringing -> accepted -> connecting -> connected -> ended
```
不能随意跳转,例如:
```text
pending -> connected
```
通常是不合理的,因为中间还没有经过设备接听、媒体连接等步骤。
---
## 三、状态机在智能锁项目中的作用
旧方案里,可能通过 UDP 字段直接通知 APP 或锁:
```text
开始视频
结束视频
```
这种方式简单,但容易出现以下问题:
- APP 以为开始了,设备没收到
- 设备接听了APP 已经取消
- 网络抖动导致消息重复
- 云端不知道当前到底是“呼叫中”还是“已连接”
- 通话失败后不好追踪原因
新方案中,由 `session-orchestrator` 统一管理状态机。
也就是云端统一记录:
```text
这个 sessionId 当前到底处于什么状态
```
---
## 四、视频会话状态机示例
### 1. 推荐状态
| 状态 | 中文含义 |
|---|---|
| `pending` | 会话刚创建,等待发起呼叫 |
| `ringing` | 正在呼叫设备 / 设备响铃 |
| `accepted` | 设备已接听 |
| `connecting` | APP 和设备正在建立媒体连接 |
| `connected` | 音视频已连通 |
| `degraded` | 通话质量下降 |
| `switching_route` | 正在切换媒体线路 |
| `recovered` | 切换后恢复正常 |
| `ended` | 正常结束 |
| `rejected` | 被拒接 |
| `timeout` | 超时未响应 |
| `failed` | 异常失败 |
---
### 2. 正常通话流程
```text
pending
-> ringing
-> accepted
-> connecting
-> connected
-> ended
```
对应中文流程:
```text
创建会话
-> 呼叫设备
-> 设备接听
-> 建立 WebRTC / ZLM 连接
-> 通话成功
-> 挂断结束
```
---
### 3. 异常流程示例
#### 设备不在线
```text
pending -> failed
```
失败原因:
```text
device_offline
```
#### 设备没有响应
```text
pending -> ringing -> timeout
```
失败原因:
```text
invite_timeout
```
#### 用户取消
```text
pending -> ringing -> ended
```
结束原因:
```text
caller_cancelled
```
#### 设备拒接
```text
pending -> ringing -> rejected
```
失败原因:
```text
device_rejected
```
#### WebRTC 连接失败后切换 ZLMediaKit
```text
pending
-> ringing
-> accepted
-> connecting
-> degraded
-> switching_route
-> recovered
-> connected
```
---
## 五、为什么需要状态机
### 1. 保证流程不乱
没有状态机时,可能出现:
```text
已经挂断了,又收到设备 accept
```
有状态机后可以规定:
```text
ended 状态下收到 accept直接忽略或记录为迟到事件
```
---
### 2. 方便排查问题
有状态机后,可以按 `sessionId` 查完整流程:
```text
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
```
这样可以明确知道失败原因是:
```text
设备接听了,但 WebRTC 没连上
```
而不是笼统地显示:
```text
通话失败
```
---
### 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
}
```
系统就可以按设备能力下发不同策略。
---
### 4. 支持灰度升级
例如只让 10% 的设备启用 ZLMediaKit
```json
{
"zlmEnabled": true
}
```
其它设备暂时不开启。
---
## 九、`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
```
```