117 lines
5.4 KiB
Markdown
117 lines
5.4 KiB
Markdown
# 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 向基座发起的主动操作。
|
||
```json
|
||
{
|
||
"type": "SGS_MAP_COMMAND",
|
||
"action": "PLAN_ROUTE", // [必填] 行为动词
|
||
"requestId": "req_sdk_123_45", // [可选] 异步确权追踪信标
|
||
"payload": { ... } // [可选] 负载参数
|
||
}
|
||
```
|
||
|
||
### 1.2 响应 (Response): 基座 -> SDK
|
||
基座处理完 `Command` 后(同步或异步计算),向 SDK 携带结果的被动回执。
|
||
```json
|
||
{
|
||
"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
|
||
基座中发生的不可预知行为(如鼠标点击)或系统状态变更,主动向外广播。
|
||
```json
|
||
{
|
||
"type": "SGS_MAP_EVENT",
|
||
"action": "ON_POI_CLICK", // [必填] 事件动词 (ON_开头)
|
||
"payload": { "poiId": 1234 } // [可选] 事件负载
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 握手时序 (Handshake Sequence)
|
||
|
||
为了解决 iframe 初始化过程中的“假死”与状态竞态,必须采用基于事件的确权握手。
|
||
|
||
```mermaid
|
||
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 }` | 切换 2D/3D 视角模式 |
|
||
| `TOGGLE_LAYER` | `{ types: string[], visible: boolean }` | `{ success: true, visibleTypes: string[] }` | 批量控制某类底座设施的显示隐藏 |
|
||
|
||
> **类型定义备注:**
|
||
> `SgsMapNode` 及 `RouteResult` 的精确结构请参考 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。
|