操作员工位 HMI
操作员工位 HMI 是部署在生产线旁边、由 15"/21"/27" 触摸屏显示、全屏运行的设备操作界面。操作员按产线节奏按下启停、切换模式、确认报警、选择配方。
本章面向 HMIType.Local 项目, 即由 HMIShellForm.cs (WebView2) 全屏承载的本地 HMI, 不是远程 Web 浏览器。
核心设计原则
| 原则 | 具体做法 |
|---|---|
| 手指触摸友好 | 按钮 >= 80 × 80 px, 重要按钮更大 |
| 颜色编码 | 红=急停/报警, 黄=警告, 绿=运行, 蓝=操作, 灰=停止 |
| 极低误触率 | 关键按钮长按 2 秒确认 / 禁用双击 |
| 单屏独立操作 | 所有主要功能 2 屏以内可达, 不需滚动 |
| 无键盘依赖 | 数字/字符输入弹虚拟键盘 (<darra-input> 自带) |
| 快速视线反馈 | LED/计数/状态字号 >= 24pt |
部署: 全屏 WebView2
HMIShellForm 构造时传入 HMIType.Local, 启动后自动加载 http://localhost:18823/local/, 全屏 WebView2 无边框呈现:
// HMIShellForm.cs (核心逻辑)
public HMIShellForm(HMIType type) {
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
TopMost = true; // 可选: 置顶防止切走
_web = new WebView2 { Dock = DockStyle.Fill };
Controls.Add(_web);
_web.Source = new Uri($"http://127.0.0.1:18823/{(type==HMIType.Local?"local":"web")}/");
}
键盘快捷键
在 HMIShellForm 按键转发给 WebView2:
| 快捷键 | 行为 |
|---|---|
F11 | 切换全屏 / 窗口 (维护时用) |
Esc | 退出全屏 (需管理员密码) |
Ctrl+Shift+D | 打开 WebView DevTools (仅工程师 dongle) |
F5 | 刷新当前页 |
生产环境可禁用 Esc 退出, 防操作员误操作退出 HMI。
布局: 工位标准五区
推荐的 21" 横屏布局 (1920×1080):
+-----------------------------+--------------+
| | |
| [1] 状态大屏 (60%) | [2] 操作区 |
| 产量 / 节拍 / 工艺参数 | 启停 / 模式 |
| | |
+-------------+---------------+ |
| | | |
| [3] 配方 | [4] 报警 | |
| 换型 | 列表 | |
| | | |
+-------------+---------------+--------------+
| [5] 底栏: 当班操作员 | 时间 | 网络状态 |
+------------------------------------------------+
区块 1: 状态大屏
核心指示
<div class="status-panel">
<darra-led var="M.Running" label="运行" size="80"></darra-led>
<darra-led var="M.Pause" label="暂停" size="80" color="yellow"></darra-led>
<darra-led var="M.Fault" label="故障" size="80" color="red"></darra-led>
<darra-numeric var="MW.Cycle" label="节拍" unit="ms" digits="0" big></darra-numeric>
<darra-numeric var="MW.Yield" label="产量" unit="件" digits="0" big></darra-numeric>
<darra-numeric var="MD.Rate" label="OEE" unit="%" digits="1" big></darra-numeric>
<darra-numeric var="MW.CurrentPart" label="当前工件编号" big></darra-numeric>
</div>
big 属性让字号升至 48pt, 远距离可见。
工艺参数仪表
<darra-gauge var="MD.Temp" min="0" max="300" unit="C" size="large"></darra-gauge>
<darra-gauge var="MD.Pressure" min="0" max="10" unit="bar" size="large"></darra-gauge>
<darra-trend vars="MD.Temp,MD.Pressure" window-seconds="300"></darra-trend>
区块 2: 启停与模式
启停按钮
<div class="ctrl-buttons">
<darra-button var="M.Start" mode="momentary"
label="启动" size="xlarge" style="background:#3c3"></darra-button>
<darra-button var="M.Stop" mode="momentary"
label="停机" size="xlarge" style="background:#aaa"></darra-button>
<darra-button var="M.EStop" mode="toggle"
label="急停" size="xxlarge"
hold-to-confirm="2000"
style="background:#c00;color:white;font-weight:bold"></darra-button>
<darra-button var="M.Reset" mode="momentary"
label="复位" size="large"></darra-button>
</div>
急停采用 红色最大尺寸 + 长按 2 秒确认 (hold-to-confirm), 物理急停按钮仍然是真正的硬接线急停, HMI 的急停是"辅助急停"信号, 由 PLC 走与硬急停相同的安全链。
模式切换 (互斥按钮组)
<div class="mode-group">
<darra-button var="MW.Mode" value="1" mode="exclusive" group="mode"
label="手动"></darra-button>
<darra-button var="MW.Mode" value="2" mode="exclusive" group="mode"
label="半自动"></darra-button>
<darra-button var="MW.Mode" value="3" mode="exclusive" group="mode"
label="自动"></darra-button>
</div>
MW.Mode 单字节代表模式 (1/2/3), 三按钮互斥, 切换时 darra.write('MW.Mode', 2) 整数赋值。
切换到"手动"时, 状态区的自动产量显示变灰、点动按钮显示出来:
<template x-if="mode === 1"> <!-- 手动 -->
<div class="jog-panel">
<darra-button var="M.Jog.Fwd" mode="hold" label="点进"></darra-button>
<darra-button var="M.Jog.Rev" mode="hold" label="点退"></darra-button>
</div>
</template>
mode="hold" 按住置 TRUE, 松开置 FALSE, 适合点动控制。
区块 3: 配方选择
换型时操作员从下拉选择产品代码, HMI 向 PLC 触发读库存流程 (详见 配方入库):
<div class="recipe-panel" x-data="{ selected: '', recipes: [] }"
x-init="
// 启动时从 PLC 读配方列表 DB
darra.bindDB('DB_RecipeList', list => recipes = list.Items);
">
<label>产品代码:
<select x-model="selected"
@change="darra.write('DB_Req.RecipeCode', selected);
darra.write('M.LoadRecipe', true)">
<option value="">-- 请选择 --</option>
<template x-for="r in recipes" :key="r.Code">
<option :value="r.Code" x-text="`${r.Code} - ${r.Name}`"></option>
</template>
</select>
</label>
<darra-led var="M.RecipeLoaded" label="已加载"></darra-led>
<darra-numeric var="DB_Current.Version" label="版本"></darra-numeric>
</div>
PLC 侧用 FB_ReadRecipes 从数据库 SELECT 批量写入 PLC 的 DB 块 (配方参数是设备参数, 不是业务数据)。
区块 4: 报警列表与确认
<div class="alarm-panel">
<darra-alarm-list max-rows="8"></darra-alarm-list>
<darra-button var="M.Alm.Ack" mode="momentary" label="确认"></darra-button>
<darra-button var="M.Alm.Reset" mode="momentary" label="复位"></darra-button>
<darra-button var="M.Alm.Mute" mode="toggle" label="静音"></darra-button>
</div>
当班报警自动滚动到顶部, 严重级红色背景, 操作员按 "确认" 只清已读标记, "复位" 清除报警锁定让设备可再启动。
详细的报警分级与推送, 见 报警推送。
区块 5: 底栏 (班次交接)
<div class="footer">
<div class="shift">
当班: <span x-text="currentOperator"></span>
<button @click="openSignInDialog()">交接班</button>
</div>
<darra-clock format="HH:mm:ss"></darra-clock>
<darra-led var="$.Online" label="PLC 在线"></darra-led>
<darra-led var="$.DbOnline" label="DB 在线"></darra-led>
</div>
$.Online / $.DbOnline 是 Service 内置系统变量 (前缀 $), 分别指示 PLC 连接 / 数据库连接状态。
班次交接流程
async function openSignInDialog() {
const newOp = prompt('请输入接班操作员工号');
if (!newOp) return;
// 向 PLC 写入新操作员 (用于记录到 Historian)
await darra.writeGroup({
'DB_Shift.Operator': newOp,
'DB_Shift.SignInTime': Date.now(),
'M.ShiftChanged': true
});
currentOperator = newOp;
}
交接时自动在 Historian 记一条班次事件, 作为"谁在何时接班"的设备操作审计。
巡视模式 (屏幕保护)
5 分钟无触摸输入自动进入"巡视模式": 隐藏所有按钮, 只留大字号状态。任意触摸返回正常界面。
<div x-data="{ patrol: false, idleTimer: null }"
@click.document="
patrol = false;
clearTimeout(idleTimer);
idleTimer = setTimeout(() => patrol = true, 5 * 60 * 1000);
"
x-init="idleTimer = setTimeout(() => patrol = true, 5 * 60 * 1000)">
<div x-show="!patrol" class="full-ui">
<!-- 完整 UI -->
</div>
<div x-show="patrol" class="patrol-mode">
<darra-numeric var="MW.Cycle" label="节拍" unit="ms" big huge></darra-numeric>
<darra-numeric var="MW.Yield" label="产量" unit="件" big huge></darra-numeric>
<darra-led var="M.Running" size="200"></darra-led>
</div>
</div>
huge 属性让字号达 96pt, 走道远距离可辨识。
防误触机制
长按确认
关键按钮加 hold-to-confirm 属性, 按下开始计时, 满指定毫秒才真正触发 darra.write:
<darra-button var="M.ProdReset" mode="momentary"
hold-to-confirm="2000"
label="清零产量"></darra-button>
按下按钮 UI 进度条动画填满 2 秒后才触发。
二次确认弹窗
<darra-button var="M.Shutdown" mode="momentary"
confirm-text="确认停机并关断气源?"
label="停机"></darra-button>
禁用双击放大
body {
touch-action: manipulation; /* 禁用双击放大 */
user-select: none; /* 禁用文本选择 */
-webkit-tap-highlight-color: transparent;
}
输入框范围限制
<darra-input var="MW.SpeedSetpoint"
min="100" max="3000" step="50"
unit="rpm">
</darra-input>
超出范围自动回弹 + 震动反馈 (navigator.vibrate)。
触摸屏尺寸适配
| 尺寸 | 布局 | 字号基准 |
|---|---|---|
| 15" (1024×768) | 两列, 状态 + 操作 | 16pt |
| 21" (1920×1080) | 五区标准布局 | 18pt |
| 27" (2560×1440) | 五区 + 更大趋势图 | 20pt |
| 竖屏 10" (1080×1920) | 状态上 / 操作下 | 18pt |
CSS Grid + @media (min-width:...) 断点适配, 推荐用 rem 单位统一放大。