Files
frontend-miniapp/static/sgs-map-sdk/sdk-protocol.md

5.4 KiB
Raw Blame History

SGS Map SDK 通信协议规格 (Protocol Specification)

版本: V2.0.0 适用对象: SGS Map SDK 核心开发者、渲染基座 (h5-sdk) 开发者

本文档定义了外壳 SDK (sgs-map-sdk.js) 与 独立渲染基座 iframe (h5-sdk/page.tsx) 之间的 postMessage 通信契约。所有消息传递必须严格遵循此结构,以保障多域环境下的确权、安全过滤与异步生命周期追踪。


1. 消息模型抽象

双方通信产生的 JSON 对象统一分为三大类:

1.1 命令 (Command): SDK -> 基座

外壳 SDK 向基座发起的主动操作。

{
  "type": "SGS_MAP_COMMAND",
  "action": "PLAN_ROUTE",          // [必填] 行为动词
  "requestId": "req_sdk_123_45",   // [可选] 异步确权追踪信标
  "payload": { ... }               // [可选] 负载参数
}

1.2 响应 (Response): 基座 -> SDK

基座处理完 Command 后(同步或异步计算),向 SDK 携带结果的被动回执。

{
  "type": "SGS_MAP_RESPONSE",
  "action": "PLAN_ROUTE",          // [必填] 原样回显 Command 的 action
  "requestId": "req_sdk_123_45",   // [必填] 原样回显 Command 的 requestId
  "payload": { "success": true },  // [可选] 成功时的返回值
  "error": { "code": "ERR_NO_PATH", "message": "无路径" } // [可选] 失败时的异常信息
}

1.3 事件 (Event): 基座 -> SDK

基座中发生的不可预知行为(如鼠标点击)或系统状态变更,主动向外广播。

{
  "type": "SGS_MAP_EVENT",
  "action": "ON_POI_CLICK",        // [必填] 事件动词 (ON_开头)
  "payload": { "poiId": 1234 }     // [可选] 事件负载
}

2. 握手时序 (Handshake Sequence)

为了解决 iframe 初始化过程中的“假死”与状态竞态,必须采用基于事件的确权握手。

sequenceDiagram
    participant SDK as 外壳 SDK
    participant Iframe as 浏览器 DOM
    participant Base as 渲染基座 (h5-sdk)

    SDK->>Iframe: 动态创建 iframe(src)
    Iframe-->>SDK: 触发 iframe.onload
    
    Note over SDK,Base: 此时 HTML 刚加载WebGL/GLB 模型并未解析完成
    
    SDK->>Base: 发送 HELLO { protocolVersion: 2, sdkVersion: "2.0.0" }
    Base->>Base: 挂载 WebGL拉取 GLB 及 POI 接口
    Base-->>SDK: 内部加载完毕,推送 ENGINE_READY 事件
    SDK->>SDK: 解锁 isReady = true清空缓存命令队列

3. 指令字典 (Command Action Dictionary)

基座通过严格的白名单机制过滤 action,任何未在下表中声明的指令都将被立刻退回 ERR_UNSUPPORTED 响应。

Action Payload 负载签名 成功 Response 负载 说明
HELLO { protocolVersion, sdkVersion } (无,以 ENGINE_READY 代替回执) 初始心跳探测
CHANGE_FLOOR { floorId: number } { success: true, floorId } 触发析构当前层并加载新层
FOCUS_TO SgsMapNode { success: true } 镜头平滑转移,改变相机视角
PLAN_ROUTE { startNode?: SgsMapNode, endNode?: SgsMapNode, from?: SgsMapNode, to?: SgsMapNode, options? } RouteResult 寻路计算。基座将转换为微服务调用
CLEAR_ROUTE (空) { success: true } 销毁当前的 NavMeshPathLayer
GET_STATE (空) { floorId, isReady, ... } 查询内部状态机当前切片
ADD_MARKER MarkerConfig { success: true } 生成三维图钉并依附到骨骼节点
REMOVE_MARKER { markerId: string } { success: true } 释放指定图钉的材质
CLEAR_MARKERS (空) { success: true } 卸载所有动态业务图钉
HIGHLIGHT_POLYGON { nodeName: string } { success: true } 激活发光材质特效
RESET_VIEW (空) { success: true } 重置相机视角至初始状态
SET_VIEW_MODE `{ mode: '2d' '3d' }` { success: true }
TOGGLE_LAYER { types: string[], visible: boolean } { success: true, visibleTypes: string[] } 批量控制某类底座设施的显示隐藏

类型定义备注: SgsMapNodeRouteResult 的精确结构请参考 TypeScript 源码定义:sdk-src/types.ts


4. 事件广播列表 (Event Action List)

事件 Action Payload 结构 SDK 派发事件名 触发时机
ENGINE_READY { engineVersion, protocolVersion, sdkVersion } ready 基座完全挂载WebGL 画布可渲染
ON_POI_CLICK { id, name, type } poiClick 用户在触摸屏或鼠标点击了高亮要素
ON_FLOOR_CHANGED { floorId } floorChanged 楼层完全切换完毕后自动抛出

5. 安全沙箱规则 (Security & Sandboxing)

  1. Origin 发射校验 (SDK 侧)
    • sgs-map-sdk.js 使用 iframe.contentWindow.postMessage(msg, targetOrigin) 发射指令。若 targetOrigin 错误,浏览器底层会进行跨域阻断。
  2. Origin 监听校验 (SDK 侧)
    • 收到事件时比对 event.origin !== targetOrigin,丢弃第三方注入的伪造消息。
    • 收到事件时比对 event.source !== this.iframe.contentWindow,丢弃宿主页面其他无关 iframe 的干扰。
  3. 安全内存释放 (GC)
    • 断网或后服务宕机时SDK 侧的 Promise 将在设定的 timeout (默认 5000ms) 到达后自动 reject
    • SDK 实例调用 destroy() 后,会清除自身 DOM 及事件树,杜绝闭包引用与孤儿 WebGL Context。