WinCC报警记录动态过滤与跨库查询,让操作员自己选着看
上个月帮一个朋友处理WinCC项目问题电话里他急得不行操作员在画面上点开报警控件整个车间的报警一股脑全铺在屏幕上几百条滚动信息想看一台设备的报警记录得翻到手酸。操作员的原话是“你就不能让我自己选着看吗”这个诉求翻译成WinCC工程语言就是标题里那四个字——动态选择报警记录。这篇文章我不打算只给结论而是把这个案例从头到尾拆开讲清楚为什么能动态选、怎么落地、有哪些反直觉的坑。内容覆盖两种最常见形态同一套项目里按设备/区域动态过滤以及跨数据库切到其他项目查看历史报警归档。做WinCC上位机组态的工程师、现场负责维护的技术员应该都能从里面拿到直接能用的方案。1. 这个需求是从哪个现场冒出来的三种典型场景1.1 多产线多设备混报操作员盯不过来工厂里只要是连续生产报警基本是同时涌进来的。一条线一个报警池子还算好设备一多电机过载、压力低、阀门反馈超时这些信号会集中在同一屏上刷新。操作员怕的是漏看更怕的是想找某台泵的报警记录时被无关信息淹没。我朋友那个现场就是这样三条生产线PLC里组态了几百条报警全部进了同一个WinCC报警控件。设备动作一频繁屏幕上的报警记录滚动速度快到根本看不清。操作员想确认“三号线2号水泵今天报了几次过载”只能先把报警列表暂停再拿肉眼一条一条筛。这种做法效率低而且容易看漏最关键的是没法形成可追溯的记录。这种场景下动态选择的价值不在于“把画面做得花哨”而是把报警从“流水账”变成“可检索的信息”。操作员能自己选择看哪条线、哪个设备问题定位速度完全不是一个量级。1.2 按时间段/班次追溯历史报警回忆式查询很常见还有一个高频需求是按时间找历史报警。交接班的时候操作员说“凌晨三点多二号线好像报过一回料位异常”这就要查特定时间段内的报警记录。报警控件的列表是实时滚动的时间一长之前的信息早被顶上去了。虽然有滚动条但靠滚动去找某一天某个瞬间的报警体验极差。比较现实的方案是把动态过滤条件和时间范围组合起来让操作员自己输入起止时间甚至按班次时间自动套模板一键把该时间段内符合设备条件的报警记录全部筛出来。这种需求在报表场景里尤其常见所以你会发现很多项目做到后面都会上一个“报警查询画面”本质上就是动态选择报警记录的智能化版本。1.3 跨项目集中查看中控室一屏管多套系统第三种场景就更棘手了。工厂扩建是常态老线是一套WinCC项目新线又是一套WinCC项目两套系统数据库都是独立的。生产经理坐在中控室想同时了解两条线的报警情况总不能开两台操作员站换着看。于是就有了“中控室一屏看多套项目报警”的需求。这会涉及跨WinCC项目、跨SQL Server数据库读取报警归档。这个场景比前两种更依赖底层的数据库结构和查询能力处理起来也要多花心思。2. 先看懂报警记录的底牌SQL库、消息块和报警控件的关系2.1 一条报警从发生到显示经过了哪几道工序要动态选择报警记录首先得知道报警记录在WinCC里是怎么存下来的。WinCC的报警记录组态在WinCC Explorer里的“报警记录”编辑器中完成。工程师在组态时定义报警消息、消息类型、消息块运行时由PLC变量触发WinCC将触发后的消息写入SQL Server运行的数据库里。这个存储过程和“工厂里流水线生产台账”很像每个报警就是一张表里的一行记录包含报警时间、报警编号、消息文本和若干自定义字段。报警发生后这些字段被当作一条结构化记录写入数据库供后续查询和展示。WinCC项目运行库在SQL Server里这是很多人忽略的一个关键点。你如果打开项目对应的SQL数据库能看到一大把以特定前缀开头的表其中就有报警消息归档相关的表。这些表就是报警控件取数的地方。2.2 报警控件本质上是一个带界面的查询工具WinCC画面里的报警控件Alarm Control看起来是个列表本质上却是一个查询前端。它把SQL库里的报警数据按你组态的条件拉出来再按规定的列和排序方式展示出来。打个比方报警控件就像查询快递的网页输入单号条件后台去数据库检索再把结果显示出来。正因为它是查询工具所以它必然有过滤条件配置。你在控件组态里看到的“筛选”页签就是给后台查询加where条件的地方。这里面的字段不是随便选的只能选报警消息块里已经定义好的字段比如消息编号、时间、消息文本以及自定义的消息变量字段。2.3 动态选择的命门提前把设备号、区域号塞进消息块这是整个方案里最容易被忽略却最关键的一步。很多工程师组态报警时习惯把设备名称写进消息文本里比如“三号线2号水泵电机过载”文本看起来直观但报警控件做过滤时按文本筛选不精确也不稳定。正确的做法是在报警记录编辑器里提前规划消息块字段把设备编号、区域、班次这类固定维度剥离出来放到“消息变量1”“消息变量2”等自定义字段里。这样报警文本仍然是人看的消息块字段是给机器查的。后期不管做动态过滤、做报表、做跨项目检索都靠这些结构化字段。有个反面案例有个项目当年组态时没预留消息变量报警文本全写在消息文本里。等项目投运后想按区域筛报警发现过滤器字段列表里根本没有“区域”这个选项只剩消息文本。最后只能靠消息文本来做模糊匹配数据一多查询慢误匹配也经常发生根源就是组态阶段没给“机器查询”留后路。3. 案例一下拉框选设备报警控件按变量动态过滤3.1 组态准备一个内部变量和一条能过滤的消息块字段先准备一个WinCC内部变量用来接收操作员选择的设备编号。打开WinCC变量管理新建一个文本变量名字叫DeviceFilter类型选择文本/字符型就行不用连PLC纯画面内部使用。再检查报警消息块确保设备编号存在“消息变量1”里。比如说一号线水泵过载报警组态如下消息文本水泵电机过载消息变量1设备编号Pump_1-01消息变量2区域Line1这个结构是后面一切动态过滤的基础。如果你的项目里报警消息块没有这些字段得先回报警记录编辑器把消息块补出来并确保触发报警时脚本或PLC连接能把正确的设备编号写进去。3.2 报警控件过滤器挂上画面变量接下来进入画面编辑器把报警控件拖到画面里双击打开它的组态对话框。在“筛选”页签里新增一条过滤条件字段选择“消息变量1”就是你存设备编号的那个字段运算符选择“等于”比较值来源选择“变量”不同WinCC版本叫法可能略有差异有的版本直接显示“变量”有的版本叫“动态值”选择刚才建好的DeviceFilter变量这样就实现了过滤条件运行时可变报警控件每次查询时会动态读取DeviceFilter当前的值按它去数据库里过滤。这里再补一个交互设计上的细节如果下拉框里放一个“显示全部”选项脚本里可以把DeviceFilter写成空字符串同时把报警控件过滤器的运算符改成“包含”。空字符串在“包含”条件下不会把数据过滤掉相当于显示全部。如果你的WinCC版本过滤器里没有“包含”选项那就多放一个专门显示全部的按钮把脚本逻辑分开处理。3.3 下拉框联动脚本把选择写进变量画面里加一个组合框ComboBox项目列表填上需要显示设备编号或区域名。事件选择OnChange然后在VBS脚本编辑器里写Sub OnChange(ByVal Item) Dim sSel sSel ScreenItems(ComboBox1).Text HMIRuntime.Tags(DeviceFilter).Write sSel End Sub这个脚本做两件事把当前下拉框选中的文本读出来再写进WinCC内部变量DeviceFilter。画面里如果定义了“全部”选项可以加一个判断Sub OnChange(ByVal Item) Dim sSel sSel ScreenItems(ComboBox1).Text If sSel 全部 Then sSel End If HMIRuntime.Tags(DeviceFilter).Write sSel End Sub写到这一步整个联动就算闭环了。操作员从下拉框里选了一个设备号变量被更新报警控件在下一次查询刷新时自动按新条件过滤。3.4 怎么确认“动态过滤”真的生效运行项目下拉框切换到某个设备报警列表里的记录立刻变成该设备的报警。想让这个效果看得更清楚可以在报警记录编辑器里故意组态几条不同设备的报警消息再通过变量连接或画面按钮触发它们让几条不同数据源头的报警先后进入运行库。我实际测试时习惯分三步确认不选任何设备时报警列表全部显示。选一号线某台设备列表里只剩该设备报警其他设备记录消失。再切换到一台根本不存在的编号列表变成空说明过滤条件被正确执行。第一次跑通后你会直观理解报警控件的查询本质它不是把数据“藏”起来了而是换了条SQL条件去查。关于刷新时效有些项目要求操作员选完设备后列表立刻更新。这个也好办把报警控件的刷新周期设置到1~2秒即可具体入口在控件组态的“运行系统”或“刷新”相关页签。找不到就用个笨办法选完后切换一下画面再切回来强制刷新视图但这种方式体验不流畅建议还是优先把刷新周期配好。4. 案例二跨数据库切报警归档中控室一屏看多套项目4.1 切库需求来自哪分库归档和多服务器集中查询案例一解决的是“同库内动态过滤”实际项目中还有一种需求是把数据源整体切走。最典型的是下面两类第一类项目按产线分开部署每套WinCC用独立数据库。中控室想查看任意一套系统的报警历史动态过滤已经不够用了必须切换数据源。第二类报警记录按时间段分库归档。有些工厂历史报警数据量很大项目组把超过一定时间的历史报警挪到单独的归档库从运行库切到历史库就成了一种常规操作。跨库查询在WinCC里没有“一台报警控件随时换连接串”这种公开的标准功能所以工程上常用另外两种方式实现多控件叠加切换或者画面窗口按需加载。4.2 方案A多报警控件叠加变量控制可见性这是最稳定、不带花花肠子的方案。在同一个画面里放多个报警控件一个控件连一套数据源组态时在控件属性里指定对应的服务器名和数据库名。然后通过一个内部整型变量ArchiveSel控制这些控件的可见性。画面上加一个下拉框选项分别为“一号线数据库”“二号线数据库”“历史归档库”。脚本这样写Sub OnChange(ByVal Item) Dim sSel sSel ScreenItems(ComboBox2).Text Select Case sSel Case 一号线数据库 HMIRuntime.Tags(ArchiveSel).Write 1 Case 二号线数据库 HMIRuntime.Tags(ArchiveSel).Write 2 Case 历史归档库 HMIRuntime.Tags(ArchiveSel).Write 3 End Select End Sub报警控件的Visible属性分别绑定到ArchiveSel的对应值。例如AlarmControl1的Visible属性设置为ArchiveSel 1AlarmControl2的Visible属性设置为ArchiveSel 2以此类推。这个方案的优势是稳不需要调用冷门API第一次做也能一次跑通。缺点也很明显几个报警控件同时存在一个画面里即便隐藏也会占用一定资源。库少、切换频率不高完全够用库多到四五个以上就不推荐了。4.3 方案B画面窗口按需加载报警画面更省资源的做法是用画面窗口动态加载。主画面放一个画面窗口组态好每个子画面子画面里各自放连好对应数据库的报警控件。运行时根据下拉框选择用VBS脚本加载对应子画面。Sub OnChange(ByVal Item) Dim sSel sSel ScreenItems(ComboBox3).Text Select Case sSel Case 一号线 ScreenItems(PictureWindow1).SetPictureName Overview, AlarmLine1.Pdl Case 二号线 ScreenItems(PictureWindow1).SetPictureName Overview, AlarmLine2.Pdl Case 历史库 ScreenItems(PictureWindow1).SetPictureName Overview, AlarmHistory.Pdl End Select End SubSetPictureName第一个参数通常填当前主画面的名字第二个参数是要加载的子画面文件名。不同版本对第一个参数的解释稍有差异写脚本时最好在VBS编辑器里看语法提示。画面窗口方案的好处是每次只加载一个报警控件不显示的那个控件会被整体卸载内存和数据库连接压力都小。切换时会有零点几秒的空白现场基本可以接受。这个方案至今还是我做中控室集中调用时优先采用的手段。4.4 延伸一步用ADO脚本把报警记录拉成报表如果你需要的不是报警控件展示而是“按条件查出来并做成报表”那可以再走一条更直接的路用VBS脚本通过ADO连接SQL Server查询WinCC运行数据库的报警归档表把结果用于报表或导出。Dim conn, rs, sSql Set conn CreateObject(ADODB.Connection) conn.ConnectionString ProviderSQLOLEDB.1;Data Sourcelocalhost;Initial Catalog你的WinCC项目运行库;User IDalarmreader;Password你的密码 conn.Open sSql SELECT TOP 100 * FROM 报警归档表名 WHERE 时间字段 2025-01-01 00:00:00 AND 设备字段 Pump_1-01 ORDER BY 时间字段 DESC Set rs conn.Execute(sSql) Do While Not rs.EOF 在这里按需取rs.Fields(字段名).Value rs.MoveNext Loop rs.Close conn.Close Set rs Nothing Set conn Nothing这个代码骨架在实际项目中完全可以跑但请务必注意几个问题库名和表名不要拍脑袋填。用SQL Server Management Studio连上WinCC项目库先看清楚报警归档表的实际名称和字段结构再写SQL。不要为了省事把SQL账号密码写死在脚本里更不要用sa这种超级管理员账号跑查询。给报警查询单独建一个只读账号最小权限原则在这里同样适用。查询一定要带时间范围否则数据量大时VBS脚本会卡很久严重时操作员站画面直接假死。ADO方案很适合和案例一结合起来画面下拉框选设备号和时间范围脚本按条件查库结果灌进报表或表格控件。很多WinCC报表案例本质就是这么做的。5. 落地时容易翻车的几个细节按这个顺序排最有效5.1 过滤器不生效先检查消息块字段里到底有没有值动态过滤做完运行发现筛选出来是空列表或者过滤不起作用。这种问题多半不在过滤条件本身而是消息块字段压根没存进数据。排查方法很直接在报警控件组态里临时把“消息变量1”这一列显示出来触发一条报警看看这列是否显示的是设备编号。如果显示为空说明报警消息组态时没有把设备编号填进消息变量过滤器再努力也查不到东西。这个问题在项目中期改报警组态时尤其高发。原有报警消息只填了消息文本后来加需求要按设备过滤光在控件里加过滤条件是不够的必须回头把报警消息里的消息变量字段补上并且确保以后组态新报警时同样规范填写。5.2 文本匹配的坑大小写、空格、编码都可能让人血压升高设备编号在报警消息里存的是“Pump_1-01”下拉框里写的是“pump_1-01”或者“Pump_1-01 ”多个空格结果是过滤不出数据。文本类过滤条件对字符串完全匹配比较敏感大小写不一致、首尾空格、全角半角都会影响结果。我建议做三件事设备编号统一用大写字母和下划线写报警消息和组合框选项时严格执行同一套规范。组合框选项里不要手敲空格如果设备编号有固定格式直接从PLC程序或报警组态里复制出来。遇到对象编号有前缀逻辑的比如地区代码设备代码建议拆成多个消息块字段而不是拼在一个字段里做模糊匹配。5.3 刷新卡顿过滤条件要带上时间范围报警数据量上来以后动态过滤会出现明显的刷新延迟。很多工程师第一反应是“报警控件性能不行”实际上数据库里要扫全表能不慢吗。处理思路有两个方向。一是给报警控件加上时间范围过滤比如默认只看最近24小时操作员需要查更早记录时再手工调整起止时间。二是把自动刷新周期调大一点建议从几百毫秒级别改到2秒以上避免操作员频繁操作时反复触发全量查询。有些项目还要在数据库侧做归档策略把早期报警定期转储到历史库运行库里只保留一两个月的数据。这样实时画面查询速度大幅提升历史查询走专门的库和画面互不拖累。5.4 历史报警查不到先查归档配置和系统时钟用动态过滤查历史报警时偶尔会出现“实时报警正常历史报警隔天就查不到”的情况。这通常不是过滤条件的问题而是归档链路没配好。WinCC报警记录有按时间归档、按数量归档等策略。如果归档周期设置不正确或者报警记录长时间不归档数据就一直停留在运行状态里查询条件稍微一跨时间范围就抓不到记录。另外容易忽略的是时钟同步。工控现场最常见的就是操作员站和PLC之间的时间不同步或者服务器时间漂移。报警记录带的时间戳不对按时间范围一过滤记录可能分分钟被划到错误的时间段里自然查不到。新项目上线时建议把系统的NTP校时弄好这个基础工作能省掉后面一大半报警追溯的麻烦。5.5 跨库连接的安全与连接池问题最后一个坑属于运维层面的。用ADO跨库查询时如果脚本里写死带密码的连接字符串时间长了容易泄露而且SQL Server账户密码变更后脚本全部失效。我给这类查询定了三条规矩单独建只读账户只授予报警归档表的SELECT权限。连接字符串集中放在一个公共脚本文件或变量里不要在每个画面脚本里各自写一遍。脚本结束时一定要释放对象否则连接堆积SQL Server的连接数很快被耗尽。这些规矩看起来不起眼但项目跑两三年后你就知道它们的价值了。回到开头那个朋友的现场我最后给他的方案就是组合拳实时报警画面用下拉框动态过滤中控室跨项目查看用画面窗口切换子画面历史报表用ADO按设备和时间段拉库。三条路径共用一套消息块字段结构维护起来很整齐。动态选择报警记录这件事说难不难说简单也有不少前置条件。最核心的经验就一条组态阶段一定要把消息块字段规划好设备编号、区域、班次这些结构化信息必须放进可过滤字段否则后面做什么都费劲。你先在测试项目里跑通案例一再按现场需求加切库和报表一步步来整个功能不会给你挖特别深的坑。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →