AllStar2.0/开发计划.方案.架构.md

1673 lines
49 KiB
Markdown
Raw Permalink 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.

# 智能锁新实时系统方案
本文档面向一个“全新项目”的设计,但明确采用 `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 2WebRTC 对讲上线
目标:让音视频主链路切到 WebRTC。
交付:
- APP 端 WebRTC
- 设备或网关端 WebRTC
- TURN 兜底
- 中心媒体转发兜底
- `ZLMediaKit` 转发方案打通
- signaling 全链路打通
### Phase 3AI 辅助模式上线
目标:接入 `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` 聚焦租户化编排与应用体验层。