205 lines
3.5 KiB
Markdown
205 lines
3.5 KiB
Markdown
|
|
状态机就是“把一次视频会话/设备流程拆成明确状态,并规定状态之间怎么流转”的机制。
|
|||
|
|
device-bootstrap 就是“设备启动或上线时,先来云端报到、认证,并领取连接 MQTT/实时系统所需临时配置和凭证”的接入服务。
|
|||
|
|
|
|||
|
|
1. 状态机是什么意思
|
|||
|
|
1.1 通俗解释
|
|||
|
|
状态机可以理解成一张流程规则表。
|
|||
|
|
|
|||
|
|
比如一次智能锁视频通话,不应该只是简单地说:
|
|||
|
|
|
|||
|
|
开始通话
|
|||
|
|
结束通话
|
|||
|
|
而是应该有一系列明确状态:
|
|||
|
|
|
|||
|
|
待创建 -> 呼叫中 -> 已接听 -> 连接中 -> 已连接 -> 通话中 -> 已结束
|
|||
|
|
每个状态只能按照规则进入下一个状态。
|
|||
|
|
|
|||
|
|
例如:
|
|||
|
|
|
|||
|
|
pending -> ringing -> accepted -> connecting -> connected -> ended
|
|||
|
|
不能乱跳,比如:
|
|||
|
|
|
|||
|
|
pending -> connected
|
|||
|
|
通常就不合理,因为中间还没经过设备接听和媒体连接。
|
|||
|
|
|
|||
|
|
1.2 在你这个智能锁项目里的含义
|
|||
|
|
你们旧方案里可能是通过 UDP 字段告诉 APP 或锁:
|
|||
|
|
|
|||
|
|
开始视频
|
|||
|
|
结束视频
|
|||
|
|
这种方式简单,但问题是:
|
|||
|
|
|
|||
|
|
APP 以为开始了,设备没收到
|
|||
|
|
|
|||
|
|
设备接听了,APP 已经取消
|
|||
|
|
|
|||
|
|
网络抖动导致消息重复
|
|||
|
|
|
|||
|
|
云端不知道现在到底是“呼叫中”还是“已连接”
|
|||
|
|
|
|||
|
|
通话失败后不好追踪原因
|
|||
|
|
|
|||
|
|
所以新方案里要用 session-orchestrator 管理状态机。
|
|||
|
|
|
|||
|
|
也就是云端统一记录:
|
|||
|
|
|
|||
|
|
这个 sessionId 当前到底处于什么状态
|
|||
|
|
2. 视频会话状态机例子
|
|||
|
|
2.1 推荐状态
|
|||
|
|
pending
|
|||
|
|
ringing
|
|||
|
|
accepted
|
|||
|
|
connecting
|
|||
|
|
connected
|
|||
|
|
degraded
|
|||
|
|
switching_route
|
|||
|
|
recovered
|
|||
|
|
ended
|
|||
|
|
rejected
|
|||
|
|
timeout
|
|||
|
|
failed
|
|||
|
|
可以翻译成:
|
|||
|
|
|
|||
|
|
状态
|
|||
|
|
|
|||
|
|
中文含义
|
|||
|
|
|
|||
|
|
pending
|
|||
|
|
|
|||
|
|
会话刚创建,等待发起呼叫
|
|||
|
|
|
|||
|
|
ringing
|
|||
|
|
|
|||
|
|
正在呼叫设备 / 设备响铃
|
|||
|
|
|
|||
|
|
accepted
|
|||
|
|
|
|||
|
|
设备已接听
|
|||
|
|
|
|||
|
|
connecting
|
|||
|
|
|
|||
|
|
APP 和设备正在建立媒体连接
|
|||
|
|
|
|||
|
|
connected
|
|||
|
|
|
|||
|
|
音视频已连通
|
|||
|
|
|
|||
|
|
degraded
|
|||
|
|
|
|||
|
|
通话质量下降
|
|||
|
|
|
|||
|
|
switching_route
|
|||
|
|
|
|||
|
|
正在切换媒体线路
|
|||
|
|
|
|||
|
|
recovered
|
|||
|
|
|
|||
|
|
切换后恢复正常
|
|||
|
|
|
|||
|
|
ended
|
|||
|
|
|
|||
|
|
正常结束
|
|||
|
|
|
|||
|
|
rejected
|
|||
|
|
|
|||
|
|
被拒接
|
|||
|
|
|
|||
|
|
timeout
|
|||
|
|
|
|||
|
|
超时未响应
|
|||
|
|
|
|||
|
|
failed
|
|||
|
|
|
|||
|
|
异常失败
|
|||
|
|
|
|||
|
|
2.2 状态流转例子
|
|||
|
|
一次正常视频通话:
|
|||
|
|
|
|||
|
|
pending
|
|||
|
|
-> ringing
|
|||
|
|
-> accepted
|
|||
|
|
-> connecting
|
|||
|
|
-> connected
|
|||
|
|
-> ended
|
|||
|
|
中文就是:
|
|||
|
|
|
|||
|
|
创建会话
|
|||
|
|
-> 呼叫设备
|
|||
|
|
-> 设备接听
|
|||
|
|
-> 建立 WebRTC / ZLM 连接
|
|||
|
|
-> 通话成功
|
|||
|
|
-> 挂断结束
|
|||
|
|
2.3 异常情况例子
|
|||
|
|
设备不在线
|
|||
|
|
pending -> failed
|
|||
|
|
原因:
|
|||
|
|
|
|||
|
|
device_offline
|
|||
|
|
设备没有响应
|
|||
|
|
pending -> ringing -> timeout
|
|||
|
|
原因:
|
|||
|
|
|
|||
|
|
invite_timeout
|
|||
|
|
用户取消
|
|||
|
|
pending -> ringing -> ended
|
|||
|
|
原因:
|
|||
|
|
|
|||
|
|
caller_cancelled
|
|||
|
|
设备拒接
|
|||
|
|
pending -> ringing -> rejected
|
|||
|
|
原因:
|
|||
|
|
|
|||
|
|
device_rejected
|
|||
|
|
WebRTC 连接失败,切 ZLMediaKit
|
|||
|
|
pending
|
|||
|
|
-> ringing
|
|||
|
|
-> accepted
|
|||
|
|
-> connecting
|
|||
|
|
-> failed_p2p
|
|||
|
|
-> switching_route
|
|||
|
|
-> connected
|
|||
|
|
或者更规范一点:
|
|||
|
|
|
|||
|
|
connecting
|
|||
|
|
-> degraded
|
|||
|
|
-> switching_route
|
|||
|
|
-> recovered
|
|||
|
|
-> connected
|
|||
|
|
3. 为什么一定要状态机
|
|||
|
|
3.1 保证流程不乱
|
|||
|
|
没有状态机时,可能出现:
|
|||
|
|
|
|||
|
|
已经挂断了,又收到设备 accept
|
|||
|
|
那系统不知道该怎么办。
|
|||
|
|
|
|||
|
|
有状态机后可以规定:
|
|||
|
|
|
|||
|
|
ended 状态下收到 accept,直接忽略或记录为迟到事件
|
|||
|
|
3.2 方便排查问题
|
|||
|
|
有状态机后,每个会话都能查:
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
这样就能知道失败原因是:
|
|||
|
|
|
|||
|
|
设备接了,但 WebRTC 没连上
|
|||
|
|
而不是一句模糊的:
|
|||
|
|
|
|||
|
|
通话失败
|
|||
|
|
3.3 方便做超时和重试
|
|||
|
|
比如:
|
|||
|
|
|
|||
|
|
呼叫设备 15 秒没响应,自动超时
|
|||
|
|
|
|||
|
|
WebRTC 10 秒没连上,切 ZLM
|
|||
|
|
|
|||
|
|
设备 ACK 没回来,重发 invite
|
|||
|
|
|
|||
|
|
通话结束后清理 token 和流资源
|
|||
|
|
|
|||
|
|
这些都依赖状态机。
|