1673 lines
49 KiB
Markdown
1673 lines
49 KiB
Markdown
|
|
# 智能锁新实时系统方案
|
|||
|
|
|
|||
|
|
本文档面向一个“全新项目”的设计,但明确采用 `starcloud` 作为共享业务能力云平台,`starlock` 作为其租户化应用层入口,不重复建设通用业务能力。
|
|||
|
|
|
|||
|
|
## 1. 目标与约束
|
|||
|
|
|
|||
|
|
### 1.1 已知现状
|
|||
|
|
|
|||
|
|
- `starcloud`:共享云平台,向下游业务应用提供可复用 API 与业务能力。
|
|||
|
|
- `starlock`:PHP 业务后台,负责 APP 用户注册、登录、权限、家庭/门锁归属和其它业务规则。
|
|||
|
|
- `app-starlock`:Flutter APP。
|
|||
|
|
- `starchart-sls1 - 0304`:现有中央通信层,承担注册、发现、转发、对讲相关职责。
|
|||
|
|
- 目标方向:
|
|||
|
|
- 发现服务迁移到 Apache BifroMQ
|
|||
|
|
- 音视频不再默认全部走中心服务器转发,但保留中心转发兜底
|
|||
|
|
- 按网络质量动态选择 WebRTC P2P 或 `ZLMediaKit` 转发
|
|||
|
|
- 在 P2P 不稳定时,可切回中心服务器转发或 ZLMediaKit 转发
|
|||
|
|
|
|||
|
|
### 1.2 新方案目标
|
|||
|
|
|
|||
|
|
新项目应满足以下目标:
|
|||
|
|
|
|||
|
|
1. `starcloud` 作为共享业务能力主平台,承载可复用的业务 API。
|
|||
|
|
2. `starlock` 作为面向 APP 的租户化业务入口和编排层。
|
|||
|
|
3. 实时控制面与媒体面彻底分离。
|
|||
|
|
4. 设备发现、在线状态、会话信令交给 Apache BifroMQ。
|
|||
|
|
5. 音视频链路不固定单一路径,而是按网络质量动态选路:中好网络优先 P2P,弱网优先 `ZLMediaKit` 转发,`TURN` 作为 RTC 路径补位。
|
|||
|
|
6. AI 通过旁路式能力接入,不破坏主对讲链路。
|
|||
|
|
|
|||
|
|
### 1.3 设计原则
|
|||
|
|
|
|||
|
|
- `starcloud` 负责可复用业务能力与共享策略,
|
|||
|
|
`starlock` 负责租户化编排和对外 API 聚合。
|
|||
|
|
- 新实时系统只做连接、会话编排、信令分发和媒体接入。
|
|||
|
|
- App 与设备获取到的是短期会话权限,不直接暴露业务后台内部权限模型。
|
|||
|
|
- AI 接入必须解耦于主通话状态机。
|
|||
|
|
- 所有大流量音视频传输采用网络自适应策略:中好网络优先标准 RTC P2P,弱网由 `ZLMediaKit` 作为优先实现方案。
|
|||
|
|
|
|||
|
|
## 2. 角色划分
|
|||
|
|
|
|||
|
|
### 2.1 `starcloud` 共享能力职责
|
|||
|
|
|
|||
|
|
`starcloud` 继续承担:
|
|||
|
|
|
|||
|
|
- 可复用用户/权限策略能力
|
|||
|
|
- 设备与家庭关系的共享模型能力
|
|||
|
|
- 通用套餐、计费、审计、风控能力
|
|||
|
|
- 标准化业务 API(供 `starlock` 等下游应用调用)
|
|||
|
|
- 可复用的业务规则引擎与跨租户能力演进
|
|||
|
|
|
|||
|
|
### 2.2 `starlock` 租户应用层职责
|
|||
|
|
|
|||
|
|
`starlock` 继续承担:
|
|||
|
|
|
|||
|
|
- 面向 `app-starlock` 的统一业务入口
|
|||
|
|
- 结合租户/渠道配置编排 `starcloud` 共享能力
|
|||
|
|
- 聚合会话、通知、AI 与设备业务流程
|
|||
|
|
- 面向 APP 的主业务 API 与体验层策略
|
|||
|
|
- 仅保留强租户定制逻辑,不重复实现通用业务能力
|
|||
|
|
|
|||
|
|
### 2.3 新实时系统承担职责
|
|||
|
|
|
|||
|
|
新项目承担:
|
|||
|
|
|
|||
|
|
- 设备在线状态管理
|
|||
|
|
- 设备能力声明与发现
|
|||
|
|
- 实时会话创建与编排
|
|||
|
|
- WebRTC signaling
|
|||
|
|
- WebRTC 媒体接入
|
|||
|
|
- TURN/STUN 基础设施
|
|||
|
|
- 中心媒体转发兜底
|
|||
|
|
- `ZLMediaKit` 转发接入
|
|||
|
|
- AI 会话桥接
|
|||
|
|
- 调试日志、会话追踪、弱状态缓存
|
|||
|
|
|
|||
|
|
## 3. 总体架构图
|
|||
|
|
|
|||
|
|
说明:如果你当前 Markdown 查看器不支持 Mermaid,请直接看 `3.0.1` 与 `3.0.2` 的纯文本结构图。
|
|||
|
|
|
|||
|
|
### 3.0.1 纯文本结构图(精简版)
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
app-starlock
|
|||
|
|
-> starlock (租户应用层)
|
|||
|
|
-> starcloud (共享业务能力 API)
|
|||
|
|
-> session-orchestrator (独立服务)
|
|||
|
|
-> Apache BifroMQ (发现/在线/信令)
|
|||
|
|
-> 媒体选路: P2P / TURN / ZLMediaKit / relay
|
|||
|
|
<-> Lock/Gateway (对讲设备)
|
|||
|
|
-> ai-gateway -> xiaozhi_server (AI旁路)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.0.2 纯文本结构图(详细版)
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
[Client]
|
|||
|
|
app-starlock
|
|||
|
|
Lock/Gateway
|
|||
|
|
|
|||
|
|
[Business]
|
|||
|
|
starlock (租户应用层,面向APP)
|
|||
|
|
- 聚合业务 API
|
|||
|
|
- 编排实时会话
|
|||
|
|
- 调用共享能力
|
|||
|
|
starcloud (共享业务云平台)
|
|||
|
|
- 用户/权限/套餐/审计等通用能力
|
|||
|
|
|
|||
|
|
[Session & Control]
|
|||
|
|
session-orchestrator (phase1+, 独立服务形态)
|
|||
|
|
device-bootstrap
|
|||
|
|
Apache BifroMQ
|
|||
|
|
MQTT event worker
|
|||
|
|
realtime-store
|
|||
|
|
|
|||
|
|
[Media]
|
|||
|
|
优先策略(自适应):
|
|||
|
|
1) 中好网络 -> WebRTC P2P
|
|||
|
|
2) RTC补位 -> TURN
|
|||
|
|
3) 弱网优先 -> ZLMediaKit
|
|||
|
|
4) 最终兜底 -> media-relay
|
|||
|
|
|
|||
|
|
[AI]
|
|||
|
|
ai-gateway -> xiaozhi_server
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph TB
|
|||
|
|
subgraph Client
|
|||
|
|
APP[app-starlock\nFlutter App]
|
|||
|
|
LOCK[Lock / Gateway\n门锁或网关]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph Business
|
|||
|
|
STARCLOUD[starcloud\n共享业务云平台]
|
|||
|
|
STARLOCK[starlock\n租户应用层]
|
|||
|
|
PUSHSVC[Push / Callback\n推送与业务通知]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph Realtime
|
|||
|
|
ORCH[session-orchestrator\n会话编排服务]
|
|||
|
|
BIFROMQ[Apache BifroMQ\n发现/在线/信令]
|
|||
|
|
TURN[coturn\nSTUN/TURN]
|
|||
|
|
RELAY[media-relay\n中心音视频转发]
|
|||
|
|
ZLM[ZLMediaKit\n标准流媒体转发]
|
|||
|
|
TRACE[realtime-store\n会话状态/日志缓存]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph AI
|
|||
|
|
AIGW[ai-gateway\nAI桥接层]
|
|||
|
|
XIAOZHI[xiaozhi_server\nAI实时服务]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
APP -->|HTTPS| STARLOCK
|
|||
|
|
STARLOCK -->|共享业务 API| STARCLOUD
|
|||
|
|
LOCK -->|HTTPS / bootstrap| STARLOCK
|
|||
|
|
|
|||
|
|
STARLOCK -->|内部 API| ORCH
|
|||
|
|
STARLOCK --> PUSHSVC
|
|||
|
|
|
|||
|
|
APP <-->|MQTT over WSS| BIFROMQ
|
|||
|
|
LOCK <-->|MQTT / MQTT over TLS| BIFROMQ
|
|||
|
|
|
|||
|
|
APP <-->|WebRTC P2P / TURN| LOCK
|
|||
|
|
APP -. fallback .-> TURN
|
|||
|
|
LOCK -. fallback .-> TURN
|
|||
|
|
APP -. relay fallback .-> RELAY
|
|||
|
|
LOCK -. relay fallback .-> RELAY
|
|||
|
|
APP -. optional relay .-> ZLM
|
|||
|
|
LOCK -. optional relay .-> ZLM
|
|||
|
|
|
|||
|
|
ORCH --> BIFROMQ
|
|||
|
|
ORCH --> RELAY
|
|||
|
|
ORCH --> ZLM
|
|||
|
|
ORCH --> TRACE
|
|||
|
|
STARLOCK --> TRACE
|
|||
|
|
|
|||
|
|
LOCK -. AI side channel .-> AIGW
|
|||
|
|
APP -. AI assisted mode .-> AIGW
|
|||
|
|
AIGW --> XIAOZHI
|
|||
|
|
AIGW --> STARLOCK
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.1 架构解读
|
|||
|
|
|
|||
|
|
- `starcloud` 是跨项目可复用业务能力平台,`starlock` 是租户化编排入口。
|
|||
|
|
- `session-orchestrator` 是会话状态机中心,但不保存完整业务模型。
|
|||
|
|
- `Apache BifroMQ` 只承接设备发现、在线状态和 signaling,不承接大媒体流。
|
|||
|
|
- `coturn` 是 WebRTC 的第一层兜底中继。
|
|||
|
|
- `media-relay` 是中心服务器音视频转发能力层,作为 P2P/TURN 失败后的工程兜底。
|
|||
|
|
- `ZLMediaKit` 可以直接承担这层能力,实现 WebRTC 失败后的中心转发,因此通常不需要再长期维护一套独立自研 relay。
|
|||
|
|
- `ai-gateway` 把 AI 从实时媒体层中解耦出来。
|
|||
|
|
|
|||
|
|
### 3.2 基于现有项目的迁移版架构图
|
|||
|
|
|
|||
|
|
下面这张图不是“完全脱离现状的理想图”,而是基于你当前项目角色关系做的迁移版架构图。
|
|||
|
|
|
|||
|
|
对应关系如下:
|
|||
|
|
|
|||
|
|
- 现有 `scd` 的“注册/发现/心跳”职责,迁移到 `Apache BifroMQ + device bootstrap + session-orchestrator`
|
|||
|
|
- 现有 `scrd` 的“媒体中继/NAT 穿透”职责,迁移到 `WebRTC P2P + coturn + 中心媒体转发兜底`
|
|||
|
|
- 现有 `rpcd` 不再承担实时转发中心角色,只保留必要的业务桥接,长期建议并入 `starlock` 内部服务调用
|
|||
|
|
- 现有 `event_listener` 继续保留在事件上报链路,但不再参与主媒体链路
|
|||
|
|
- 新增 `media-relay` 能力层,优先采用 `ZLMediaKit` 落地
|
|||
|
|
- 新增 `ai-gateway + xiaozhi_server` 作为 AI 能力面
|
|||
|
|
|
|||
|
|
当前项目约束补充:`WiFi锁` 默认就是“网关锁形态”,因此可直接承接 `网关设备` 角色。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
subgraph AppSide[APP侧]
|
|||
|
|
APP[app-starlock\nFlutter APP]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph BizSide[业务后台]
|
|||
|
|
STARCLOUD[starcloud\n共享业务云平台]
|
|||
|
|
STARLOCK[starlock\n租户应用层]
|
|||
|
|
CALLBACK[推送/回调/业务通知]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph RealtimeCloud[新实时云]
|
|||
|
|
BOOT[device-bootstrap\n设备接入与临时凭证]
|
|||
|
|
BIFROMQ[Apache BifroMQ\n发现/在线/信令]
|
|||
|
|
ORCH[session-orchestrator\n会话编排]
|
|||
|
|
TURN[coturn\nTURN/STUN]
|
|||
|
|
RELAY[media-relay\n中心音视频转发]
|
|||
|
|
ZLM[ZLMediaKit\n流媒体转发]
|
|||
|
|
EVT[event-listener\n事件监听/媒体落库]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph AIPlane[AI能力]
|
|||
|
|
AIGW[ai-gateway]
|
|||
|
|
XIAOZHI[xiaozhi_server]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph DeviceSide[智能锁设备侧]
|
|||
|
|
GW[WiFi网关锁\nWebRTC/AI优先承载]
|
|||
|
|
BLE[蓝牙锁]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
APP -->|HTTPS业务API| STARLOCK
|
|||
|
|
STARLOCK -->|共享业务 API| STARCLOUD
|
|||
|
|
STARLOCK -->|内部调用| BOOT
|
|||
|
|
STARLOCK -->|内部调用| ORCH
|
|||
|
|
STARLOCK --> CALLBACK
|
|||
|
|
|
|||
|
|
GW -->|设备认证/换取MQTT凭证| BOOT
|
|||
|
|
|
|||
|
|
APP <-->|MQTT over WSS| BIFROMQ
|
|||
|
|
GW <-->|MQTT/TLS| BIFROMQ
|
|||
|
|
|
|||
|
|
ORCH --> BIFROMQ
|
|||
|
|
BOOT --> BIFROMQ
|
|||
|
|
|
|||
|
|
APP <-->|WebRTC P2P / ZLM 自适应| GW
|
|||
|
|
APP -. P2P失败走TURN .-> TURN
|
|||
|
|
GW -. P2P失败走TURN .-> TURN
|
|||
|
|
APP -. TURN仍失败走中心转发 .-> RELAY
|
|||
|
|
GW -. TURN仍失败走中心转发 .-> RELAY
|
|||
|
|
APP -. 可选切到ZLM .-> ZLM
|
|||
|
|
GW -. 可选切到ZLM .-> ZLM
|
|||
|
|
|
|||
|
|
GW -->|事件上报| EVT
|
|||
|
|
GW -. 蓝牙透传 .-> BLE
|
|||
|
|
EVT -->|HTTP回调| STARLOCK
|
|||
|
|
|
|||
|
|
GW -. AI音频旁路 .-> AIGW
|
|||
|
|
APP -. AI辅助模式 .-> AIGW
|
|||
|
|
AIGW --> XIAOZHI
|
|||
|
|
AIGW --> STARLOCK
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 这张迁移图怎么理解
|
|||
|
|
|
|||
|
|
- 对你当前项目,`WiFi锁` 就是 `网关设备` 形态,可直接承接 WebRTC、双讲、AI 音频旁路能力。
|
|||
|
|
- 图中已合并为单节点 `WiFi网关锁`,避免角色重复表达。
|
|||
|
|
- `Apache BifroMQ` 取代了原先 `scd` 的发现中心角色,但不再承接媒体搬运。
|
|||
|
|
- `TURN` 是 RTC 路径的补位能力,但不是所有场景的首选。
|
|||
|
|
- `media-relay` 继续保留中心服务器音视频转发能力,便于兼容旧设备和极端网络环境。
|
|||
|
|
- `ZLMediaKit` 可以作为更标准的中心转发实现,在弱网场景下可优先于 P2P 成为首选媒体路径。
|
|||
|
|
- `event_listener` 继续服务事件回调、图片/视频处理、业务通知,不进入主实时链路。
|
|||
|
|
- `starlock` 仍然是外部唯一可信业务入口,APP 不直接向 `session-orchestrator` 暴露业务接口。
|
|||
|
|
|
|||
|
|
### 3.4 第一阶段落地架构图(`session-orchestrator` 独立)
|
|||
|
|
|
|||
|
|
按当前决策,第一阶段就独立部署 `session-orchestrator`,不再采用内嵌 `starlock` 的过渡形态。
|
|||
|
|
|
|||
|
|
这样做的目的:
|
|||
|
|
|
|||
|
|
- 从一开始就把业务编排与实时状态机解耦
|
|||
|
|
- 统一会话控制协议,替代历史 UDP 协议分散控制
|
|||
|
|
- 提前建立可扩容、可观测、可回放的会话控制平面
|
|||
|
|
- 后续只做横向扩容,不再经历二次拆分改造
|
|||
|
|
|
|||
|
|
对应第一阶段架构图如下:
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
subgraph AppSide[APP侧]
|
|||
|
|
APP[app-starlock\nFlutter APP]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph BizSide[业务后台]
|
|||
|
|
STARCLOUD[starcloud\n共享业务云平台]
|
|||
|
|
STARLOCK[starlock\n租户应用层]
|
|||
|
|
CALLBACK[推送/业务通知]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph RealtimeInfra[实时基础设施]
|
|||
|
|
ORCH[session-orchestrator\n独立会话控制服务]
|
|||
|
|
BOOT[device-bootstrap\n设备接入与临时凭证]
|
|||
|
|
BIFROMQ[Apache BifroMQ\n发现/在线/信令/事件总线]
|
|||
|
|
TURN[coturn\nTURN/STUN]
|
|||
|
|
RELAY[media-relay\n中心音视频转发]
|
|||
|
|
ZLM[ZLMediaKit\n流媒体转发]
|
|||
|
|
EVT[MQTT event worker\n原event-listener演进]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph AIPlane[AI能力]
|
|||
|
|
AIGW[ai-gateway]
|
|||
|
|
XIAOZHI[xiaozhi_server]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph DeviceSide[智能锁设备侧]
|
|||
|
|
GW[WiFi网关锁\nWebRTC/AI优先承载]
|
|||
|
|
BLE[蓝牙锁]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
APP -->|HTTPS业务API| STARLOCK
|
|||
|
|
STARLOCK -->|共享业务 API| STARCLOUD
|
|||
|
|
STARLOCK -->|内部调用| ORCH
|
|||
|
|
STARLOCK --> CALLBACK
|
|||
|
|
|
|||
|
|
GW -->|认证/换取MQTT凭证| BOOT
|
|||
|
|
STARLOCK -->|内部调用| BOOT
|
|||
|
|
|
|||
|
|
APP <-->|MQTT over WSS| BIFROMQ
|
|||
|
|
GW <-->|MQTT/TLS| BIFROMQ
|
|||
|
|
|
|||
|
|
ORCH --> BIFROMQ
|
|||
|
|
ORCH --> RELAY
|
|||
|
|
ORCH --> ZLM
|
|||
|
|
|
|||
|
|
APP <-->|WebRTC P2P / ZLM 自适应| GW
|
|||
|
|
APP -. P2P失败走TURN .-> TURN
|
|||
|
|
GW -. P2P失败走TURN .-> TURN
|
|||
|
|
APP -. TURN失败走中心转发 .-> RELAY
|
|||
|
|
GW -. TURN失败走中心转发 .-> RELAY
|
|||
|
|
APP -. 可选切ZLM .-> ZLM
|
|||
|
|
GW -. 可选切ZLM .-> ZLM
|
|||
|
|
|
|||
|
|
GW -->|事件上报| BIFROMQ
|
|||
|
|
BIFROMQ --> EVT
|
|||
|
|
EVT -->|HTTP回调/业务处理| STARLOCK
|
|||
|
|
|
|||
|
|
GW -. 蓝牙透传 .-> BLE
|
|||
|
|
|
|||
|
|
GW -. AI音频旁路 .-> AIGW
|
|||
|
|
APP -. AI辅助模式 .-> AIGW
|
|||
|
|
AIGW --> XIAOZHI
|
|||
|
|
AIGW --> STARLOCK
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.5 第一阶段图的关键变化
|
|||
|
|
|
|||
|
|
与前面的“目标态迁移图”相比,第一阶段版本有三个关键变化:
|
|||
|
|
|
|||
|
|
1. 第一阶段即独立部署 `session-orchestrator`
|
|||
|
|
2. `starlock` 只做业务授权与编排,不承载会话状态机
|
|||
|
|
3. `event_listener` 不再作为协议接收器,而是变成 `MQTT event worker`
|
|||
|
|
|
|||
|
|
### 3.6 第一阶段图的实际含义
|
|||
|
|
|
|||
|
|
- `starlock` 负责业务授权与会话编排入口,实时状态流转由 `session-orchestrator` 统一管理。
|
|||
|
|
- MQTT 上只跑发现、在线、signaling 和事件通知,不跑大媒体流。
|
|||
|
|
- 主媒体链路采用自适应策略:中好网络优先 `WebRTC P2P`,弱网优先 `ZLMediaKit`,`TURN` 负责 RTC 路径补位,中心转发能力持续保留。
|
|||
|
|
- `Apache BifroMQ -> MQTT event worker -> starlock` 负责事件消费、回调、媒体后处理等异步任务。
|
|||
|
|
- 后续如果会话量上来,优先扩容 `session-orchestrator` 实例与会话存储层,不再做架构拆分。
|
|||
|
|
|
|||
|
|
### 3.6.1 `session-orchestrator` 如何控制视频会话(详细)
|
|||
|
|
|
|||
|
|
你们之前“通过 UDP 协议字段通知 APP 和锁端开始/结束”的模式,本质是点对点控制,状态一致性和故障收敛依赖端侧实现,云端很难统一治理。
|
|||
|
|
|
|||
|
|
新方案里,`session-orchestrator` 用“会话状态机 + 控制指令 + ACK/超时机制”统一控制视频会话。
|
|||
|
|
|
|||
|
|
核心机制如下:
|
|||
|
|
|
|||
|
|
1. 建会话:`starlock` 完成权限校验后调用 `session-orchestrator` 创建会话,返回 `sessionId`、topic、短期 token、媒体策略。
|
|||
|
|
2. 发起呼叫:`session-orchestrator` 下发 `invite` 控制事件,设备侧回 `ringing/accept/reject`。
|
|||
|
|
3. 信令协商:APP/设备仅在约定 topic 交换 `offer/answer/candidate`,`session-orchestrator` 只做状态编排与超时控制,不搬运大媒体流。
|
|||
|
|
4. 建链判定:`session-orchestrator` 收集两端链路质量上报(RTT、丢包、抖动、可用带宽、candidate 类型),进入 `connecting -> connected`。
|
|||
|
|
5. 动态选路:当指标降级,发 `switch-route` 控制指令,从 `p2p` 切 `turn` 或 `zlmediakit`;若仍失败,再切 `relay`。
|
|||
|
|
6. 结束会话:任一端发送 `hangup` 或超时触发 `terminate`,`session-orchestrator` 统一写入终态并清理 token/资源。
|
|||
|
|
|
|||
|
|
推荐状态机:
|
|||
|
|
|
|||
|
|
- `pending` -> `ringing` -> `accepted` -> `connecting` -> `connected`
|
|||
|
|
- 通话中可进入:`degraded` -> `switching_route` -> `recovered`
|
|||
|
|
- 结束态:`ended` / `rejected` / `timeout` / `failed`
|
|||
|
|
|
|||
|
|
和旧 UDP 控制的关系:
|
|||
|
|
|
|||
|
|
- 旧模型:端到端 UDP 协议字段直接表达“开始/结束”,中心侧难追踪完整会话。
|
|||
|
|
- 新模型:开始/结束只是状态机中的两个事件,所有控制动作都有 `sessionId`、事件序号、ACK、超时重试与最终态落库。
|
|||
|
|
- 结果:可审计、可回放、可补偿,且便于联调和问题追踪。
|
|||
|
|
|
|||
|
|
### 3.7 现状与第一阶段对照图
|
|||
|
|
|
|||
|
|
这张图适合给团队评审时使用,左边是你们当前主要链路,右边是第一阶段目标链路。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
subgraph NOW[当前架构]
|
|||
|
|
APP1[app-starlock]
|
|||
|
|
STAR1[starlock]
|
|||
|
|
SCD[scd\n注册/发现/心跳]
|
|||
|
|
SCRD[scrd\n媒体转发/NAT]
|
|||
|
|
RPCD[rpcd\n业务桥接]
|
|||
|
|
EVT1[event_listener]
|
|||
|
|
DEV1[锁/网关设备]
|
|||
|
|
|
|||
|
|
APP1 --> STAR1
|
|||
|
|
STAR1 --> RPCD
|
|||
|
|
DEV1 --> SCD
|
|||
|
|
APP1 --> SCD
|
|||
|
|
APP1 --> SCRD
|
|||
|
|
DEV1 --> SCRD
|
|||
|
|
DEV1 --> EVT1
|
|||
|
|
EVT1 --> STAR1
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph PHASE1[第一阶段架构]
|
|||
|
|
APP2[app-starlock]
|
|||
|
|
STAR2[starlock]
|
|||
|
|
ORCH2[session-orchestrator]
|
|||
|
|
BOOT2[device-bootstrap]
|
|||
|
|
BIFROMQ2[Apache BifroMQ]
|
|||
|
|
TURN2[coturn]
|
|||
|
|
RELAY2[media-relay]
|
|||
|
|
ZLM2[ZLMediaKit]
|
|||
|
|
EVTW[MQTT event worker]
|
|||
|
|
AIGW2[ai-gateway]
|
|||
|
|
XIAO2[xiaozhi_server]
|
|||
|
|
DEV2[锁/网关设备]
|
|||
|
|
|
|||
|
|
APP2 --> STAR2
|
|||
|
|
STAR2 --> ORCH2
|
|||
|
|
STAR2 --> BOOT2
|
|||
|
|
ORCH2 --> BIFROMQ2
|
|||
|
|
APP2 --> BIFROMQ2
|
|||
|
|
DEV2 --> BOOT2
|
|||
|
|
DEV2 --> BIFROMQ2
|
|||
|
|
APP2 --> TURN2
|
|||
|
|
DEV2 --> TURN2
|
|||
|
|
APP2 --> RELAY2
|
|||
|
|
DEV2 --> RELAY2
|
|||
|
|
APP2 --> ZLM2
|
|||
|
|
DEV2 --> ZLM2
|
|||
|
|
BIFROMQ2 --> EVTW
|
|||
|
|
EVTW --> STAR2
|
|||
|
|
ORCH2 --> RELAY2
|
|||
|
|
ORCH2 --> ZLM2
|
|||
|
|
DEV2 -. AI旁路 .-> AIGW2
|
|||
|
|
AIGW2 --> XIAO2
|
|||
|
|
AIGW2 --> STAR2
|
|||
|
|
end
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.8 `xiaozhi_server` 的 MQTT 网关策略(已定)
|
|||
|
|
|
|||
|
|
策略已定:主方案不使用 `xiaozhi-mqtt` 网关。
|
|||
|
|
|
|||
|
|
- 智能锁主链路只使用 `Apache BifroMQ`
|
|||
|
|
- AI 面只使用 `ai-gateway <-> xiaozhi_server` 的 HTTP/WebSocket 会话
|
|||
|
|
- 不引入第二套 MQTT broker,不保留双 broker 共存方案
|
|||
|
|
|
|||
|
|
### 3.9 改进后的推荐方案
|
|||
|
|
|
|||
|
|
推荐做法是:
|
|||
|
|
|
|||
|
|
- 智能锁主实时链路只保留一套 MQTT 基础设施,即 `Apache BifroMQ`
|
|||
|
|
- `xiaozhi_server` 只保留在 AI 能力面,负责 ASR、TTS、Agent、知识库、工具调用
|
|||
|
|
- 明确禁用 `xiaozhi-mqtt` 网关,不在任何环境接入智能锁主链路
|
|||
|
|
|
|||
|
|
对应理解是:
|
|||
|
|
|
|||
|
|
- 锁、APP、网关设备的发现、在线、signaling、事件总线,都走 `Apache BifroMQ`
|
|||
|
|
- WebRTC signaling 仍然走 `Apache BifroMQ`
|
|||
|
|
- 音视频主链路走 `WebRTC + coturn`,P2P/TURN 失败后切到中心媒体转发或 `ZLMediaKit`
|
|||
|
|
- `xiaozhi_server` 只通过 `ai-gateway` 接入,不直接成为锁侧 MQTT broker
|
|||
|
|
|
|||
|
|
这样改完以后,`xiaozhi_server` 不会和 `Apache BifroMQ` 在主方案中发生正面冲突。
|
|||
|
|
|
|||
|
|
### 3.10 执行规范(禁用 `xiaozhi-mqtt`)
|
|||
|
|
|
|||
|
|
为避免双 broker 风险,执行层按以下规范落地:
|
|||
|
|
|
|||
|
|
1. 仅部署并对外开放 `Apache BifroMQ` 的 MQTT 接入。
|
|||
|
|
2. 不部署 `xiaozhi-mqtt-gateway`,或在配置中明确关闭其对外监听。
|
|||
|
|
3. 智能锁、APP、网关设备统一接入 `Apache BifroMQ`。
|
|||
|
|
4. AI 功能统一走 `ai-gateway <-> xiaozhi_server` 的 HTTP/WebSocket,不走 MQTT。
|
|||
|
|
5. 运维检查项中增加“第二 MQTT broker 禁入”巡检规则。
|
|||
|
|
|
|||
|
|
### 3.11 最终建议
|
|||
|
|
|
|||
|
|
对你这个智能锁项目,最稳的版本是:
|
|||
|
|
|
|||
|
|
- `Apache BifroMQ` 是唯一主 MQTT 平台
|
|||
|
|
- `starcloud` 是共享业务能力平台,`starlock` 是租户应用层入口
|
|||
|
|
- `xiaozhi_server` 是 AI 引擎,不是主消息总线
|
|||
|
|
- 不启用 `xiaozhi-mqtt`,避免双 broker 架构复杂度
|
|||
|
|
|
|||
|
|
### 3.12 按你项目落地的真实接线图,Broker 改为 Apache BifroMQ
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart LR
|
|||
|
|
subgraph ClientSide[用户侧]
|
|||
|
|
APP[app-starlock]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph BizSide[业务与控制面]
|
|||
|
|
STARCLOUD[starcloud]
|
|||
|
|
STARLOCK[starlock]
|
|||
|
|
BOOT[device-bootstrap]
|
|||
|
|
ORCH[session state machine]
|
|||
|
|
EVTW[MQTT event worker]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph BrokerSide[消息面]
|
|||
|
|
BIFROMQ[Apache BifroMQ]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph MediaSide[实时媒体]
|
|||
|
|
TURN[coturn]
|
|||
|
|
RELAY[media-relay]
|
|||
|
|
ZLM[ZLMediaKit]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph DeviceSide[设备侧]
|
|||
|
|
GW[WiFi网关锁]
|
|||
|
|
BLE[蓝牙锁]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph AIPlane[AI能力面]
|
|||
|
|
AIGW[ai-gateway]
|
|||
|
|
XIAOZHI[xiaozhi_server]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
APP -->|HTTPS 业务 API| STARLOCK
|
|||
|
|
STARLOCK -->|共享业务 API| STARCLOUD
|
|||
|
|
STARLOCK -->|内部调用| BOOT
|
|||
|
|
STARLOCK -->|内部调用| ORCH
|
|||
|
|
STARLOCK -->|事件消费/回调| EVTW
|
|||
|
|
|
|||
|
|
GW -->|认证/换 MQTT 凭证| BOOT
|
|||
|
|
|
|||
|
|
APP <-->|MQTT over WSS| BIFROMQ
|
|||
|
|
GW <-->|MQTT over TLS| BIFROMQ
|
|||
|
|
|
|||
|
|
ORCH -->|signaling/session control| BIFROMQ
|
|||
|
|
EVTW <-->|订阅事件| BIFROMQ
|
|||
|
|
|
|||
|
|
APP <-->|WebRTC P2P / ZLM 自适应| GW
|
|||
|
|
APP -. TURN fallback .-> TURN
|
|||
|
|
GW -. TURN fallback .-> TURN
|
|||
|
|
APP -. relay fallback .-> RELAY
|
|||
|
|
GW -. relay fallback .-> RELAY
|
|||
|
|
APP -. optional ZLM relay .-> ZLM
|
|||
|
|
GW -. optional ZLM relay .-> ZLM
|
|||
|
|
GW -. 蓝牙透传 .-> BLE
|
|||
|
|
|
|||
|
|
GW -. AI 音频旁路 .-> AIGW
|
|||
|
|
APP -. AI 辅助模式 .-> AIGW
|
|||
|
|
AIGW --> XIAOZHI
|
|||
|
|
AIGW --> STARLOCK
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
这张图对应的边界是:
|
|||
|
|
|
|||
|
|
- `Apache BifroMQ` 只承接在线、发现、signaling、事件通知,不承接大媒体流。
|
|||
|
|
- 主音视频链路按网络质量自适应选择:中好网络优先 `WebRTC + coturn`,弱网优先 `ZLMediaKit`。
|
|||
|
|
- `media-relay` 承接 P2P/TURN 不可用时的中心音视频转发。
|
|||
|
|
- `ZLMediaKit` 提供标准化流媒体转发方案,可作为中心转发实现之一。
|
|||
|
|
- `starcloud` 提供可复用业务能力,`starlock` 负责租户化编排与 APP 入口。
|
|||
|
|
- `xiaozhi_server` 只在 `ai-gateway` 后面提供 ASR、TTS、Agent、知识库、工具调用。
|
|||
|
|
- 用户、权限、套餐、审计等可复用能力优先沉淀在 `starcloud`,`starlock` 负责租户侧业务编排与体验层策略。
|
|||
|
|
|
|||
|
|
### 3.13 精简业务图(管理/评审)
|
|||
|
|
|
|||
|
|
这张图只保留关键角色和主链路,适合评审会快速对齐。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart LR
|
|||
|
|
APP[app-starlock]
|
|||
|
|
STARLOCK[starlock\n租户应用层]
|
|||
|
|
STARCLOUD[starcloud\n共享业务能力]
|
|||
|
|
SESSION[session-orchestrator]
|
|||
|
|
MQ[Apache BifroMQ]
|
|||
|
|
MEDIA[ZLMediaKit / TURN / relay]
|
|||
|
|
DEV[Lock/Gateway]
|
|||
|
|
AI[ai-gateway + xiaozhi]
|
|||
|
|
|
|||
|
|
APP -->|业务 API| STARLOCK
|
|||
|
|
STARLOCK -->|共享业务 API| STARCLOUD
|
|||
|
|
STARLOCK -->|会话编排| SESSION
|
|||
|
|
SESSION --> MQ
|
|||
|
|
APP <-->|信令| MQ
|
|||
|
|
DEV <-->|信令| MQ
|
|||
|
|
APP <-->|音视频自适应| DEV
|
|||
|
|
APP -. 弱网优先 .-> MEDIA
|
|||
|
|
DEV -. 弱网优先 .-> MEDIA
|
|||
|
|
APP -. AI模式 .-> AI
|
|||
|
|
DEV -. AI旁路 .-> AI
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.14 详细业务图(研发/实现)
|
|||
|
|
|
|||
|
|
这张图包含业务层、会话层、媒体层、事件回调与 AI 旁路,适合研发实现和联调。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TB
|
|||
|
|
subgraph Client[客户端与设备]
|
|||
|
|
APP[app-starlock]
|
|||
|
|
GW[Gateway/Lock]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph Biz[业务层]
|
|||
|
|
STARLOCK[starlock\n租户应用层]
|
|||
|
|
STARCLOUD[starcloud\n共享业务API]
|
|||
|
|
PUSH[push/callback]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph SessionPlane[会话与控制面]
|
|||
|
|
SESSION[session-orchestrator]
|
|||
|
|
BOOT[device-bootstrap]
|
|||
|
|
MQ[Apache BifroMQ]
|
|||
|
|
EVT[MQTT event worker]
|
|||
|
|
TRACE[realtime-store]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph MediaPlane[媒体面]
|
|||
|
|
P2P[WebRTC P2P]
|
|||
|
|
TURN[coturn]
|
|||
|
|
ZLM[ZLMediaKit]
|
|||
|
|
RELAY[media-relay]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph AIPlane[AI面]
|
|||
|
|
AIGW[ai-gateway]
|
|||
|
|
XZ[xiaozhi_server]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
APP -->|HTTPS 业务请求| STARLOCK
|
|||
|
|
STARLOCK -->|共享能力调用| STARCLOUD
|
|||
|
|
STARLOCK -->|创建会话| SESSION
|
|||
|
|
STARLOCK --> PUSH
|
|||
|
|
|
|||
|
|
GW -->|设备认证| BOOT
|
|||
|
|
STARLOCK -->|内部调用| BOOT
|
|||
|
|
|
|||
|
|
SESSION -->|会话信令编排| MQ
|
|||
|
|
APP <-->|MQTT/WSS| MQ
|
|||
|
|
GW <-->|MQTT/TLS| MQ
|
|||
|
|
|
|||
|
|
APP -->|网络探测上报| SESSION
|
|||
|
|
GW -->|链路质量上报| SESSION
|
|||
|
|
SESSION -->|中好网络| P2P
|
|||
|
|
SESSION -->|RTC补位| TURN
|
|||
|
|
SESSION -->|弱网优先| ZLM
|
|||
|
|
SESSION -->|最终兜底| RELAY
|
|||
|
|
|
|||
|
|
APP <-->|媒体| P2P
|
|||
|
|
GW <-->|媒体| P2P
|
|||
|
|
APP -. fallback .-> TURN
|
|||
|
|
GW -. fallback .-> TURN
|
|||
|
|
APP -. weak network .-> ZLM
|
|||
|
|
GW -. weak network .-> ZLM
|
|||
|
|
APP -. emergency fallback .-> RELAY
|
|||
|
|
GW -. emergency fallback .-> RELAY
|
|||
|
|
|
|||
|
|
GW -->|事件上报| MQ
|
|||
|
|
MQ --> EVT
|
|||
|
|
EVT -->|业务回调| STARLOCK
|
|||
|
|
SESSION --> TRACE
|
|||
|
|
|
|||
|
|
GW -. AI音频旁路 .-> AIGW
|
|||
|
|
APP -. AI辅助模式 .-> AIGW
|
|||
|
|
AIGW --> XZ
|
|||
|
|
AIGW --> STARLOCK
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 4. 控制面与媒体面分层
|
|||
|
|
|
|||
|
|
### 4.1 控制面
|
|||
|
|
|
|||
|
|
控制面使用:
|
|||
|
|
|
|||
|
|
- HTTPS
|
|||
|
|
- MQTT
|
|||
|
|
|
|||
|
|
控制面承载:
|
|||
|
|
|
|||
|
|
- 登录与鉴权
|
|||
|
|
- 设备绑定与发现
|
|||
|
|
- 会话创建
|
|||
|
|
- 呼叫控制
|
|||
|
|
- 开锁命令
|
|||
|
|
- 在线状态
|
|||
|
|
- 事件通知
|
|||
|
|
|
|||
|
|
### 4.2 媒体面
|
|||
|
|
|
|||
|
|
媒体面使用:
|
|||
|
|
|
|||
|
|
- WebRTC
|
|||
|
|
|
|||
|
|
媒体面承载:
|
|||
|
|
|
|||
|
|
- 视频上行
|
|||
|
|
- 双向音频
|
|||
|
|
- DataChannel 辅助消息
|
|||
|
|
- 录制或云存的旁路扩展
|
|||
|
|
- P2P/TURN 失败后的中心媒体转发
|
|||
|
|
- 基于 `ZLMediaKit` 的流转发
|
|||
|
|
|
|||
|
|
### 4.3 AI 面
|
|||
|
|
|
|||
|
|
AI 面使用:
|
|||
|
|
|
|||
|
|
- `ai-gateway` 与 `xiaozhi_server` 的 WebSocket/HTTP 会话
|
|||
|
|
- 不使用 `xiaozhi` 原生 MQTT+UDP 网关能力,避免引入第二套 MQTT 基础设施
|
|||
|
|
|
|||
|
|
AI 面承载:
|
|||
|
|
|
|||
|
|
- 语音转文本
|
|||
|
|
- TTS
|
|||
|
|
- 意图识别
|
|||
|
|
- 工具调用
|
|||
|
|
- 智能应答
|
|||
|
|
- AI 辅助摘要/关键词提取
|
|||
|
|
|
|||
|
|
## 5. 核心时序图
|
|||
|
|
|
|||
|
|
### 5.1 设备上线与发现
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant Lock as Lock/Gateway
|
|||
|
|
participant Starlock as starlock
|
|||
|
|
participant BifroMQ as Apache BifroMQ
|
|||
|
|
participant App as APP
|
|||
|
|
|
|||
|
|
Lock->>Starlock: 设备认证/获取 MQTT 临时凭证
|
|||
|
|
Starlock-->>Lock: mqtt username/password 或 JWT
|
|||
|
|
Lock->>BifroMQ: 建立 MQTT 连接
|
|||
|
|
Lock->>BifroMQ: 发布 retained presence=online
|
|||
|
|
Lock->>BifroMQ: 发布 retained capabilities
|
|||
|
|
|
|||
|
|
App->>Starlock: 获取门锁列表与权限
|
|||
|
|
App->>Starlock: 申请查看设备在线态
|
|||
|
|
App->>BifroMQ: 订阅锁相关 presence/status topic
|
|||
|
|
BifroMQ-->>App: 推送设备在线与能力信息
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 App 发起对讲,媒体路径自适应
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant App as APP
|
|||
|
|
participant Starlock as starlock
|
|||
|
|
participant Orch as session-orchestrator
|
|||
|
|
participant BifroMQ as Apache BifroMQ
|
|||
|
|
participant Lock as Lock/Gateway
|
|||
|
|
participant TURN as coturn
|
|||
|
|
participant Relay as media-relay
|
|||
|
|
participant ZLM as ZLMediaKit
|
|||
|
|
|
|||
|
|
App->>Starlock: 发起视频/对讲请求
|
|||
|
|
Starlock->>Starlock: 校验用户对该锁的权限
|
|||
|
|
Starlock->>Orch: 创建 realtime session
|
|||
|
|
Orch-->>Starlock: sessionId + signaling topics + rtc config + token
|
|||
|
|
Starlock-->>App: 返回 session 启动信息
|
|||
|
|
|
|||
|
|
Starlock->>BifroMQ: 通知目标锁有呼叫请求
|
|||
|
|
BifroMQ-->>Lock: 推送 incoming call
|
|||
|
|
|
|||
|
|
App->>BifroMQ: 发布 offer
|
|||
|
|
BifroMQ-->>Lock: 转发 offer
|
|||
|
|
Lock->>BifroMQ: 发布 answer
|
|||
|
|
BifroMQ-->>App: 转发 answer
|
|||
|
|
|
|||
|
|
App->>BifroMQ: 发布 ICE candidate
|
|||
|
|
Lock->>BifroMQ: 发布 ICE candidate
|
|||
|
|
|
|||
|
|
Orch->>Orch: 根据 RTT/丢包/NAT/终端能力选择媒体路径
|
|||
|
|
alt 网络良好,优先 P2P
|
|||
|
|
App-->>Lock: WebRTC P2P 建链
|
|||
|
|
else RTC 可用但 P2P 不理想
|
|||
|
|
App-->>TURN: 使用 TURN 中继
|
|||
|
|
Lock-->>TURN: 使用 TURN 中继
|
|||
|
|
else 弱网或高丢包,优先中心转发
|
|||
|
|
Orch->>ZLM: 创建 ZLMediaKit 转发会话
|
|||
|
|
App->>ZLM: 拉流/推流
|
|||
|
|
Lock->>ZLM: 推流/拉流
|
|||
|
|
else P2P/TURN/ZLM 都受限
|
|||
|
|
Orch->>Relay: 创建中心媒体转发会话
|
|||
|
|
App->>Relay: 接入中心音视频转发
|
|||
|
|
Lock->>Relay: 接入中心音视频转发
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
App->>BifroMQ: 会话控制消息 accept/hangup
|
|||
|
|
Lock->>BifroMQ: 会话状态更新
|
|||
|
|
Orch->>Orch: 聚合状态并记录 trace
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2.1 弱网判定与自动切换规则
|
|||
|
|
|
|||
|
|
为了让“弱网优先 `ZLMediaKit`”可执行,建议 `session-orchestrator` 在建链前和通话中都持续评估以下指标:
|
|||
|
|
|
|||
|
|
- RTT:连续 3 个采样窗口平均 RTT `> 250ms`
|
|||
|
|
- 丢包率:上行或下行连续 3 个窗口丢包率 `> 8%`
|
|||
|
|
- 抖动:连续 3 个窗口抖动 `> 30ms`
|
|||
|
|
- 实际可用上行带宽:低于当前音视频档位最低要求的 `1.3x` 安全阈值
|
|||
|
|
- NAT/连通性:ICE 在限定时间内无法形成稳定 candidate pair,或只剩高成本 relay 路径
|
|||
|
|
|
|||
|
|
建议默认策略如下:
|
|||
|
|
|
|||
|
|
1. 建链前网络探测显示 RTT、丢包、抖动都健康时,优先 `WebRTC P2P`。
|
|||
|
|
2. 建链前就已经出现高丢包、复杂 NAT、运营商弱网或企业网限制时,直接优先 `ZLMediaKit`。
|
|||
|
|
3. P2P 已建成但连续 `5-10s` 质量低于阈值时,先尝试降码率、降分辨率、关闭非关键视频层。
|
|||
|
|
4. 降档后仍连续 `10-15s` 不达标时,从 P2P/TURN 自动切到 `ZLMediaKit`。
|
|||
|
|
5. 只有在 `ZLMediaKit` 也不可用,或该设备型号暂不支持对应接入方式时,才退回通用 `media-relay` 兜底。
|
|||
|
|
|
|||
|
|
建议把这些阈值做成可配置项,而不是写死在代码里;不同设备型号、码率档位、音频优先级和运营商环境下,实际阈值会有差异。
|
|||
|
|
|
|||
|
|
### 5.3 AI 旁路模式
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant Lock as Lock/Gateway
|
|||
|
|
participant App as APP
|
|||
|
|
participant Starlock as starlock
|
|||
|
|
participant Orch as session-orchestrator
|
|||
|
|
participant AIGW as ai-gateway
|
|||
|
|
participant Xiao as xiaozhi_server
|
|||
|
|
|
|||
|
|
App->>Starlock: 请求开启 AI 模式
|
|||
|
|
Starlock->>Starlock: 校验 AI 权限/套餐/设备能力
|
|||
|
|
Starlock->>Orch: 为当前会话启用 AI sidecar
|
|||
|
|
Orch->>AIGW: 创建 ai session
|
|||
|
|
AIGW->>Xiao: 建立 AI 对话会话
|
|||
|
|
|
|||
|
|
Lock->>AIGW: 推送音频副本或独立音频流
|
|||
|
|
AIGW->>Xiao: 转发音频
|
|||
|
|
Xiao-->>AIGW: ASR / 意图 / TTS / 工具调用结果
|
|||
|
|
|
|||
|
|
alt AI 辅助模式
|
|||
|
|
AIGW-->>Starlock: 摘要/关键词/告警事件
|
|||
|
|
else AI 应答模式
|
|||
|
|
AIGW-->>Lock: TTS 音频或文本应答
|
|||
|
|
AIGW-->>App: AI 状态与结果
|
|||
|
|
end
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 6. 服务清单与职责设计
|
|||
|
|
|
|||
|
|
### 6.1 `starlock`
|
|||
|
|
|
|||
|
|
角色:租户应用层业务入口。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- 对外提供 APP 业务 API
|
|||
|
|
- 编排 `starcloud` 共享业务能力
|
|||
|
|
- 管理租户/渠道差异化配置
|
|||
|
|
- 生成实时会话请求
|
|||
|
|
- 向 APP 返回会话入口信息
|
|||
|
|
|
|||
|
|
不负责:
|
|||
|
|
|
|||
|
|
- 长连接连接保持
|
|||
|
|
- WebRTC signaling 分发
|
|||
|
|
- 大媒体转发
|
|||
|
|
- 重复实现本应沉淀到 `starcloud` 的通用业务能力
|
|||
|
|
|
|||
|
|
### 6.1.1 `starcloud`
|
|||
|
|
|
|||
|
|
角色:共享业务能力云平台。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- 对下游应用(包括 `starlock`)输出可复用业务 API
|
|||
|
|
- 沉淀用户、权限、套餐、审计等通用能力
|
|||
|
|
- 承载跨项目可复用的业务规则与模型
|
|||
|
|
- 减少同类项目重复开发,提升统一治理能力
|
|||
|
|
|
|||
|
|
### 6.2 `session-orchestrator`
|
|||
|
|
|
|||
|
|
角色:实时会话编排中心。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- 创建 `sessionId`
|
|||
|
|
- 生成 signaling topic
|
|||
|
|
- 生成短期 session token
|
|||
|
|
- 聚合会话状态:`pending`、`ringing`、`accepted`、`connected`、`ended`
|
|||
|
|
- 管理媒体兜底策略:`p2p`、`turn`、`relay`、`zlmediakit`
|
|||
|
|
- 根据网络质量阈值执行媒体路径切换
|
|||
|
|
- 管理 AI sidecar 生命周期
|
|||
|
|
- 写会话 trace、诊断日志
|
|||
|
|
|
|||
|
|
不负责:
|
|||
|
|
|
|||
|
|
- 用户权限判断
|
|||
|
|
- 业务订单/套餐判断
|
|||
|
|
- 持久化完整业务模型
|
|||
|
|
|
|||
|
|
#### 为什么需要它
|
|||
|
|
|
|||
|
|
`session-orchestrator` 这个名字容易让人误以为它是一个很重的“中央调度服务”,其实不是。
|
|||
|
|
|
|||
|
|
它本质上只是一个“实时会话状态机”,作用是把下面几类逻辑从 `starlock` 的普通业务接口里剥出来:
|
|||
|
|
|
|||
|
|
- 创建一次实时会话
|
|||
|
|
- 给这次会话分配 `sessionId`
|
|||
|
|
- 给 APP 和设备生成本次会话可用的 signaling topic
|
|||
|
|
- 生成短期 session token / TURN 凭证
|
|||
|
|
- 在需要时切换中心媒体转发或 `ZLMediaKit` 流转发
|
|||
|
|
- 维护这次会话的状态变化:响铃、接听、连接成功、挂断、异常结束
|
|||
|
|
|
|||
|
|
换句话说,它不决定“这个人有没有权限打这个锁”;这类权限决策通常由 `starlock` 发起并结合 `starcloud` 共享能力完成。它只负责“既然已经允许打了,那这通会话怎么被安全地建起来并结束”。
|
|||
|
|
|
|||
|
|
#### 为什么必须独立服务
|
|||
|
|
|
|||
|
|
按当前决策,`session-orchestrator` 必须从第一阶段独立部署,理由是:
|
|||
|
|
|
|||
|
|
- 视频会话控制与业务 API 解耦,避免 `starlock` 发布节奏被实时链路牵制
|
|||
|
|
- 统一替代历史 UDP 分散控制,形成中心化状态机治理
|
|||
|
|
- 路由切换策略(`p2p/turn/zlmediakit/relay`)可独立演进
|
|||
|
|
- 会话可观测性(trace、失败原因、切路记录)可统一沉淀
|
|||
|
|
|
|||
|
|
落地约束:
|
|||
|
|
|
|||
|
|
1. `starlock` 只负责权限校验、业务编排、对外 API。
|
|||
|
|
2. `session-orchestrator` 负责会话状态机、控制命令、超时收敛、媒体路径决策。
|
|||
|
|
3. APP/设备只认会话级 topic 与短期 token,不直接依赖业务后台内部状态。
|
|||
|
|
|
|||
|
|
#### 会话控制协议建议(替代旧 UDP 开始/结束协议)
|
|||
|
|
|
|||
|
|
建议把“开始/结束”从 UDP 专用协议,升级为统一会话控制事件:
|
|||
|
|
|
|||
|
|
- `sessions/{sessionId}/control`:`invite`、`ringing`、`accept`、`reject`、`hangup`、`switch-route`、`terminate`
|
|||
|
|
- `sessions/{sessionId}/status`:`pending`、`connecting`、`connected`、`degraded`、`switching_route`、`ended`、`failed`
|
|||
|
|
|
|||
|
|
每条控制事件都带:
|
|||
|
|
|
|||
|
|
- `sessionId`
|
|||
|
|
- `eventId`(单调递增)
|
|||
|
|
- `from`(app/device/orchestrator)
|
|||
|
|
- `ts`
|
|||
|
|
- `ackTimeoutMs`
|
|||
|
|
|
|||
|
|
处理规则:
|
|||
|
|
|
|||
|
|
1. 未 ACK 的控制事件按策略重发。
|
|||
|
|
2. 超过最大重试进入 `timeout` 或 `failed`。
|
|||
|
|
3. 任一终态都由 `session-orchestrator` 写最终状态并触发资源清理。
|
|||
|
|
|
|||
|
|
#### 归属结论与简化实现(提炼版)
|
|||
|
|
|
|||
|
|
归属结论:
|
|||
|
|
|
|||
|
|
- `session-orchestrator` 属于云端实时基础设施层,不属于 APP 端,也不属于设备端。
|
|||
|
|
- 它是被 `starlock` 调用的独立服务。
|
|||
|
|
- `starlock` 负责业务授权与编排,`session-orchestrator` 负责视频会话控制与状态机收敛。
|
|||
|
|
|
|||
|
|
技术建议:
|
|||
|
|
|
|||
|
|
- 首选 Go 实现独立服务(更适合高并发会话状态控制)。
|
|||
|
|
|
|||
|
|
|
|||
|
|
简单实现方法(MVP):
|
|||
|
|
|
|||
|
|
1. 先独立部署 `session-orchestrator`,并配套 `Redis`(热状态/重试队列)与 `MySQL`(会话记录/审计)。
|
|||
|
|
2. 先开三个内部接口:创建会话、结束会话、开启 AI sidecar,`starlock` 只通过这三个接口编排实时流程。
|
|||
|
|
3. APP/设备统一使用会话级 topic:`sessions/{sessionId}/control` 与 `sessions/{sessionId}/status`,不再用旧 UDP 协议字段直接控制开始/结束。
|
|||
|
|
4. 按固定状态机落地:`pending -> ringing -> accepted -> connecting -> connected -> ended/failed`,并实现 ACK 超时重试。
|
|||
|
|
5. 媒体选路先做最小闭环:`p2p -> turn -> zlmediakit -> relay`,由 `session-orchestrator` 统一下发 `switch-route`。
|
|||
|
|
6. 灰度迁移旧方案:先镜像上报、再双栈并行、最后下线旧 UDP 开始/结束控制。
|
|||
|
|
|
|||
|
|
### 6.3 `Apache BifroMQ`
|
|||
|
|
|
|||
|
|
角色:发现、在线、信令总线。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- 设备 presence
|
|||
|
|
- retained capabilities
|
|||
|
|
- signaling 消息传递
|
|||
|
|
- 控制类 topic 分发
|
|||
|
|
- ACL 与连接鉴权
|
|||
|
|
|
|||
|
|
不负责:
|
|||
|
|
|
|||
|
|
- 大媒体流
|
|||
|
|
- 复杂业务校验
|
|||
|
|
|
|||
|
|
### 6.4 `coturn`
|
|||
|
|
|
|||
|
|
角色:RTC 网络兜底。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- STUN
|
|||
|
|
- TURN relay
|
|||
|
|
- 临时凭证校验
|
|||
|
|
|
|||
|
|
### 6.4.1 `media-relay`
|
|||
|
|
|
|||
|
|
角色:中心服务器音视频转发兜底。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- 在 P2P/TURN 都不可用时承接音视频转发
|
|||
|
|
- 兼容旧设备或弱网场景
|
|||
|
|
- 为录制、审计、媒体后处理保留中心接入点
|
|||
|
|
- 作为一个能力层存在,不要求必须单独做成自研服务
|
|||
|
|
|
|||
|
|
### 6.4.2 `ZLMediaKit`
|
|||
|
|
|
|||
|
|
角色:中心媒体转发能力的优先实现方案。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- 提供比自定义 relay 更标准的媒体转发实现
|
|||
|
|
- 支持 WebRTC、推流、拉流、转协议和中心媒体接入
|
|||
|
|
- 可直接承接 `media-relay` 这层能力,逐步替代自研转发逻辑
|
|||
|
|
- 在弱网、高抖动、高丢包场景下,可作为比 P2P 更稳的优先媒体方案
|
|||
|
|
|
|||
|
|
#### 结合 WebRTC 怎么理解
|
|||
|
|
|
|||
|
|
- 中好网络时,首选仍然是 App 与设备直接做 WebRTC P2P。
|
|||
|
|
- 弱网、高丢包、复杂 NAT 或需要录制审计时,可以直接优先 `ZLMediaKit`。
|
|||
|
|
- 如果仍希望保持 RTC 直连能力,可让 `coturn` 作为 RTC 路径补位。
|
|||
|
|
- 当 `ZLMediaKit` 也受限或需要特殊兼容时,再切到更通用的中心转发能力。
|
|||
|
|
- 这时中心转发不一定再单独做一套自研 `media-relay` 服务,可以直接由 `ZLMediaKit` 承担。
|
|||
|
|
|
|||
|
|
#### 弱网下哪个更适合作为首选
|
|||
|
|
|
|||
|
|
- 如果目标是“弱网下更稳”,通常优先 `ZLMediaKit` 转发,而不是 WebRTC P2P。
|
|||
|
|
- 原因是 P2P 更依赖两端实时网络质量、NAT 情况和上行稳定性;弱网下抖动、重传、带宽突降会更明显暴露出来。
|
|||
|
|
- `ZLMediaKit` 走中心接入点,更容易做统一的拥塞控制、转协议、录制和链路治理,所以在弱网场景更适合作为首选方案。
|
|||
|
|
- 只有在网络质量较好、希望最低时延和最低中心带宽成本时,才应把 WebRTC P2P 放到第一位。
|
|||
|
|
|
|||
|
|
|
|||
|
|
- 如果你的意思是“完全不要中心转发能力”,不建议。
|
|||
|
|
- 原因是 WebRTC P2P 和 TURN 仍然会遇到设备兼容性、弱网、企业网限制、录制审计、协议桥接等场景,这些场景仍需要中心接入点。
|
|||
|
|
- 更合理的做法是:保留中心转发这层能力,但把实现尽量收敛到 `ZLMediaKit`,不要长期维护两套并行转发系统。
|
|||
|
|
|
|||
|
|
### 6.5 `ai-gateway`
|
|||
|
|
|
|||
|
|
角色:AI 桥接层。
|
|||
|
|
|
|||
|
|
关键职责:
|
|||
|
|
|
|||
|
|
- 为设备或会话创建 AI session
|
|||
|
|
- 对接 `xiaozhi_server`
|
|||
|
|
- 在 AI 模式和业务模式之间做协议适配
|
|||
|
|
- 把 AI 结果回送 `starlock`、APP 或设备
|
|||
|
|
|
|||
|
|
不负责:
|
|||
|
|
|
|||
|
|
- 用户体系
|
|||
|
|
- 主对讲状态机
|
|||
|
|
|
|||
|
|
### 6.6 `event-listener` 是否还能保留
|
|||
|
|
|
|||
|
|
这个问题要拆成两类:
|
|||
|
|
|
|||
|
|
#### 类别一:实时通知分发
|
|||
|
|
|
|||
|
|
这部分很多是可以用 MQTT 做的。
|
|||
|
|
|
|||
|
|
例如:
|
|||
|
|
|
|||
|
|
- 设备上线/下线通知
|
|||
|
|
- 门锁状态变化通知
|
|||
|
|
- 振铃通知
|
|||
|
|
- 会话状态变化通知
|
|||
|
|
- AI 摘要完成通知
|
|||
|
|
|
|||
|
|
这类消息天然适合通过 MQTT 分发,因为它们是轻量消息、低延迟、面向订阅者的实时通知。
|
|||
|
|
|
|||
|
|
#### 类别二:业务事件消费与回调
|
|||
|
|
|
|||
|
|
这部分不建议只靠 MQTT 替代。
|
|||
|
|
|
|||
|
|
例如:
|
|||
|
|
|
|||
|
|
- 设备上报开锁记录
|
|||
|
|
- 报警事件
|
|||
|
|
- 图片/视频文件处理
|
|||
|
|
- 回调 `starlock` 或其它 HTTP 接口
|
|||
|
|
- 做重试、幂等、失败补偿、落库
|
|||
|
|
|
|||
|
|
这些更像“异步业务任务”,而不只是“通知”。如果只用 MQTT 裸消费,后面你很容易遇到这些问题:
|
|||
|
|
|
|||
|
|
- 消费失败后的补偿不清楚
|
|||
|
|
- 回调重试策略分散
|
|||
|
|
- 消息被订阅了,但业务并没有真正处理成功
|
|||
|
|
- 文件处理、转码、上传对象存储这类任务不适合留在纯通知链路里
|
|||
|
|
|
|||
|
|
所以更合理的做法是:
|
|||
|
|
|
|||
|
|
- 用 MQTT 承担“事件通知总线”
|
|||
|
|
- 保留一个事件消费器来做“业务处理和回调”
|
|||
|
|
|
|||
|
|
这个消费器仍然可以继续叫 `event-listener`,但它的角色要重新定义。
|
|||
|
|
|
|||
|
|
#### 推荐的新定义
|
|||
|
|
|
|||
|
|
建议把 `event-listener` 改成:
|
|||
|
|
|
|||
|
|
- 订阅 MQTT 事件主题
|
|||
|
|
- 负责把事件写入业务处理流水
|
|||
|
|
- 负责做 HTTP 回调、对象存储、媒体后处理、重试和幂等
|
|||
|
|
|
|||
|
|
也就是说,它不再是老架构里“星图协议事件接收器”,而是“MQTT 事件消费器 + 业务回调 worker”。
|
|||
|
|
|
|||
|
|
这个改法是最平滑的,因为:
|
|||
|
|
|
|||
|
|
- 设备侧事件入口可以改成 MQTT
|
|||
|
|
- 你们现有很多事件处理逻辑还能保留
|
|||
|
|
- `starlock` 不需要直接订阅所有低层设备消息
|
|||
|
|
|
|||
|
|
## 6.7 对你当前项目的更实际建议
|
|||
|
|
|
|||
|
|
结合你现在的系统,我建议这样落:
|
|||
|
|
|
|||
|
|
### 第一阶段
|
|||
|
|
|
|||
|
|
- 独立部署 `session-orchestrator` 服务
|
|||
|
|
- `starlock` 专注业务授权与编排,实时会话状态机由 `session-orchestrator` 承担
|
|||
|
|
- 新增通用业务能力优先落在 `starcloud`,再由 `starlock` 编排调用
|
|||
|
|
- 用 Apache BifroMQ 做 presence + signaling
|
|||
|
|
- 保留现有中心服务器音视频转发作为兜底
|
|||
|
|
- 直接把 `ZLMediaKit` 作为中心转发优先实现,逐步下线自研 relay
|
|||
|
|
- 保留一个 `event-listener` worker,改为订阅 MQTT 事件并做业务回调
|
|||
|
|
|
|||
|
|
### 第二阶段
|
|||
|
|
|
|||
|
|
- 根据会话量扩容 `session-orchestrator`(多实例 + 会话分片/一致性哈希)
|
|||
|
|
- 如果事件量很大,再把 `event-listener` 拆成多类 worker:
|
|||
|
|
- 业务回调 worker
|
|||
|
|
- 媒体处理 worker
|
|||
|
|
- AI 结果消费 worker
|
|||
|
|
|
|||
|
|
### 一句话判断
|
|||
|
|
|
|||
|
|
- `session-orchestrator` 从第一阶段就独立部署,“实时会话状态机”不内嵌到 `starlock`
|
|||
|
|
- `event-listener` 的通知入口可以迁到 MQTT,但“业务处理与回调”仍然建议保留专门消费者,不要只靠 MQTT 本身完成
|
|||
|
|
|
|||
|
|
## 7. 设备形态建议
|
|||
|
|
|
|||
|
|
### 7.1 推荐的设备侧分层
|
|||
|
|
|
|||
|
|
对你当前项目,`WiFi锁` 默认按网关锁能力建设,可直接承接高能力终端职责。
|
|||
|
|
|
|||
|
|
如果后续扩展到多设备形态(低功耗锁体 + 高能力网关),再按下面方式分层:
|
|||
|
|
|
|||
|
|
- 锁体 MCU:负责电机、门磁、电池、基础控制协议
|
|||
|
|
- 网关/猫眼/门口机/Linux SoC:负责摄像头、麦克风、编码、WebRTC、AI 侧接入
|
|||
|
|
|
|||
|
|
### 7.2 不建议的做法
|
|||
|
|
|
|||
|
|
当前项目因为 `WiFi锁` 已是网关锁形态,本节主要用于后续低功耗设备线扩展时参考。
|
|||
|
|
|
|||
|
|
不建议把完整 WebRTC 栈强行压到能力非常有限的锁体 MCU 上,除非你已经确认:
|
|||
|
|
|
|||
|
|
- 编码能力足够
|
|||
|
|
- 网络和 TLS 栈足够稳定
|
|||
|
|
- 长连接状态机可维护
|
|||
|
|
- 双讲回声、抖动和弱网体验可接受
|
|||
|
|
|
|||
|
|
如果只是探索方向,可以参考 `libpeer-main` 作为设备侧 C WebRTC 库候选,但量产方案仍应优先基于更成熟的端侧平台或网关代理。
|
|||
|
|
|
|||
|
|
## 8. 接口草案
|
|||
|
|
|
|||
|
|
以下接口草案按“APP -> starlock -> realtime services”关系设计。
|
|||
|
|
|
|||
|
|
### 8.1 APP 调 `starlock`
|
|||
|
|
|
|||
|
|
#### 创建会话
|
|||
|
|
|
|||
|
|
`POST /api/realtime/sessions`
|
|||
|
|
|
|||
|
|
请求示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"deviceId": "lock_123456",
|
|||
|
|
"sessionType": "talk",
|
|||
|
|
"mediaPolicy": {
|
|||
|
|
"strategy": "adaptive",
|
|||
|
|
"preferP2PWhenGoodNetwork": true,
|
|||
|
|
"preferZlmWhenWeakNetwork": true,
|
|||
|
|
"autoSwitch": true
|
|||
|
|
},
|
|||
|
|
"media": {
|
|||
|
|
"audio": true,
|
|||
|
|
"video": true,
|
|||
|
|
"dataChannel": true
|
|||
|
|
},
|
|||
|
|
"aiMode": "disabled"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
响应示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"sessionId": "sess_01HT...",
|
|||
|
|
"role": "caller",
|
|||
|
|
"mqtt": {
|
|||
|
|
"brokerUrl": "wss://mq.example.com:8084/mqtt",
|
|||
|
|
"clientId": "app_user_1001_sess_01HT",
|
|||
|
|
"username": "app_user_1001",
|
|||
|
|
"password": "temp-password",
|
|||
|
|
"topics": {
|
|||
|
|
"signalPublish": "sessions/sess_01HT/signal/app",
|
|||
|
|
"signalSubscribe": "sessions/sess_01HT/signal/device",
|
|||
|
|
"control": "sessions/sess_01HT/control"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"rtc": {
|
|||
|
|
"iceServers": [
|
|||
|
|
{
|
|||
|
|
"urls": ["stun:turn.example.com:3478"]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"urls": ["turn:turn.example.com:3478?transport=udp"],
|
|||
|
|
"username": "turn-user",
|
|||
|
|
"credential": "turn-pass"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"mediaRoute": {
|
|||
|
|
"selected": "p2p",
|
|||
|
|
"candidates": ["p2p", "turn", "zlmediakit", "relay"],
|
|||
|
|
"switchPolicy": {
|
|||
|
|
"rttMs": 250,
|
|||
|
|
"packetLossRate": 0.08,
|
|||
|
|
"jitterMs": 30,
|
|||
|
|
"degradeDurationSec": 10
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"sessionToken": "jwt-or-paseto"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 结束会话
|
|||
|
|
|
|||
|
|
`POST /api/realtime/sessions/{sessionId}/terminate`
|
|||
|
|
|
|||
|
|
#### 查询会话详情
|
|||
|
|
|
|||
|
|
`GET /api/realtime/sessions/{sessionId}`
|
|||
|
|
|
|||
|
|
#### 开启 AI 模式
|
|||
|
|
|
|||
|
|
`POST /api/realtime/sessions/{sessionId}/ai`
|
|||
|
|
|
|||
|
|
请求示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"mode": "assistant",
|
|||
|
|
"voiceProfile": "default",
|
|||
|
|
"intentScope": ["intercom", "unlock", "qa"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.2 `starlock` 调 `session-orchestrator`
|
|||
|
|
|
|||
|
|
#### 创建内部会话
|
|||
|
|
|
|||
|
|
`POST /internal/realtime/sessions`
|
|||
|
|
|
|||
|
|
请求示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"sessionId": "sess_01HT...",
|
|||
|
|
"tenantId": 1,
|
|||
|
|
"userId": 1001,
|
|||
|
|
"deviceId": "lock_123456",
|
|||
|
|
"sessionType": "talk",
|
|||
|
|
"mediaPolicy": {
|
|||
|
|
"audio": true,
|
|||
|
|
"video": true,
|
|||
|
|
"p2pPreferred": true,
|
|||
|
|
"turnFallback": true,
|
|||
|
|
"zlmPreferredWhenWeakNetwork": true,
|
|||
|
|
"autoSwitch": true,
|
|||
|
|
"thresholds": {
|
|||
|
|
"rttMs": 250,
|
|||
|
|
"packetLossRate": 0.08,
|
|||
|
|
"jitterMs": 30,
|
|||
|
|
"degradeDurationSec": 10
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"authContext": {
|
|||
|
|
"familyId": 2002,
|
|||
|
|
"permissionSnapshot": ["device.talk", "device.view"]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
响应示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"sessionId": "sess_01HT...",
|
|||
|
|
"mqttTopics": {
|
|||
|
|
"deviceSignal": "sessions/sess_01HT/signal/device",
|
|||
|
|
"appSignal": "sessions/sess_01HT/signal/app",
|
|||
|
|
"control": "sessions/sess_01HT/control"
|
|||
|
|
},
|
|||
|
|
"sessionToken": "signed-token",
|
|||
|
|
"mediaRoute": {
|
|||
|
|
"selected": "p2p",
|
|||
|
|
"fallbackOrder": ["turn", "zlmediakit", "relay"]
|
|||
|
|
},
|
|||
|
|
"turnCredential": {
|
|||
|
|
"username": "turn-u",
|
|||
|
|
"credential": "turn-c",
|
|||
|
|
"ttl": 300
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 上报业务结束态
|
|||
|
|
|
|||
|
|
`POST /internal/realtime/sessions/{sessionId}/finalize`
|
|||
|
|
|
|||
|
|
#### 开启 AI sidecar
|
|||
|
|
|
|||
|
|
`POST /internal/realtime/sessions/{sessionId}/ai-sidecar`
|
|||
|
|
|
|||
|
|
### 8.3 设备 bootstrap 接口
|
|||
|
|
|
|||
|
|
设备不应长期写死 MQTT 密钥,建议通过 `starlock` 或设备接入子服务换取短期凭证。
|
|||
|
|
|
|||
|
|
`POST /internal/device/bootstrap`
|
|||
|
|
|
|||
|
|
请求示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"deviceId": "lock_123456",
|
|||
|
|
"firmwareVersion": "2.3.1",
|
|||
|
|
"nonce": "abc123",
|
|||
|
|
"signature": "device-signature"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.4 `starlock` 调 `starcloud` 共享业务 API
|
|||
|
|
|
|||
|
|
#### 权限快照与策略校验
|
|||
|
|
|
|||
|
|
`POST /internal/starcloud/policy/evaluate`
|
|||
|
|
|
|||
|
|
请求示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"tenantId": 1,
|
|||
|
|
"userId": 1001,
|
|||
|
|
"deviceId": "lock_123456",
|
|||
|
|
"action": "device.talk",
|
|||
|
|
"context": {
|
|||
|
|
"familyId": 2002,
|
|||
|
|
"channel": "app-starlock"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
响应示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"allow": true,
|
|||
|
|
"policyVersion": "pcv_20260422_01",
|
|||
|
|
"permissionSnapshot": ["device.talk", "device.view"],
|
|||
|
|
"reason": "matched-tenant-policy"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
响应示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"mqtt": {
|
|||
|
|
"clientId": "lock_123456",
|
|||
|
|
"username": "lock_123456",
|
|||
|
|
"password": "temporary-secret",
|
|||
|
|
"expireAt": 1713700000
|
|||
|
|
},
|
|||
|
|
"topics": {
|
|||
|
|
"presence": "locks/lock_123456/presence",
|
|||
|
|
"capabilities": "locks/lock_123456/capabilities",
|
|||
|
|
"commands": "locks/lock_123456/commands",
|
|||
|
|
"signal": "locks/lock_123456/signals"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9. Apache BifroMQ Topic 设计
|
|||
|
|
|
|||
|
|
### 9.1 设备级 topic
|
|||
|
|
|
|||
|
|
- `locks/{deviceId}/presence`
|
|||
|
|
- `locks/{deviceId}/capabilities`
|
|||
|
|
- `locks/{deviceId}/status`
|
|||
|
|
- `locks/{deviceId}/commands`
|
|||
|
|
- `locks/{deviceId}/events`
|
|||
|
|
- `locks/{deviceId}/signals`
|
|||
|
|
|
|||
|
|
#### 用途说明
|
|||
|
|
|
|||
|
|
- `presence`:在线/离线,建议 retained + LWT
|
|||
|
|
- `capabilities`:设备支持的编码、AI、摄像头、麦克风等能力,建议 retained
|
|||
|
|
- `status`:电量、网络质量、门状态、当前是否忙
|
|||
|
|
- `commands`:来自后台或 APP 的设备控制命令
|
|||
|
|
- `events`:设备产生的业务事件
|
|||
|
|
- `signals`:设备级呼叫通知或预唤起 signaling
|
|||
|
|
|
|||
|
|
### 9.2 会话级 topic
|
|||
|
|
|
|||
|
|
- `sessions/{sessionId}/signal/app`
|
|||
|
|
- `sessions/{sessionId}/signal/device`
|
|||
|
|
- `sessions/{sessionId}/control`
|
|||
|
|
- `sessions/{sessionId}/status`
|
|||
|
|
- `sessions/{sessionId}/ai-events`
|
|||
|
|
|
|||
|
|
### 9.3 消息类型建议
|
|||
|
|
|
|||
|
|
`signal/*` 统一使用以下类型:
|
|||
|
|
|
|||
|
|
- `offer`
|
|||
|
|
- `answer`
|
|||
|
|
- `candidate`
|
|||
|
|
- `restart-ice`
|
|||
|
|
|
|||
|
|
`control` 使用:
|
|||
|
|
|
|||
|
|
- `ringing`
|
|||
|
|
- `accept`
|
|||
|
|
- `reject`
|
|||
|
|
- `hangup`
|
|||
|
|
- `mute`
|
|||
|
|
- `unmute`
|
|||
|
|
- `pause-video`
|
|||
|
|
- `resume-video`
|
|||
|
|
|
|||
|
|
`status` 使用:
|
|||
|
|
|
|||
|
|
- `pending`
|
|||
|
|
- `connecting`
|
|||
|
|
- `connected`
|
|||
|
|
- `reconnecting`
|
|||
|
|
- `ended`
|
|||
|
|
- `error`
|
|||
|
|
|
|||
|
|
### 9.4 ACL 建议
|
|||
|
|
|
|||
|
|
APP 在某个会话中只允许:
|
|||
|
|
|
|||
|
|
- 发布:`sessions/{sessionId}/signal/app`
|
|||
|
|
- 订阅:`sessions/{sessionId}/signal/device`
|
|||
|
|
- 发布/订阅:`sessions/{sessionId}/control`、`sessions/{sessionId}/status`
|
|||
|
|
|
|||
|
|
设备在某个会话中只允许:
|
|||
|
|
|
|||
|
|
- 发布:`sessions/{sessionId}/signal/device`
|
|||
|
|
- 订阅:`sessions/{sessionId}/signal/app`
|
|||
|
|
- 发布/订阅:`sessions/{sessionId}/control`、`sessions/{sessionId}/status`
|
|||
|
|
|
|||
|
|
这样可以避免跨会话串话和 topic 污染。
|
|||
|
|
|
|||
|
|
## 10. Session Token 设计
|
|||
|
|
|
|||
|
|
### 10.1 设计目标
|
|||
|
|
|
|||
|
|
session token 只表达“某个主体在某个短会话里的实时权限”,不重复承载完整业务模型。
|
|||
|
|
|
|||
|
|
### 10.2 推荐字段
|
|||
|
|
|
|||
|
|
推荐使用 JWT 或 PASETO,字段如下:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"iss": "starlock",
|
|||
|
|
"aud": "realtime",
|
|||
|
|
"sub": "user:1001",
|
|||
|
|
"sid": "sess_01HT...",
|
|||
|
|
"did": "lock_123456",
|
|||
|
|
"role": "caller",
|
|||
|
|
"scp": ["signal", "rtc", "ai:disabled"],
|
|||
|
|
"tenant": 1,
|
|||
|
|
"family": 2002,
|
|||
|
|
"exp": 1713700300,
|
|||
|
|
"nbf": 1713700000,
|
|||
|
|
"jti": "uuid"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 10.3 说明
|
|||
|
|
|
|||
|
|
- `sid`:绑定单个会话
|
|||
|
|
- `did`:绑定单个设备
|
|||
|
|
- `role`:`caller`、`callee`、`observer`、`ai-sidecar`
|
|||
|
|
- `scp`:实时权限范围,如 `signal`、`rtc`、`ai`、`record`
|
|||
|
|
- 过期时间建议 5 到 10 分钟
|
|||
|
|
|
|||
|
|
### 10.4 验证位置
|
|||
|
|
|
|||
|
|
- `session-orchestrator` 验证 token
|
|||
|
|
- MQTT ACL 网关可基于 token 生成动态权限
|
|||
|
|
- TURN 凭证由 `session-orchestrator` 基于 session token 派生
|
|||
|
|
- `ai-gateway` 验证是否允许 AI 接入
|
|||
|
|
|
|||
|
|
## 11. 数据模型建议
|
|||
|
|
|
|||
|
|
### 11.1 `starlock` 保存
|
|||
|
|
|
|||
|
|
- `users`
|
|||
|
|
- `families`
|
|||
|
|
- `locks`
|
|||
|
|
- `family_lock_members`
|
|||
|
|
- `device_permissions`
|
|||
|
|
- `realtime_session_records`
|
|||
|
|
- `ai_usage_records`
|
|||
|
|
|
|||
|
|
### 11.2 新实时项目保存
|
|||
|
|
|
|||
|
|
- `device_presence_snapshot`
|
|||
|
|
- `device_capability_snapshot`
|
|||
|
|
- `realtime_session_state`
|
|||
|
|
- `realtime_session_trace`
|
|||
|
|
- `signaling_audit_log`
|
|||
|
|
- `ai_session_state`
|
|||
|
|
|
|||
|
|
### 11.3 数据归属原则
|
|||
|
|
|
|||
|
|
- 用户与业务归属只认 `starlock`
|
|||
|
|
- 新实时项目只保存运行时弱状态和诊断数据
|
|||
|
|
- 异常恢复时可允许丢失部分弱状态,但不能影响业务主数据
|
|||
|
|
|
|||
|
|
## 12. AI 接入策略
|
|||
|
|
|
|||
|
|
### 12.1 三种模式
|
|||
|
|
|
|||
|
|
#### 模式一:`human_to_human`
|
|||
|
|
|
|||
|
|
纯 APP 与设备对讲。
|
|||
|
|
|
|||
|
|
#### 模式二:`human_assisted`
|
|||
|
|
|
|||
|
|
AI 作为旁路助手,提供:
|
|||
|
|
|
|||
|
|
- 转写
|
|||
|
|
- 摘要
|
|||
|
|
- 关键词告警
|
|||
|
|
- 指令识别
|
|||
|
|
|
|||
|
|
#### 模式三:`human_to_ai`
|
|||
|
|
|
|||
|
|
用户直接与设备上的 AI 交互,设备通过 `ai-gateway` 接入 `xiaozhi_server`。
|
|||
|
|
|
|||
|
|
### 12.2 推荐优先级
|
|||
|
|
|
|||
|
|
上线顺序建议是:
|
|||
|
|
|
|||
|
|
1. 先做人对人对讲
|
|||
|
|
2. 再做 AI 辅助
|
|||
|
|
3. 最后做设备直连 AI 应答
|
|||
|
|
|
|||
|
|
### 12.3 为什么 AI 必须旁路化
|
|||
|
|
|
|||
|
|
因为 AI 是高延迟、可失败、可替换的能力。如果把它直接嵌入主通话状态机:
|
|||
|
|
|
|||
|
|
- AI 延迟会拖慢接听体验
|
|||
|
|
- AI 故障会中断主通话
|
|||
|
|
- 后续替换 `xiaozhi_server` 成本高
|
|||
|
|
|
|||
|
|
## 13. 演进路径
|
|||
|
|
|
|||
|
|
### Phase 1:发现与在线迁移
|
|||
|
|
|
|||
|
|
目标:把设备发现、在线状态、基础 signaling 从 `scd` 拆到 Apache BifroMQ。
|
|||
|
|
|
|||
|
|
交付:
|
|||
|
|
|
|||
|
|
- 设备 bootstrap
|
|||
|
|
- MQTT 连接鉴权
|
|||
|
|
- presence / capability / status topic
|
|||
|
|
- APP 通过 `starlock` 获取设备在线态
|
|||
|
|
|
|||
|
|
### Phase 2:WebRTC 对讲上线
|
|||
|
|
|
|||
|
|
目标:让音视频主链路切到 WebRTC。
|
|||
|
|
|
|||
|
|
交付:
|
|||
|
|
|
|||
|
|
- APP 端 WebRTC
|
|||
|
|
- 设备或网关端 WebRTC
|
|||
|
|
- TURN 兜底
|
|||
|
|
- 中心媒体转发兜底
|
|||
|
|
- `ZLMediaKit` 转发方案打通
|
|||
|
|
- signaling 全链路打通
|
|||
|
|
|
|||
|
|
### Phase 3:AI 辅助模式上线
|
|||
|
|
|
|||
|
|
目标:接入 `xiaozhi_server`,但不侵入主媒体链路。
|
|||
|
|
|
|||
|
|
交付:
|
|||
|
|
|
|||
|
|
- ai-gateway
|
|||
|
|
- AI sidecar
|
|||
|
|
- 转写/摘要/命令识别
|
|||
|
|
|
|||
|
|
### Phase 4:旧通信层逐步退役
|
|||
|
|
|
|||
|
|
目标:减少对 `starchart-sls1` 中发现和媒体 relay 能力的依赖。
|
|||
|
|
|
|||
|
|
保留项可按实际评估:
|
|||
|
|
|
|||
|
|
- 某些设备尚未迁移时的兼容 relay
|
|||
|
|
- 某些 RPC 查询能力
|
|||
|
|
- 事件回调历史逻辑
|
|||
|
|
|
|||
|
|
## 14. 风险与决策点
|
|||
|
|
|
|||
|
|
### 14.1 最大技术风险
|
|||
|
|
|
|||
|
|
- 设备端是否真有能力稳定跑 WebRTC
|
|||
|
|
- 音频 codec 选型是否统一
|
|||
|
|
- 双讲回声与弱网体验是否可接受
|
|||
|
|
- TURN 成本与带宽预算
|
|||
|
|
|
|||
|
|
### 14.2 关键决策点
|
|||
|
|
|
|||
|
|
已经定下:
|
|||
|
|
|
|||
|
|
1. WebRTC 终端跑在锁体、网关
|
|||
|
|
2. 音频 codec 兼容 G711 桥接
|
|||
|
|
3. 会话信令完全走 MQTT
|
|||
|
|
4. AI 能提供的功能都用上
|
|||
|
|
|
|||
|
|
## 15. 推荐结论
|
|||
|
|
|
|||
|
|
最终推荐方案如下:
|
|||
|
|
|
|||
|
|
- `starcloud`:共享业务能力主平台
|
|||
|
|
- `starlock`:租户化应用层与 APP 业务入口
|
|||
|
|
- `Apache BifroMQ`:发现、在线、会话 signaling
|
|||
|
|
- `session-orchestrator`:实时会话编排中心
|
|||
|
|
- `coturn`:RTC 第一层兜底
|
|||
|
|
- `media-relay` 能力层,由 `ZLMediaKit` 优先实现:P2P/TURN 失败后的中心转发兜底
|
|||
|
|
- `ai-gateway + xiaozhi_server`:AI 能力面
|
|||
|
|
- 设备侧优先由网关/高能力终端承担 WebRTC 与 AI,而不是全部压到低功耗锁体
|
|||
|
|
|
|||
|
|
这套方案能把你现在的“中央通信系统”拆成可演进的分层结构,同时把通用业务能力沉淀到 `starcloud`,由 `starlock` 聚焦租户化编排与应用体验层。
|