2026-04-22 13:47:37 +08:00
2026-04-27 14:56:30 +08:00
2026-04-27 14:23:41 +08:00

智能锁新实时系统方案

本文档面向一个“全新项目”的设计,但明确采用 starcloud 作为共享业务能力云平台,starlock 作为其租户化应用层入口,不重复建设通用业务能力。

1. 目标与约束

1.1 已知现状

  • starcloud:共享云平台,向下游业务应用提供可复用 API 与业务能力。
  • starlockPHP 业务后台,负责 APP 用户注册、登录、权限、家庭/门锁归属和其它业务规则。
  • app-starlockFlutter 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 继续承担:

  • 可复用用户/权限策略能力
  • 设备与家庭关系的共享模型能力
  • 通用套餐、计费、审计、风控能力
  • 标准化业务 APIstarlock 等下游应用调用)
  • 可复用的业务规则引擎与跨租户能力演进

2.2 starlock 租户应用层职责

starlock 继续承担:

  • 面向 app-starlock 的统一业务入口
  • 结合租户/渠道配置编排 starcloud 共享能力
  • 聚合会话、通知、AI 与设备业务流程
  • 面向 APP 的主业务 API 与体验层策略
  • 仅保留强租户定制逻辑,不重复实现通用业务能力

2.3 新实时系统承担职责

新项目承担:

  • 设备在线状态管理
  • 设备能力声明与发现
  • 实时会话创建与编排
  • WebRTC signaling
  • WebRTC 媒体接入
  • TURN/STUN 基础设施
  • 中心媒体转发兜底
  • ZLMediaKit 转发接入
  • AI 会话桥接
  • 调试日志、会话追踪、弱状态缓存

3. 总体架构图

说明:如果你当前 Markdown 查看器不支持 Mermaid请直接看 3.0.13.0.2 的纯文本结构图。

3.0.1 纯文本结构图(精简版)

app-starlock
  -> starlock (租户应用层)
    -> starcloud (共享业务能力 API)
    -> session-orchestrator (独立服务)
      -> Apache BifroMQ (发现/在线/信令)
      -> 媒体选路: P2P / TURN / ZLMediaKit / relay
  <-> Lock/Gateway (对讲设备)
  -> ai-gateway -> xiaozhi_server (AI旁路)

3.0.2 纯文本结构图(详细版)

[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
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锁 默认就是“网关锁形态”,因此可直接承接 网关设备 角色。

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 协议分散控制
  • 提前建立可扩容、可观测、可回放的会话控制平面
  • 后续只做横向扩容,不再经历二次拆分改造

对应第一阶段架构图如下:

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,弱网优先 ZLMediaKitTURN 负责 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/candidatesession-orchestrator 只做状态编排与超时控制,不搬运大媒体流。
  4. 建链判定:session-orchestrator 收集两端链路质量上报RTT、丢包、抖动、可用带宽、candidate 类型),进入 connecting -> connected
  5. 动态选路:当指标降级,发 switch-route 控制指令,从 p2pturnzlmediakit;若仍失败,再切 relay
  6. 结束会话:任一端发送 hangup 或超时触发 terminatesession-orchestrator 统一写入终态并清理 token/资源。

推荐状态机:

  • pending -> ringing -> accepted -> connecting -> connected
  • 通话中可进入:degraded -> switching_route -> recovered
  • 结束态:ended / rejected / timeout / failed

和旧 UDP 控制的关系:

  • 旧模型:端到端 UDP 协议字段直接表达“开始/结束”,中心侧难追踪完整会话。
  • 新模型:开始/结束只是状态机中的两个事件,所有控制动作都有 sessionId、事件序号、ACK、超时重试与最终态落库。
  • 结果:可审计、可回放、可补偿,且便于联调和问题追踪。

3.7 现状与第一阶段对照图

这张图适合给团队评审时使用,左边是你们当前主要链路,右边是第一阶段目标链路。

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 + coturnP2P/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

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、知识库、工具调用。
  • 用户、权限、套餐、审计等可复用能力优先沉淀在 starcloudstarlock 负责租户侧业务编排与体验层策略。

3.13 精简业务图(管理/评审)

这张图只保留关键角色和主链路,适合评审会快速对齐。

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 旁路,适合研发实现和联调。

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-gatewayxiaozhi_server 的 WebSocket/HTTP 会话
  • 不使用 xiaozhi 原生 MQTT+UDP 网关能力,避免引入第二套 MQTT 基础设施

AI 面承载:

  • 语音转文本
  • TTS
  • 意图识别
  • 工具调用
  • 智能应答
  • AI 辅助摘要/关键词提取

5. 核心时序图

5.1 设备上线与发现

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 发起对讲,媒体路径自适应

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 旁路模式

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
  • 聚合会话状态:pendingringingacceptedconnectedended
  • 管理媒体兜底策略:p2pturnrelayzlmediakit
  • 根据网络质量阈值执行媒体路径切换
  • 管理 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}/controlinviteringingacceptrejecthangupswitch-routeterminate
  • sessions/{sessionId}/statuspendingconnectingconnecteddegradedswitching_routeendedfailed

每条控制事件都带:

  • sessionId
  • eventId(单调递增)
  • fromapp/device/orchestrator
  • ts
  • ackTimeoutMs

处理规则:

  1. 未 ACK 的控制事件按策略重发。
  2. 超过最大重试进入 timeoutfailed
  3. 任一终态都由 session-orchestrator 写最终状态并触发资源清理。

归属结论与简化实现(提炼版)

归属结论:

  • session-orchestrator 属于云端实时基础设施层,不属于 APP 端,也不属于设备端。
  • 它是被 starlock 调用的独立服务。
  • starlock 负责业务授权与编排,session-orchestrator 负责视频会话控制与状态机收敛。

技术建议:

  • 首选 Go 实现独立服务(更适合高并发会话状态控制)。

简单实现方法MVP

  1. 先独立部署 session-orchestrator,并配套 Redis(热状态/重试队列)与 MySQL(会话记录/审计)。
  2. 先开三个内部接口:创建会话、结束会话、开启 AI sidecarstarlock 只通过这三个接口编排实时流程。
  3. APP/设备统一使用会话级 topicsessions/{sessionId}/controlsessions/{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

请求示例:

{
  "deviceId": "lock_123456",
  "sessionType": "talk",
  "mediaPolicy": {
    "strategy": "adaptive",
    "preferP2PWhenGoodNetwork": true,
    "preferZlmWhenWeakNetwork": true,
    "autoSwitch": true
  },
  "media": {
    "audio": true,
    "video": true,
    "dataChannel": true
  },
  "aiMode": "disabled"
}

响应示例:

{
  "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

请求示例:

{
  "mode": "assistant",
  "voiceProfile": "default",
  "intentScope": ["intercom", "unlock", "qa"]
}

8.2 starlocksession-orchestrator

创建内部会话

POST /internal/realtime/sessions

请求示例:

{
  "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"]
  }
}

响应示例:

{
  "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

请求示例:

{
  "deviceId": "lock_123456",
  "firmwareVersion": "2.3.1",
  "nonce": "abc123",
  "signature": "device-signature"
}

8.4 starlockstarcloud 共享业务 API

权限快照与策略校验

POST /internal/starcloud/policy/evaluate

请求示例:

{
  "tenantId": 1,
  "userId": 1001,
  "deviceId": "lock_123456",
  "action": "device.talk",
  "context": {
    "familyId": 2002,
    "channel": "app-starlock"
  }
}

响应示例:

{
  "allow": true,
  "policyVersion": "pcv_20260422_01",
  "permissionSnapshot": ["device.talk", "device.view"],
  "reason": "matched-tenant-policy"
}

响应示例:

{
  "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}/controlsessions/{sessionId}/status

设备在某个会话中只允许:

  • 发布:sessions/{sessionId}/signal/device
  • 订阅:sessions/{sessionId}/signal/app
  • 发布/订阅:sessions/{sessionId}/controlsessions/{sessionId}/status

这样可以避免跨会话串话和 topic 污染。

10. Session Token 设计

10.1 设计目标

session token 只表达“某个主体在某个短会话里的实时权限”,不重复承载完整业务模型。

10.2 推荐字段

推荐使用 JWT 或 PASETO字段如下

{
  "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:绑定单个设备
  • rolecallercalleeobserverai-sidecar
  • scp:实时权限范围,如 signalrtcairecord
  • 过期时间建议 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:实时会话编排中心
  • coturnRTC 第一层兜底
  • media-relay 能力层,由 ZLMediaKit 优先实现P2P/TURN 失败后的中心转发兜底
  • ai-gateway + xiaozhi_serverAI 能力面
  • 设备侧优先由网关/高能力终端承担 WebRTC 与 AI而不是全部压到低功耗锁体

这套方案能把你现在的“中央通信系统”拆成可演进的分层结构,同时把通用业务能力沉淀到 starcloud,由 starlock 聚焦租户化编排与应用体验层。

Description
AllStar2.0
Readme 23 KiB