预览与发布
Darra HMI 没有传统意义的"打包 MSI", 发布 = 保存项目 → 启动 HmiWebServer → 访问端口 18823。LocalHMI 由 WinForms 外壳自动加载, WebHMI 暴露给浏览器/手机/平板。
发布全流程
IDE 设计器 ──保存──> HMIProjectDef JSON
│
↓
项目文件 .plc (Service 随启动读取)
│
↓
HmiWebServer (18823)
┌────────┴────────┐
↓ ↓
/local/ /web/
↓ ↓
Darra.PLC.HMI.exe 浏览器 / 手机
(WebView2 全屏) (任意终端)
步骤 1: 保存项目
设计器内 Ctrl+S:
- GrapesJS 把画布序列化为
HtmlCode / CssCode / JsCode / Elements[] - IDE 写入
project.LocalHMI或project.WebHMI .plc项目文件保存到磁盘
步骤 2: 启动 HmiWebServer
HmiWebServer 是 Darra.PLC.Service 的内部组件, 随 Service 启动:
- 菜单
运行 → 启动 PLC Service - 或命令行:
Darra.PLC.Service.exe --project=myproj.plc
Service 启动日志:
[Info] [HmiWebServer] 监听 http://+:18823
[Info] [HmiWebServer] LocalHMI 路由: /local/{route}
[Info] [HmiWebServer] WebHMI 路由: /web/{route}
[Info] [HmiWebServer] 静态资源: /static/*
[Info] [HmiWebServer] WebSocket: /ws
端口占用检测: 如果 18823 被占, Service 会在日志打
SocketException: Address already in use, 可通过netstat -ano | findstr 18823查占用进程。
步骤 3: LocalHMI 本地访问
Darra.PLC.HMI.exe (HMIShellForm.cs) 是 WinForms + WebView2 外壳:
- 启动后自动导航到
http://localhost:18823/local/ - 全屏 (无标题栏/无边框/覆盖任务栏)
- 快捷键:
- F11 切换全屏
- F5 刷新页面
- Ctrl+Shift+I 开发者工具 (仅 Debug 构建)
- ESC 退出 (需密码/管理员权限)
- 断线自动重连
命令行参数:
Darra.PLC.HMI.exe --url=http://localhost:18823/local/ --fullscreen --no-esc-exit
| 参数 | 说明 |
|---|---|
--url | 覆盖默认起始页 |
--fullscreen | 默认启用 |
--no-esc-exit | 禁止 ESC 退出 (生产环境) |
--kiosk | Kiosk 模式 (禁用所有快捷键) |
步骤 4: WebHMI 外部访问
PC 浏览器
http://<Service 主机 IP>:18823/web/
http://192.168.1.100:18823/web/reactor
推荐浏览器: Edge / Chrome / Firefox 最新版 (需支持 WebSocket + CSS Grid)。
移动端 (手机/平板)
同一局域网 WiFi 下:
- 查 Service 主机 IP:
ipconfig | findstr IPv4 - 手机浏览器输入
http://<IP>:18823/web/ - 加到主屏 → 创建 PWA 应用图标
外网远程
- 端口映射 (路由器配置): 公网
18823 → 内网 Service:18823 - 启用 HTTPS (反向代理 nginx/caddy), 配合
wss://WebSocket - 必须启用
RequireAuth = true+ 强密码 + HTTPS
多页面与路由
每个 HMIPageDef.Route 是相对路径:
| HtmlCode 所在页 | URL |
|---|---|
Route: "/", IsHome: true | /local/ 或 /local |
Route: "/reactor" | /local/reactor |
Route: "/alarm" | /local/alarm |
页面导航:
<darra-nav-button route="/reactor">点击跳转- JS:
location.href = '/local/reactor' - 浏览器后退/前进按钮正常工作 (HTML 原生路由)
多分辨率适配
HMIProjectDef.Settings:
{
"DesignWidth": 1920,
"DesignHeight": 1080,
"AspectRatio": "16:9",
"ScaleMode": "FitRatio"
}
FitRatio(推荐): 按比例缩放, 超出的区域显示背景色 (黑边)Stretch: 拉伸填满, 会变形Fixed: 不缩放, 小屏出现滚动条
LocalHMI 外壳会根据物理屏幕尺寸计算 transform: scale(x):
body {
width: 1920px;
height: 1080px;
transform-origin: top left;
transform: scale(var(--darra-scale, 1));
}
--darra-scale 由 HmiLayoutRenderer 根据窗口尺寸动态计算。
认证与权限
启用登录 (RequireAuth = true)
Service 在所有 /local/ / /web/ 请求处拦截, 未登录重定向到 /login:
<darra-login-panel redirect-on-success="/"></darra-login-panel>
登录成功写入 Cookie darra-token (HttpOnly, 30 天), 下次请求自动带上。
角色与权限门控
<darra-permission-gate role="admin">
<darra-button var="M100.0">紧急停车</darra-button>
</darra-permission-gate>
角色集: admin / engineer / operator / viewer, 由 HmiAuthProvider 管理。
写入白名单
HMIProjectDef.WriteWhitelist 是生产环境必配项, 未在白名单的写入一律拒绝:
{
"WriteWhitelist": [ "M0.*", "DB2.Setpoint*", "MW200" ]
}
发布前检查清单
- 所有
<darra-*>的var=""都指向真实 PLC 变量 (F12 Network/ws看订阅) -
DesignWidth/Height匹配真实屏幕 (或已配 FitRatio) -
WriteWhitelist只包含必须的变量 (最小权限) -
RequireAuth在 WebHMI 必须true -
GlobalCss无语法错误 (浏览器控制台无 CSS 报错) -
JsCode无console.error(F12 控制台) - 断开 PLC 验证: 右下角出现"断开-重连中", UI 不崩
- 触摸屏测试: 按钮最小 44x44px, 不重叠
- 移动端测试: 屏幕旋转 / 软键盘不遮挡输入框
HTTPS 部署 (推荐用 nginx 反代)
server {
listen 443 ssl http2;
server_name hmi.example.com;
ssl_certificate /etc/letsencrypt/live/hmi.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hmi.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:18823;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
}
浏览器访问 https://hmi.example.com/web/ → WebSocket 自动升级为 wss://。
打包 Service + HMI 分发
IDE 菜单 发布 → 生成运行时包, 输出目录结构:
output/
Darra.PLC.Service.exe
Darra.PLC.HMI.exe
HMI/Static/ (alpine, chart, devextreme, darra-*.js/css)
HMI/Templates/ (7 个模板)
myproject.plc (含 HMIProjectDef)
run-service.bat
run-hmi.bat
双击 run-service.bat 启动 Service, run-hmi.bat 启动 LocalHMI 外壳。