Skip to content

多端遥测可视化:一套极简 WebSocket 协议 ​

个人技术实验记录。目标是验证"实时数据能不能稳定驱动 3D 场景",不是设计一个工业协议。

场景里放几十栋建筑是静态的,真正要看的是动态数据在空间里的状态。我不想要一套复杂的工业协议,所以自己定了个只有三种消息的版本:遥测、指令、回执。

一、协议全文 ​

传输:WebSocket,本地端口自定。所有消息单层 JSON,无嵌套。

服务端 → 客户端:遥测 ​

每秒一条,连接建立时立即补发一条(避免客户端等一秒才有画面):

json
{
  "type": "telemetry",
  "ts": 1792309614,
  "devices": [
    { "deviceId": "DEV-01", "temperature": 23.6, "power": true,  "x": 9.1,  "y": 10.6, "z": 9.0 },
    { "deviceId": "DEV-02", "temperature": 24.2, "power": false, "x": 25.0, "y": -31.6, "z": 9.0 }
  ]
}

x / y / z 直接复用建模时的局部米制坐标,客户端不需要再做任何地理换算。z 给的是屋顶高度,标记物直接浮在建筑上方。

客户端 → 服务端:指令 ​

json
{ "type": "command", "commandId": "CMD-0001", "deviceId": "DEV-01", "action": "power_on", "value": 0 }

action 只留四个取值:power_on / power_off / temp_up / temp_down。

服务端 → 客户端:回执 ​

json
{ "type": "ack", "commandId": "CMD-0001", "result": "ok" }

二、几个刻意的设计决定 ​

1. commandId 由客户端生成,服务端原样回传 这样客户端能把自己的请求和回执对上,不用维护"当前最新序号"这种全局状态。一开始我让服务端生成,结果并发点两次按钮就分不清哪个回执对应哪次操作。

2. 先 ack,再广播新遥测 顺序反了会出现"回执说成功,但画面还是旧状态",看起来像 bug。ack 只表示指令收到并已处理,遥测里的变化才是最终状态。

3. 设备首次出现就自动建 Actor,不做显式的 create 消息 少一种消息、少一个状态同步问题。代价是不能靠"消息消失"来表达设备移除,所以设备下线用 power: false 表达,而不是从数组里删掉。

4. 断线后固定 3 秒重连,重连不清空已有 Actor 3 秒是拍的:更短会在服务端真挂的时候把连接打爆,更长时画面卡太久。不清空 Actor 是为了避免"重连后场景闪一下全空",视觉上稳定很多。

5. 坐标单位换算写死在客户端 UE 侧是厘米,Web 侧是米。约定"协议里一律是米",各端自己乘,协议层不做单位协商——一旦允许协商,两端实现就会开始漂移。

三、这套东西不适合什么 ​

说清楚边界,免得有人当真照抄:

  • 不是可靠传输:没做序号、没做重传。遥测本身有下一帧覆盖,丢一条无所谓;但指令如果丢在网络上,客户端只会等不到 ack,不会知道原因。
  • 没有鉴权:只在本地回环跑,纯实验。真要做远端,这层必须补。
  • 没有历史:只有最新状态,不能回放。要做趋势得另加存储,不该塞进这个协议。

四、下一步 ​

  • 加一个 seq 字段,让客户端能发现"遥测断流了但连接还在"
  • 指令超时后允许重发,配合幂等的 commandId
  • 设备数量上百之后,遥测按变化量发送(现在每秒全量,几十台还行)

相关 ​

本站为个人技术展示网站,仅用于个人研发作品、3D 数字孪生技术学习展示,无任何经营性服务、无社区互动、不对外提供商业服务。

本站为个人技术展示网站,仅用于个人研发作品、3D 数字孪生技术学习展示,无任何经营性服务、无社区互动、不对外提供商业服务。

蜀ICP备2026068005号-1|个人 3D 数字孪生技术研发展示站