HMI 总览
Darra HMI 是 DarraRT PLC 产品内置的 Web 化人机界面子系统, 使用纯 HTML/CSS/JavaScript 技术栈构建, 通过 WebSocket 与 PLC Service 进行实时数据交互。整个 HMI 既可以随 PLC 本地运行 (LocalHMI, WinForms + WebView2 全屏外壳), 也可以对外暴露 18823 端口 (WebHMI) 供浏览器、手机、平板远程访问。
HMI 与 PLC 运行时 完全解耦: HMI 挂掉不会影响 PLC 扫描; PLC 停机时 HMI 会自动进入"断开重连"状态。
为什么选择 Web 技术栈
| 对比项 | 传统 WinForms/WPF HMI | Darra Web HMI |
|---|---|---|
| 渲染引擎 | GDI / DirectX | Chromium (WebView2) |
| 跨平台 | 仅 Windows | 本地 + 浏览器 + 手机 + 平板 |
| 热更新 | 重启 | 刷新 F5 |
| 开发门槛 | 需 VS + C# | 任意文本编辑器 |
| 控件生态 | WinForms 有限 | npm 百万级生态 |
| 响应式 | 困难 | CSS 原生支持 |
架构总览
+------------------------------------------------------------+
| LocalHMI (WinForms + WebView2 外壳) |
| Darra.PLC.HMI.exe |
| F11 全屏 / F5 刷新 / ESC 退出 / 自动重连 |
+------------------------------------------------------------+
加载
|
v
+------------------------------------------------------------+
| HmiWebServer (端口 18823, System.Net.HttpListener) |
| /local/{route} LocalHMI 页面 |
| /web/{route} WebHMI 页面 |
| /static/* 静态资源 (alpine.js, darra-plc.js 等) |
| /ws WebSocket (变量订阅/推送/写入) |
| /api/hmi/* 管理 API (登录/DB描述/列页面) |
+------------------------------------------------------------+
|
v
+------------------------------------------------------------+
| Darra.PLC.Service (永驻进程) |
| HmiBroadcaster 变量推送节流合批 |
| HmiVariableBridge PLC ↔ JSON 变量读写桥 |
| HmiPythonBridge HMI 调 Python 脚本 |
| HmiAuthProvider 登录/角色/Token |
+------------------------------------------------------------+
|
v (与 PLC VM 共享内存)
+------------------------------------------------------------+
| DarraRT_PLC.sys (内核态, PLC 扫描) |
+------------------------------------------------------------+
LocalHMI vs WebHMI
| 属性 | LocalHMI | WebHMI |
|---|---|---|
| 访问方式 | 本地 WebView2 全屏 | 浏览器 http://<ip>:18823/web/... |
| 外壳 | Darra.PLC.HMI.exe | 无, 浏览器直接访问 |
| 典型终端 | 工控机 / 触摸屏 / 工位 Panel | 移动端 / 办公电脑 / 外部大屏 |
| 认证 | 可选 (一般局域网直接登录) | 强制 (RequireAuth = true) |
| 写入白名单 | 通常宽松 | 强烈建议启用 WriteWhitelist |
| 页面路由 | /local/{route} | /web/{route} |
一个 PLC 项目可同时拥有 LocalHMI 和 WebHMI 两份独立工程 (
project.LocalHMI/project.WebHMI), 它们共用同一个 PLC 变量, 但页面、皮肤、导航完全独立。
前端技术栈
| 技术 | 作用 | 加载方式 |
|---|---|---|
| Alpine.js 3.x | 声明式响应 x-data/x-text/x-bind, Custom Element 驱动 | /static/alpine.min.js |
| GrapesJS 0.21 | 拖拽式可视化设计器 (仅 IDE 使用) | IDE 内嵌 |
| Chart.js 4.x | 趋势图 / 仪表 / 柱状图 | /static/chart.umd.js |
| DevExtreme JS 23.x | 高级企业控件 (DataGrid/TreeList/Scheduler/PivotGrid/Form/Gauge 系列) | /static/devextreme/dx.all.js 按需 |
| darra-plc.js | darra.* 全局 API, 封装 WebSocket + 变量绑定 | /static/darra-plc.js |
| darra-controls.js | 36 个 <darra-*> 自定义标签, 注册 GrapesJS Block | /static/darra-controls.js |
| darra-devextreme.js | DevExtreme 到 <darra-dx-*> 的封装 | /static/darra-devextreme.js |
| darra-hmi.css | 基础样式 + modern / industrial 主题 CSS 变量 | /static/darra-hmi.css |
所有 JS 库均本地自带, 不依赖外网 CDN。离线工厂环境开箱即用。
数据模型
每个 HMI 项目 (HMIProjectDef) 由以下部分组成:
{
"Type": "Local",
"Settings": {
"DesignWidth": 1920,
"DesignHeight": 1080,
"AspectRatio": "16:9",
"ScaleMode": "FitRatio"
},
"ActiveSkin": "modern",
"CustomSkins": [],
"Pages": [
{
"Name": "首页",
"Route": "/",
"IsHome": true,
"HtmlCode": "<!DOCTYPE html>...",
"CssCode": "body { ... }",
"JsCode": "// 页面脚本",
"Elements": []
}
],
"HomeRoute": "/",
"Navigation": { "Position": "Top", "Items": [] },
"WriteWhitelist": [],
"RequireAuth": false,
"GlobalCss": "",
"Version": 1
}
两种编辑模式
- FreeForm (拖拽) — IDE 内嵌 GrapesJS 画布, 拖入
<darra-*>控件, 右侧 Trait 属性面板设置var="...", 保存时自动生成HtmlCode+CssCode+JsCode+Elements[] - Code (纯代码) — IDE 内嵌 Monaco 三段式编辑器 (HTML/CSS/JS), 可直接写任意合法 Web 代码,
darra全局对象已注入
两种模式可以在同一页面内切换: 拖拽先搭骨架, 再切到 Code 补 JS 逻辑。参见 混合模式。
最小示例
HomeRoute = "/" 页的 HtmlCode:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>车间首页</title>
<link rel="stylesheet" href="/static/darra-hmi.css" />
<script src="/static/alpine.min.js" defer></script>
<script src="/static/darra-plc.js"></script>
</head>
<body class="theme-modern">
<h1>1# 反应釜</h1>
<darra-led var="M0.0" color-on="#00FF00" color-off="#666"></darra-led>
<darra-numeric var="DB1.Temperature" unit="℃" format="0.00"></darra-numeric>
<darra-button var="M0.1" mode="toggle">启动</darra-button>
<darra-trend vars="DB1.Temperature,DB1.Pressure" max-points="300"></darra-trend>
</body>
</html>
保存后, 打开 http://localhost:18823/local/ 即可看到实时数据。
控件总览 (36 个 <darra-*>)
| 分类 | 控件 |
|---|---|
| 基础 | <darra-button> <darra-led> <darra-numeric> <darra-input> <darra-label> |
| 图表 | <darra-gauge> <darra-trend> <darra-chart> <darra-progress-bar> <darra-slider> |
| 工业 | <darra-tank> <darra-pipe> <darra-motor> <darra-valve> |
| 系统 | <darra-alarm-list> <darra-image-toggle> <darra-nav-button> <darra-panel> |
| 运动 | <darra-axis> <darra-jog-panel> <darra-motion-path> |
| 机器人 | <darra-robot-status> <darra-robot-jog> <darra-robot-3d> |
| 视觉 | <darra-camera-view> <darra-vision-result> |
| 边缘 | <darra-comm-status> <darra-device-list> <darra-data-logger> |
| 用户 | <darra-login-panel> <darra-user-badge> <darra-permission-gate> |
| 布局 | <darra-separator> <darra-tab-container> <darra-group-box> |
| DevExtreme | <darra-dx-grid> <darra-dx-tree> <darra-dx-scheduler> <darra-dx-pivot> <darra-dx-form> <darra-dx-speedometer> <darra-dx-linear-gauge> <darra-dx-bar-gauge> <darra-dx-bullet> <darra-dx-sparkline> |
完整属性表见 控件库。
关键约束
- 全部运行在 Chromium: LocalHMI 用 WebView2, WebHMI 用浏览器; 不依赖 Flash / ActiveX / Silverlight
- 双向数据流: PLC → HMI 推送由
HmiBroadcaster节流 (默认 100ms), HMI → PLC 写入走WriteWhitelist白名单校验 - 离线重连: WebSocket 断开会进入
offline事件, 3 秒后自动重连, 重新订阅所有变量 - 变量寻址 IEC 61131-3:
M0.0/MW100/MD200/DB1.Field/I0.0/Q0.0 - 响应断开: 右下角内置
<div id="darra-conn-status">连接状态指示, 不可关闭