VisualHMI - 告警记录

在工业自动化的人机界面(HMI)应用场景中,当单个HMI上位机需连接多个PLC设备时,若各PLC产生的告警数量庞大且内容一致,使用VisualHMI软件内置的图形化告警配置界面会显得效率低下、操作繁琐且灵活性不足。
为解决此问题,可通过编写LUA脚本的方式来实现告警的集中管理。该方法的核心优势在于:利用脚本读取来自不同PLC的告警数据源,触发,解触,并解析告警信息,从而绕过可视化配置的限制,大幅提升配置效率与系统的可维护性。
使用范围:VisualHMI - HMI&M系列&Dx系列
1.应用背景
假设基于Modbus RTU通讯的应用中,HMI通过串行总线连接8台PLC设备(站地址1~8),每台PLC均定义100个同构告警点(地址连续,例如每个PLC的告警起始地址为4x1000,连续6个地址,每个地址的一个bit对应一个告警状态)

2.API说明
2.1.warning_set_mode(en)
告警触发模式控制函数,warning_set_mode(en) 是 HMI 脚本告警系统的全局使能开关,用于启用后,需要 warning_set 函数的告警触发。
📊 参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
en |
number | 告警模式使能标志 • 1:开启Lua解析告警模式• 0:关闭Lua解析告警模式 |
2.2.warning_set(warning_id,value,count)
批量告警状态设置函数,warning_set() 是 HMI 脚本告警系统的核心操作接口,用于按位批量触发或清除连续的告警条目。该函数将 value 视为一个位掩码(bitmap),其低 count 位分别对应从 warning_id 开始的 count 个告警的状态(1=触发,0=清除)。
🔑 前提条件:必须先调用 warning_set_mode(1) 启用脚本告警模式,否则本函数无效。
📊 参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
warning_id |
number | 起始告警 ID(从 0 开始) |
value |
number | 告警状态位图(16 位) • 最低位(bit 0)对应 warning_id • bit 1 对应 warning_id + 1,依此类推 • 每BIT: 1 = 触发告警,0 = 清除告警 |
count |
number | 连续操作的告警数量 • 取值范围:1 ~ 16 |
5.3.on_parse_warning(id, text, screen_id, control_id, p0, p1, p2, p3)
告警内容动态解析回调函数,on_parse_warning 是 HMI 系统提供的告警文本自定义生成接口,开发者根据告警 ID、画面信息,生成自定义的告警描述字符串。
📊 参数说明
参数 类型 说明 idnumber 告警 ID*
• 对应warning_set中使用的warning_id
• 用于区分不同类型的告警textstring 原始告警文本
• 此处可以忽略,因为本回调中,拼接新的字符串返回screen_idnumber 当前画面 ID control_idnumber 当前控件 ID p0~p3number 告警参数(0~3)
• 仅在工程中为该告警启用了参数功能时有效
• 实际值由on_get_warning_param回调提供,详细参考API说明
返回值
| 返回值 | 类型 | 说明 |
|---|---|---|
str |
string | 告警描述字符串 • 支持拼接变量、单位、状态等 • 示例: "电机#3 温度 98°C 超过阈值 95°C!",带参配合on_get_warning_param `实现 |
encode |
number | 字符编码标识(可选) • 1:表示返回字符串为 UTF-8 编码(默认) • 0:GBK-8 编码 |
3.应用
3.1.告警设置
“工程”→“告警设置”配置如下所示:
假设HMI接8个PLC,1个PLC有96个告警,则设置告警条数768(该参数,不能小于实际告警条数)

3.2.告警显示
“告警控件”属性配置如下所示:

3.3.编辑Lua
3.3.1.初始化
在Lua脚本on_init里,启用Lua告警解析,并初始化读8个从机的告警寄存器
function on_init()
warning_set_mode(1) --启用Lua告警解析
set_auto_read(0) --脚本控制读取
create_resp_que() --队列发送,使能回调 on_cmd_resp
for i = 0, 7
do
select_slave(i)
start_read(i+1, VT_4x, 0x1000, 6) --读取从机1~8的告警
end
end
3.3.2.触发/解除告警
读取每个从机告警,在系统回调on_cmd_resp函数里面,依次解析每个从机、每个寄存器(0x1000~0x1005),每个位(bit0~bit15)的状态
_warningTb = {
--4x1000, bit0~bit15
'相序保护',--bit0
'水流开关保护',
'水位开关保护',
'制热出水温度过高',
'下水流开关断开',
'1#电流故障',
'2#电流故障',
'线控器通讯故障',
'进水传感器故障',
'出水传感器故障',
'水箱传感器故障',
'环境传感器故障',
'1#盘管传感器故障',
'2#盘管传感器故障',
'1#排气传感器故障',
'2#排气传感器故障',--bit15
--4x1001, bit0~bit15
'下回水传感器故障',--bit0
'1#回气传感器故障',
'2#回气传感器故障',
'1#高压开关保护',
'2#高压开关保护',
'1#低压开关保护',
'2#低压开关保护',
'冬季防冻保护',
'制冷进出水温度过低保护',
'进出水温差过大保护',
'1#制热环境与盘管温差过大保护',
'2#制热环境与盘管温差过大保护',
'3#制热环境与盘管温差过大保护',
'4#制热环境与盘管温差过大保护',
'3#电流故障',
'4#电流故障',--bit15
--4x1002, bit0~bit15
'1#增焓进口传感器故障',--bit0
'2#增焓进口传感器故障',
'预留',
'子设备掉线',
'1#增焓出口传感器故障',
'2#增焓出口传感器故障',
'3#增焓出口传感器故障',
'4#增焓出口传感器故障',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',--bit15
--4x1003, bit0~bit15
'压机1过载保护',--bit0
'压机2过载保护',
'压机3过载保护',
'压机4过载保护',
'内风机1过载保护',
'内风机2过载保护',
'内风机3过载保护',
'内风机4过载保护',
'外风机1过载保护',
'外风机2过载保护',
'外风机3过载保护',
'外风机4过载保护',
'电辅热1过载保护',
'电辅热2过载保护',
'电辅热3过载保护',
'电辅热4过载保护',--bit15
--4x1004, bit0~bit15
'系统1高压保护',--bit0
'系统2高压保护',
'系统3高压保护',
'系统4高压保护',
'系统1低压保护',
'系统2低压保护',
'系统3低压保护',
'系统4低压保护',
'系统1排气过高保护',
'系统2排气过高保护',
'系统3排气过高保护',
'系统4排气过高保护',
'系统1电流保护',
'系统2电流保护',
'系统3电流保护',
'系统4电流保护',--bit15
--4x1005, bit0~bit15
'室内翅片1探头故障',--bit0
'室内翅片2探头故障',
'室内翅片3探头故障',
'室内翅片4探头故障',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',
'预留',--bit15
}
function on_cmd_resp(slave,vtype,addr,count,ret,wr)
if ret == 0 and wr == 0
then
if vtype == VT_4x and addr == 0x1000 and count == 6
then
select_slave(slave) -- 从机1~8
for i = 0, 5 --6个告警寄存器
do
local val = get_uint16(VT_4x, 0x1000 + i)
for j = 0, 15 --16个bit
do
local idx = i*16 + j + 1
if idx ~= 35 and (not (idx >= 41 and idx <= 48)) and (not (idx >= 85 and idx <= 96)) --跳过“预留”bit
then
--1~100:从机1告警ID
--101~200:从机2告警ID
--201~300:从机3告警ID
--301~400:从机4告警ID
--401~500:从机5告警ID
--501~600:从机6告警ID
--601~700:从机7告警ID
--701~800:从机8告警ID
warning_set(idx + slave*100 ,((val >> j) & 0x01), 1)
end
end
end
end
end
end
3.3.3.解析告警
根据告警id范围,区分那个从机触发的告警,在返回的字符串拼接上前缀“从机X”
function on_parse_warning(id, text, screen_id, control_id, p0, p1, p2, p3)
--1~100:从机1告警ID
--101~200:从机2告警ID
--201~300:从机3告警ID
--301~400:从机4告警ID
--401~500:从机5告警ID
--501~600:从机6告警ID
--601~700:从机7告警ID
--701~800:从机8告警ID
local slaveId = (id // 96) + 1 --第几个从机
local msgId = id % 96 --告警类型ID
local curWarnMsg = '' --告警字符
if msgId == 0 then msgId = 96 end
curWarnMsg = '从机'..string.format('%02d', slaveId).. ': '.._warningTb[msgId]
return curWarnMsg, 1 --返回GBK编码
end
3.3.4.运行预览
运行虚拟屏,和Modbus slave 连接,如下所示:
