Web 运行站解决的是工业软件交付环节中一个长期痛点:客户端部署 。传统方案要么安装客户端软件,要么安装浏览器插件(ActiveX/NPAPI),在浏览器持续收紧安全策略的今天越来越难以为继。本平台的做法是把同一套运行内核 编译为 WebAssembly,在标准浏览器中运行完整的运行站,并通过 ucchmiserver 网关收敛全部工业通信。
4.1 总体架构与设计约束
图 12 Web WASM 运行站(WebPlayer)运行时结构
Web 运行站由两个角色组成:浏览器内的 WebPlayer (WASM 运行站)与服务端的 ucchmiserver (数据网关)。二者职责边界非常清晰:
角色 职责 明确不做的事
WebPlayer(WASM) 画面渲染与动画、实时/历史曲线、报警与 SOE 查询与呈现、报表、3D 渲染、脚本(受限沙箱)、工程本地缓存、运维 HUD 不打开任何工业协议 socket ;不持有本地权威数据库;不做设备采集
ucchmiserver WebSocket/WSS 服务、实时数据订阅与轮询、站级 Historian 只读查询代理、报警命令转发、工程与媒体分发、客户端在线名册与运维接口 不替代运行站做实时数据评估;不产生独立的报警权威数据
4.1.1 三条核心设计约束
浏览器不是可信环境。 因此所有工业通信、协议解析、权限判定都在服务端完成;浏览器只接收已授权的数据,且脚本执行与危险方法调用均受白名单限制。
WebAssembly 内存不能无限增长。 WebPlayer 使用固定的 512 MiB 线性堆(ALLOW_MEMORY_GROWTH=0),所有缓存、队列、缓冲都必须有明确预算与回收策略。
浏览器不能阻塞。 任何同步等待(例如历史查询)都必须走异步回调,禁止嵌套事件循环,否则会冻结整个运行时。
注 这三条约束不是「Web 版的妥协」,而是把 Web 端当作一个独立形态的运行站 来认真设计的结果。也正因为如此,WebPlayer 提供的不是「看板」,而是完整的运行站功能集。
4.2 ucchmiserver 数据网关
ucchmiserver 是纯服务端组件,提供数据网关、工程分发、运维控制与数据源集成四类能力,并以系统托盘程序的形式常驻运行,提供主界面、工具栏服务控制、事件日志、Web 客户端在线名册与运行状态提示。
4.2.1 四类能力
能力 组成 说明
数据网关 WebSocket / WSS 服务(默认端口 8030)、UDP 接收(实时 45452 / 告警 45454)、实时数据取数(本地或远程实时库)、Historian 只读桥(默认 9100) 把站端实时与历史数据以统一帧协议提供给浏览器端
工程分发 HTTP 测试与分发服务、工程目录与资源目录管理、可选 SHA256 清单校验 让浏览器端无需安装即可获取工程文件与媒体资源
运维控制 实时库服务启停与配置对话框、实时库运维控制台、实时库诊断面板、事件日志查看、HTTP 测试服务开关 把实时库与网关的运维动作可视化,降低现场维护门槛
数据源集成 SQLite / MySQL 数据源、MQTT 消息总线(自带 MQTT 源码编译)、配置持久化(Windows GBK / 信创 Linux UTF-8) 与既有信息系统和历史数据源对接
4.2.2 实时库服务与远程取数
网关对实时库的支持有两种形态:本地进程内服务 与远程客户端连接 。网关可作为实时库的客户端连接到站端运行站的实时库(默认端口 6389),并在启动初期自动补连,保证首批实时请求不被丢弃。
8990 通道(远程实时 JSON) :通过实时库 MGET 批量取键值,返回 JSON 帧,适合变量数量中等、需要可读性的场景。
8989 通道(紧凑二进制) :远程 rt/<id> 键值以紧凑二进制打包(可选压缩),适合高频、大批量、带宽敏感的场景。
连接独占与防饿死 :同一连接的取数请求不会互相排队等待,而是保留「每连接最新一次轮询」(8989 优先于 8990),锁释放后立即投递最新结果。
线程池异步 :取数在工作线程完成,结果再回到主线程投递 WebSocket 帧,保证网关自身的响应性。
4.2.3 站级 Historian 桥
历史数据的权威源是站级 Historian ,Web 端不存在本地历史库回退。网关提供只读桥接,查询失败时显式返回 remote_fail:* 错误,而不是返回空结果——这一点对工业场景至关重要:「没有数据」和「查询失败」必须是两种不同的状态 。
帧类型 对应业务 说明
'b' (8970)历史日窗曲线 按分辨率(小时/分钟/曲线)查询指定日期的曲线数据
'c' (8971)历史报警分页 按时间范围、确认状态、等级、区域、点名过滤分页查询
'd' (8972)SOE / 历史事件 按日期与关键字查询事件顺序记录
8973 站级命令转发 报警确认、全确认、重同步、搁置等操作下发站端执行
8974 查询游标取消 超时或发起新查询时取消网关侧游标,cursorId=0 表示最近一次
8975 运维指标快照 获取网关与站端运维指标
8976 通道诊断快照 获取站端运行站写入的通道诊断 JSON
注 游标与取消机制 是 Web 历史查询的关键:浏览器端可能在用户快速翻页或切换画面时发起新查询。若不取消旧查询,过期结果可能覆盖新结果,造成「曲线显示错位」。平台通过游标 ID + owner 归属实现精确取消——例如报表刷新不会打断曲线或报警的查询。
4.3 WebPlayer 的 WebAssembly 技术实现
4.3.1 构建配置
构建要素 配置 原因
目标平台 Emscripten / WebAssembly,定义 HMI_WASM_BUILD 同一份源码条件编译,避免维护两套代码
模块裁剪 剔除 sql、concurrent、serialbus 模块 浏览器内无本地数据库、无线程与串口总线
语言标准 C++11 / gnu++11 构建标志 匹配 Emscripten 工具链与 Qt for WebAssembly 的约束
JS 互操作 Embind(wasmbridge.cpp) 把 C++ 运行站能力以受控接口暴露给宿主 JS
虚拟文件系统 -lidbfs.js(IDBFS,基于 IndexedDB)持久化工程文件与运行缓存,实现二次冷启动加速
内存模型 固定 512 MiB 线性堆 + ALLOW_MEMORY_GROWTH=0 避免内存无限增长导致浏览器标签页崩溃,强制资源预算化
同步语义 Asyncify(用于必须同步的既有代码路径) 在不重写全部业务代码的前提下支持同步调用语义
工程预载 预载 RunApp 运行文件 减少首次加载的往返次数
4.3.2 内存治理:HmiMem 框架
浏览器端的内存治理是本方案最具工程含量的部分。平台提供统一的 HmiMem 内存策略层,把「桌面宽松、Web 严格」的差异收敛为一组编译期常量,并在运行期以周期性整理(housekeep)+ 压力分级(Normal/High/Critical)两级机制执行回收。
图 13 桌面运行站与 Web(WASM) 运行站的资源预算对比
预算项 桌面运行站 Web 运行站 回收策略
线性堆上限 不限制(操作系统管理) 512 MiB(固定) 压力分级 + 强制回收
实时曲线最大点数 100 000 4 000 隐藏页面丢弃实时缓冲
历史曲线最大点数 20 000 8 000 隐藏页面释放历史曲线缓冲
历史报警单页行数 5 000 500 分页拉取
SOE 查询上限 10 000 2 000 结果集上限
页面缓存数 16 2 Critical 时逐出隐藏页面缓存
脚本缓存条目 256 48 超限淘汰
媒体缓存 64 MiB 8 MiB 按键淘汰最旧条目
查询缓存 16 MiB 4 MiB 按键淘汰最旧条目
解码图片条目 128 24 LRU 淘汰
Pixmap 缓存 100 000 KB 8 192 KB 按节拍刷新,High 压力时立即刷新
事件持久化(JSONL) 开启 关闭 避免写放大
隐藏曲线采样 开启 关闭 隐藏页面不做无谓计算
注 分级回收策略 :HmiMem::housekeep() 以固定周期(桌面 30 s / Web 15 s)执行;隐藏页面释放历史/3D/GIF/实时缓冲,可见页面压缩曲线点数并触发脚本 GC;Pixmap 缓存按节拍刷新;进入 Critical 压力时进一步逐出隐藏页面与图片缓存。整个过程在 UI 线程安全执行,不产生阻塞。
4.3.3 二次冷启动与持久化
IDBFS 持久化 :工程文件、媒体资源与运行缓存写入浏览器持久化文件系统。
Service Worker :承担离线缓存与二次冷启动的快速装载,使第二次进入接近秒级。
工程同步(RunApp 同步) :启动阶段同步 HTTP 服务端的分发目录,先取 manifest.json,再按清单拉取各文件;支持可选 SHA256 完整性校验;同步过程向宿主 JS 报告运行阶段(便于 HUD 显示进度与错误)。
失败可解释 :同步失败、校验失败、网络失败均以明确的阶段与原因上报,而不是停留在白屏。
4.4 通信协议与帧字典
图 14 ucchmiserver 与 WebPlayer 通信协议栈及二进制帧字典
WebSocket 通道分为文本控制面 与二进制数据面 两部分:
平面 内容 用途
文本帧(控制面) 心跳(heartbeat)、会话握手(session hello)、运行状态(runtime status)、运维 HUD 指令(HMIOPS1/HMISESS1) 连接保活、会话建立、状态上报与运维交互
二进制帧(数据面) 首字节为类型标识,其后为负载 实时数据、历史曲线、报警、SOE、工程与媒体文件、SQL 结果等
表 4-1 二进制帧类型字典
类型字节 业务语义 说明
'1'8998 变量/标签数据 标签数据下行
'2'UDP 实时桥接 / 二进制回显 运行站 UDP 实时帧转发给浏览器;也用于回显
'3'9000 工程文件 / 1102 媒体二进制 工程与媒体的大块二进制传输
'4'8997 媒体 JSON 媒体资源元数据
'5'1103 文件数据 JSON 文件数据描述
'6'1101 画面文件包 画面定义的打包传输
'7'告警 UDP 帧 告警事件转发
'8'8990 远程实时 JSON 实时库 MGET 结果
'9'8996 SQL JSON SQL 查询结果的兼容帧
'a'8989 远程实时紧凑二进制 高频批量实时数据(可选压缩)
'b'8970 历史日窗曲线 历史曲线查询响应
'c'8971 历史报警分页 报警历史查询响应
'd'8972 SOE / 历史事件 SOE 查询响应
注 帧上限 :桌面形态 32 MiB、Web 形态 8 MiB;待发送二进制缓冲桌面 16 MiB、Web 4 MiB。超限的连接会被明确拒绝而不是静默截断,避免「数据看起来传过去了但内容是残缺的」这类难以定位的问题。
4.5 安全模型
Web 端直接暴露在 IT 网络中,安全设计的核心思路是「收敛能力 + 显式授权 + 可验证完整性 」。
安全层面 机制 默认值
传输安全 WS / WSS(TLS),支持配置证书、私钥与 CA;对端校验策略可选 none / query / require 对端校验可选,生产环境建议 require
宿主脚本 任意脚本执行默认关闭 ,仅可通过接口在操作员登录后开启;实验环境可通过编译开关 HMI_ALLOW_HOST_SCRIPT=1 放开 关闭
危险方法调用 myObjInvoke / 宿主路径调用受方法白名单 限制白名单机制
写入操作 写操作要求操作员已登录(可配置为强制) 强制登录
工程完整性 工程清单 SHA256 校验;未提供期望哈希时跳过校验 支持且可强制
数据平面 浏览器端不打开工业协议 socket,所有协议通信经网关代理 架构保证
历史数据权威性 历史/报警数据一律回源站级 Historian,不提供本地回退 架构保证
运维可见 提供安全策略 JSON 查询接口与运维 HUD,策略状态对运维透明 内置
注 「默认关闭」原则 :宿主脚本、危险方法、写入操作三者的默认状态都是「关闭或受限」,必须显式开启。这与工业现场的安全要求一致——默认配置应当是安全的,而不是需要额外加固才安全的。
4.6 部署实施
图 15 典型部署拓扑与端口规划
4.6.1 部署步骤
部署站端运行站 :按第 3 章的运行站部署方式安装 HMIPlayer,确认实时库、时序库、报警与采集正常运行。
部署网关 :在服务区/DMZ 主机上部署 ucchmiserver;配置数据源(SQLite/MySQL)、实时库端点(本地或远程 6389)、站级 Historian 端点(默认 9100)、WebSocket 监听地址与端口(默认 8030)、WSS 证书与对端校验策略。
配置工程分发 :把工程发布目录配置为 HTTP 分发根目录,启用可选的 SHA256 清单校验。
部署 WebPlayer 静态资源 :把 WASM 构建产物(.js / .wasm / .data 与静态页面)部署到 Web 服务器,或由网关的 HTTP 服务直接分发。
网络与防火墙 :按端口清单放行(见下表);OT/IT 之间建议单向或白名单方式隔离。
验收 :浏览器访问 → 观察工程同步进度 → 进入画面 → 验证实时刷新、历史曲线、报警查询、报警确认、报表导出与 3D 渲染。
运维接入 :配置运维 HUD 与指标抓取(运维指标快照 8975、通道诊断快照 8976),纳入既有监控体系。
4.6.2 端口与协议清单
表 4-2 默认端口与用途
端口 协议 用途 方向
8030 WebSocket / WSS 网关数据服务(可配置) 浏览器 → 网关
80 / 8080 HTTP 工程与媒体分发、HTTP 测试服务 浏览器 → 网关
9100 TCP(CTSP) 站级 Historian 只读查询桥 网关 → 站端
6389 TCP(RESP 兼容) 实时库命令服务与复制 内部 / 网关 → 运行站
45452 UDP 实时数据转发 站端 → 网关
45454 UDP 告警转发 站端 → 网关
1883 / 8883 MQTT / MQTTS 消息总线(可选) 双向
4840 OPC UA(opc.tcp) OPC UA 服务端(可选) 双向
— 设备协议端口 Modbus TCP、S7、IEC104、DNP3 等(按现场配置) 运行站 → 现场设备
4.6.3 运行与升级
工程热更新 :工程变更后无需重新安装任何客户端,浏览器刷新或按提示重载即可获得新版本;SHA256 校验保证新旧版本混用不会产生静默错误。
网关服务控制 :主界面工具栏可一键启停网络服务、实时库服务,并可查看运行状态提示与事件日志。
在线名册 :网关维护 Web 客户端在线名册(可只看在线),并记录历史接入端点,便于运维掌握终端分布。
诊断 :运行时状态、事件、崩溃报告、安全策略、宿主脚本控制均通过对外 API 暴露,可接入第三方运维平台。
4.6.4 容量与带宽估算方法
Web 运行站与桌面运行站的最大差别是资源边界是硬的 :浏览器侧是固定的 512 MiB 线性堆,网关侧是有限的连接与线程预算。因此容量规划不能靠「先上再看」,而应在设计阶段按下面的口径估算。
容量维度 估算方法 / 口径 工程建议
下行带宽 带宽 ≈ 可见测点数 × 变化率 × 单点负载字节 × 刷新频率;紧凑二进制帧的单点负载约 8~16 B(含质量码与时标),文本 JSON 帧约为其 2~4 倍 优先让网关使用紧凑二进制通道(8989);文本通道(8990)用于低频或调试场景
网关并发 单会话在 1 Hz 刷新、数千可见点下约为数十 KB/s 量级;取数经线程池异步执行并按连接独占排队 按实测压测确定单网关会话上限;超出后横向扩展网关或按区域划分
单画面测点 画面内可见测点全部需要订阅与刷新 建议单画面可见测点控制在数千级;用弹出画面、分组刷新与死区降低瞬时负载
曲线点数 实时曲线上限 4 000 点,历史曲线上限 8 000 点(代码常量) 长区间查询用抽点间隔,避免在浏览器侧做超大点数渲染
历史查询 日窗查询支持小时/分钟/曲线粒度;跨日区间用抽点 避免「大区间 + 高密度」同时出现;批量取数用异步并支持取消
浏览器内存 固定 512 MiB;页面缓存 2 个、媒体缓存 8 MiB、报警队列 64、待发缓冲 4 MiB 页面与 3D 场景按预算设计;隐藏页面会被回收,不应把状态寄托在隐藏页面上
3D 场景 模型与纹理计入 8 MiB 媒体预算 建议单画面一个 3D 视图;Web 端优先使用低多边形模型与压缩纹理
工程体积 工程文件经 HTTP 分发并缓存于 IDBFS 拆分工程资源、按需加载;启用 SHA256 校验以保证版本一致
注 口径声明 :上表给出的是估算方法与设计边界 ,不是性能承诺;实际容量必须在目标硬件与目标工程规模上压测确认。好在平台把关键边界都做成了可读的代码常量与可统计的指标,压测结果可以直接与常量对照,而不是靠猜。
4.7 技术指标
表 4-3 Web 运行站关键指标
类别 指标 数值 / 说明
运行时 内存模型 固定 512 MiB 线性堆,ALLOW_MEMORY_GROWTH=0
持久化 IDBFS(IndexedDB)+ Service Worker 二次冷启动
工程装载 HTTP manifest + 分文件同步 + 可选 SHA256 校验
渲染 画面 矢量图元 + 动画 + 多页面/弹出页面(并发上限按预算控制)
实时曲线 最大 4 000 点
历史曲线 最大 8 000 点
3D 支持(assimp 模型 + 媒体缓存 8 MiB)
数据 实时数据 文本 JSON 帧(8990)与紧凑二进制帧(8989)双通道
历史查询 日窗(小时/分钟/曲线)+ 跨日区间 + 抽点间隔;异步 + 可取消
报警 历史报警分页(单页 500 行)、SOE(上限 2 000 条)、确认/全确认/搁置/重同步
报表 周期报表经时序库/Historian 通道(8970)
通信 帧上限 单帧 8 MiB;待发缓冲 4 MiB
保活 文本帧心跳 + 会话握手 + 运行状态上报
重连 带退避策略的重连,会话恢复后按需重同步
安全 传输 WS/WSS + 证书 + 对端校验策略
脚本 宿主脚本默认关闭、方法白名单、写操作要求登录
完整性 工程清单 SHA256 校验
运维 接口 运行状态、事件、崩溃报告、安全策略查询
指标 运维指标快照(8975)、通道诊断快照(8976)
兼容 浏览器 Chrome / Edge / Firefox 及主流国产浏览器(需支持 WASM)
运行看护 浏览器侧 无本地自愈能力 (浏览器沙箱不允许);运行健康由站端 HMICare 统一负责(见第 5 章)
网关侧 网关作为普通 Windows/Linux 服务进程,可纳入 HMICare 或既有 IT 监控
对外可见 运行状态、事件、崩溃报告与运维指标快照对外暴露,便于统一采集
4.8 适应领域
场景 为什么适合 Web 运行站
集团/厂级调度大屏 免安装、集中发布、任意终端打开,运维成本最低
工程师与管理人员远程查看 不受办公终端操作系统与权限限制
多终端分散监视 车间、值班室、移动终端统一入口,无需逐台安装
巡检与移动作业 平板/手机浏览器直接访问,支持响应式画面
演示与培训环境 临时电脑、会议室设备即可作为运行站使用
承包商/第三方协同 授予只读或受限权限,不暴露工程与站端网络
边缘/无人值守站点 站端运行 + 远程 Web 监视,减少现场值守成本
项目交付与验收 业主无需安装任何软件即可验收,缩短交付周期
国产化办公终端 国产 OS + 国产浏览器环境下无需额外适配客户端
4.9 技术领先性对比
对比项 传统 Web 方案 本方案(WASM 运行站)
技术路线 服务端渲染 HTML 看板;或 ActiveX / NPAPI 插件;或远程桌面推送 同一 C++ 运行内核编译为 WebAssembly,浏览器内原生执行
功能完整性 通常是桌面功能的子集(曲线、报警、报表常被简化或缺失) 完整运行站:曲线、报警、SOE、报表、3D、脚本(受限沙箱)
插件依赖 需要安装插件或在特定浏览器版本运行 标准浏览器直接运行,无插件、无本地安装
与桌面的一致性 两套代码两套行为,需分别验证 同一份工程、同一套内核,行为一致(仅按内存预算裁剪上限值)
安全模型 插件通常拥有较高本地权限,风险面大 浏览器沙箱 + 服务端代理通信 + 默认关闭宿主脚本 + 方法白名单
内存可控性 前端长跑易内存泄漏,只能靠刷新页面缓解 固定 512 MiB 堆 + 显式预算 + 分级回收,支持长时间稳定运行
历史数据权威性 部分方案在浏览器侧缓存历史,产生「双源」歧义 一律回源站级 Historian,失败显式报错,不静默返回空
部署成本 需为每个终端安装/配置,版本升级需逐台处理 零安装、集中发布、刷新即升级
可观测性 前端黑盒,问题难定位 运行状态/事件/崩溃报告/安全策略/运维指标对外可见
运行看护 浏览器端无法自愈,且缺少「数据是否还在更新」的功能级判定 浏览器侧明确不做本地自愈;运行与采集的健康由站端 HMICare 统一看护(含历史库静默停写、通道设备在线率判定)
注 与其他 Web 化路线的本质区别 :多数 SCADA 的 Web 化是重写一个前端 ,结果是「两套产品、功能不等、验证翻倍」。本方案是把运行内核搬到浏览器 ,结果是「一套工程、两种形态、行为一致」。代价是必须认真解决内存、异步与安全三个难题——这正是本章 §4.3/§4.5/§4.7 的内容。