夜雨聆风学习资料网

ARTICLE · 1012596

WinCC 企业微信报警实时推送插件实战 (附:控件)

WinCC 企业微信报警实时推送插件实战 (附:控件)

WinCC 企业微信报警插件实战:从零到部署,完整实现步骤

上期说了为什么报警控件,这期手把手带你做出来。


开始前需要准备的东西

工具
版本
用途
Visual Studio
2022
开发环境
.NET Framework
4.7.2
目标框架(与 WinCC V7 匹配)
WinCC
V7.4 及以上
运行环境
企业微信
免费版
创建群机器人

项目类型选择 Windows 窗体控件库 (.NET Framework),不要选 .NET Core/.NET 5+——WinCC V7 不支持。


第一步:建项目

  1. Visual Studio → 新建项目 → Windows 窗体控件库 (.NET Framework)

  2. 项目名:WinCCAlarmPlugin

  3. 目标框架:.NET Framework 4.7.2


第二步:装依赖

工具 → NuGet 包管理器 → 程序包管理器控制台:

Install-Package Newtonsoft.Json

装完之后,packages 文件夹里会有 Newtonsoft.Json.dll。记下路径,后面部署要用。


第三步:定义数据模型

在项目里新建 AlarmItem.cs:

    public enum AlarmLevel    {        Info = 0,        Warning = 1,        Critical = 2,        Emergency = 3    }    public class AlarmItem    {        public string Key { get; set; }        public string TagName { get; set; }        public string Message { get; set; }        public string Area { get; set; }        public DateTime Timestamp { get; set; }        public DateTime? RecoveredTime { get; set; }        public AlarmLevel Level { get; set; }        public bool IsActive { get; set; }        public bool IsAcknowledged { get; set; }        public int TriggerCount { get; set; }        public bool Notified { get; set; }        public string StateText        {            get            {                if (!IsActive)                {                    return "已恢复";                }                return IsAcknowledged ? "已确认" : "待处理";            }        }        public AlarmItem()        {            Key = "";            TagName = "";            Message = "";            Area = "";            Timestamp = DateTime.Now;            IsActive = true;        }    }}

第四步:写核心报警面板控件

新建 AlarmPanel.cs,这是整个插件的主控件:

    partial class AlarmPanel    {        private System.ComponentModel.IContainer components = null;        private System.Windows.Forms.TableLayoutPanel rootLayoutPanel;        private System.Windows.Forms.FlowLayoutPanel toolbarFlowLayoutPanel;        private System.Windows.Forms.Label titleLabel;        private System.Windows.Forms.Label filterLabel;        private System.Windows.Forms.ComboBox levelFilterComboBox;        private System.Windows.Forms.CheckBox showAcknowledgedCheckBox;        private System.Windows.Forms.Button acknowledgeButton;        private System.Windows.Forms.Button testButton;        private System.Windows.Forms.Button clearButton;        private System.Windows.Forms.DataGridView alarmGridView;        private System.Windows.Forms.BindingSource alarmBindingSource;        private System.Windows.Forms.StatusStrip statusStrip;        private System.Windows.Forms.ToolStripStatusLabel activeStatusLabel;        private System.Windows.Forms.ToolStripStatusLabel sendStatusLabel;        private System.Windows.Forms.ContextMenuStrip alarmContextMenuStrip;        private System.Windows.Forms.ToolStripMenuItem acknowledgeToolStrip          MenuItem;         private System.Windows.Forms.ToolStripMenuItem sendToolStripMenuItem;        private System.Windows.Forms.ToolStripMenuItem clearToolStripMenuItem;        private System.Windows.Forms.DataGridViewTextBoxColumn timestampColumn;        private System.Windows.Forms.DataGridViewTextBoxColumn levelColumn;        private System.Windows.Forms.DataGridViewTextBoxColumn tagColumn;        private System.Windows.Forms.DataGridViewTextBoxColumn messageColumn;        private System.Windows.Forms.DataGridViewTextBoxColumn areaColumn;        private System.Windows.Forms.DataGridViewTextBoxColumn stateColumn;        private System.Windows.Forms.DataGridViewTextBoxColumn countColumn;        protected override void Dispose(bool disposing)        {            if (disposing && (components != null))            {                components.Dispose();            }            base.Dispose(disposing);        }        private void InitializeComponent()        {            this.components = new System.ComponentModel.Container();            this.rootLayoutPanel = new System.Windows.Forms.TableLayoutPanel();            this.toolbarFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel();            this.titleLabel = new System.Windows.Forms.Label();            this.filterLabel = new System.Windows.Forms.Label();            this.levelFilterComboBox = new System.Windows.Forms.ComboBox();            this.showAcknowledgedCheckBox = new System.Windows.Forms.CheckBox();            this.acknowledgeButton = new System.Windows.Forms.Button();            this.testButton = new System.Windows.Forms.Button();            this.clearButton = new System.Windows.Forms.Button();            this.alarmGridView = new System.Windows.Forms.DataGridView();            this.alarmBindingSource = new System.Windows.Forms.BindingSource(this.components);            this.statusStrip = new System.Windows.Forms.StatusStrip();            this.activeStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();            this.sendStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();            this.alarmContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);            this.acknowledgeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();            this.sendToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();            this.clearToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();            this.timestampColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();            this.levelColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();            this.tagColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();            this.messageColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();            this.areaColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();            this.stateColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();            this.countColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();            this.rootLayoutPanel.SuspendLayout();            this.toolbarFlowLayoutPanel.SuspendLayout();            ((System.ComponentModel.ISupportInitialize)(this.alarmGridView)).BeginInit();            ((System.ComponentModel.ISupportInitialize)(this.alarmBindingSource)).BeginInit();            this.statusStrip.SuspendLayout();            this.alarmContextMenuStrip.SuspendLayout();            this.SuspendLayout();            //            // rootLayoutPanel            //            this.rootLayoutPanel.ColumnCount = 1;            this.rootLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));            this.rootLayoutPanel.Controls.Add(this.toolbarFlowLayoutPanel, 0, 0);            this.rootLayoutPanel.Controls.Add(this.alarmGridView, 0, 1);            this.rootLayoutPanel.Controls.Add(this.statusStrip, 0, 2);            this.rootLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;            this.rootLayoutPanel.Location = new System.Drawing.Point(0, 0);            this.rootLayoutPanel.Name = "rootLayoutPanel";            this.rootLayoutPanel.RowCount = 3;            this.rootLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 44F));            this.rootLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));            this.rootLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));            this.rootLayoutPanel.Size = new System.Drawing.Size(900, 450);            this.rootLayoutPanel.TabIndex = 0;            //            // toolbarFlowLayoutPanel            //            this.toolbarFlowLayoutPanel.AutoSize = true;            this.toolbarFlowLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;            this.toolbarFlowLayoutPanel.BackColor = System.Drawing.Color.FromArgb(244, 246, 249);            this.toolbarFlowLayoutPanel.Controls.Add(this.titleLabel);            this.toolbarFlowLayoutPanel.Controls.Add(this.filterLabel);            this.toolbarFlowLayoutPanel.Controls.Add(this.levelFilterComboBox);            this.toolbarFlowLayoutPanel.Controls.Add(this.showAcknowledgedCheckBox);            this.toolbarFlowLayoutPanel.Controls.Add(this.acknowledgeButton);            this.toolbarFlowLayoutPanel.Controls.Add(this.testButton);            this.toolbarFlowLayoutPanel.Controls.Add(this.clearButton);            this.toolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;            this.toolbarFlowLayoutPanel.Location = new System.Drawing.Point(1, 1);            this.toolbarFlowLayoutPanel.Margin = new System.Windows.Forms.Padding(0);            this.toolbarFlowLayoutPanel.Name = "toolbarFlowLayoutPanel";            this.toolbarFlowLayoutPanel.Padding = new System.Windows.Forms.Padding(8, 8, 8, 8);            this.toolbarFlowLayoutPanel.Size = new System.Drawing.Size(898, 42);            this.toolbarFlowLayoutPanel.TabIndex = 0;            this.toolbarFlowLayoutPanel.WrapContents = false;            //            // titleLabel            //            this.titleLabel.AutoSize = true;            this.titleLabel.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Bold);            this.titleLabel.Name = "titleLabel";            this.titleLabel.Margin = new System.Windows.Forms.Padding(0, 8, 12, 0);            this.titleLabel.Text = "报警列表";            //            // filterLabel            //            this.filterLabel.AutoSize = true;            this.filterLabel.Margin = new System.Windows.Forms.Padding(10, 9, 4, 0);            this.filterLabel.Name = "filterLabel";            this.filterLabel.Text = "级别";            //            // levelFilterComboBox            //            this.levelFilterComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;            this.levelFilterComboBox.DropDownWidth = 78;            this.levelFilterComboBox.FormattingEnabled = true;            this.levelFilterComboBox.Items.AddRange(new object[] {            "全部",            "信息",            "警告",            "重要",            "紧急"});            this.levelFilterComboBox.Location = new System.Drawing.Point(92, 9);            this.levelFilterComboBox.Name = "levelFilterComboBox";            this.levelFilterComboBox.Size = new System.Drawing.Size(78, 23);            this.levelFilterComboBox.TabIndex = 0;            //            // showAcknowledgedCheckBox            //            this.showAcknowledgedCheckBox.AutoSize = true;            this.showAcknowledgedCheckBox.Checked = true;            this.showAcknowledgedCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;            this.showAcknowledgedCheckBox.Margin = new System.Windows.Forms.Padding(10, 9, 4, 0);            this.showAcknowledgedCheckBox.Name = "showAcknowledgedCheckBox";            this.showAcknowledgedCheckBox.Text = "已确认";            //            // acknowledgeButton            //            this.acknowledgeButton.Location = new System.Drawing.Point(251, 8);            this.acknowledgeButton.Name = "acknowledgeButton";            this.acknowledgeButton.Size = new System.Drawing.Size(68, 26);            this.acknowledgeButton.TabIndex = 1;            this.acknowledgeButton.Text = "确认";            //            // testButton            //            this.testButton.Location = new System.Drawing.Point(323, 8);            this.testButton.Name = "testButton";            this.testButton.Size = new System.Drawing.Size(68, 26);            this.testButton.TabIndex = 2;            this.testButton.Text = "测试";            //            // clearButton            //            this.clearButton.Location = new System.Drawing.Point(395, 8);            this.clearButton.Name = "clearButton";            this.clearButton.Size = new System.Drawing.Size(68, 26);            this.clearButton.TabIndex = 3;            this.clearButton.Text = "清空";            //            // alarmGridView            //            this.alarmGridView.AllowUserToAddRows = false;            this.alarmGridView.AllowUserToDeleteRows = false;            this.alarmGridView.AllowUserToResizeRows = false;            this.alarmGridView.AutoGenerateColumns = false;            this.alarmGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;            this.alarmGridView.BackgroundColor = System.Drawing.Color.White;            this.alarmGridView.BorderStyle = System.Windows.Forms.BorderStyle.None;            this.alarmGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;            this.alarmGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {            this.timestampColumn,            this.levelColumn,            this.tagColumn,            this.messageColumn,            this.areaColumn,            this.stateColumn,            this.countColumn});            this.alarmGridView.ContextMenuStrip = this.alarmContextMenuStrip;            this.alarmGridView.DataSource = this.alarmBindingSource;            this.alarmGridView.Dock = System.Windows.Forms.DockStyle.Fill;            this.alarmGridView.Location = new System.Drawing.Point(1, 45);            this.alarmGridView.MultiSelect = false;            this.alarmGridView.Name = "alarmGridView";            this.alarmGridView.ReadOnly = true;            this.alarmGridView.RowHeadersVisible = false;            this.alarmGridView.RowHeadersWidth = 34;            this.alarmGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;            this.alarmGridView.Size = new System.Drawing.Size(898, 379);            this.alarmGridView.TabIndex = 1;            this.alarmGridView.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.AlarmGridView_CellDoubleClick);            this.alarmGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.AlarmGridView_CellFormatting);            this.alarmGridView.SelectionChanged += new System.EventHandler(this.AlarmGridView_SelectionChanged);            //            // statusStrip            //            this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {            this.activeStatusLabel,            this.sendStatusLabel});            this.statusStrip.Location = new System.Drawing.Point(1, 424);            this.statusStrip.Name = "statusStrip";            this.statusStrip.Padding = new System.Windows.Forms.Padding(8, 0, 12, 0);            this.statusStrip.Size = new System.Drawing.Size(898, 25);            this.statusStrip.TabIndex = 2;            //            // activeStatusLabel            //            this.activeStatusLabel.Name = "activeStatusLabel";            this.activeStatusLabel.Size = new System.Drawing.Size(140, 20);            this.activeStatusLabel.Text = "活动报警:0";            this.activeStatusLabel.Spring = false;            //            // sendStatusLabel            //            this.sendStatusLabel.Name = "sendStatusLabel";            this.sendStatusLabel.Size = new System.Drawing.Size(0, 20);            this.sendStatusLabel.Spring = true;            this.sendStatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;            this.sendStatusLabel.Text = "";            //            // alarmContextMenuStrip            //            this.alarmContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {            this.acknowledgeToolStripMenuItem,            this.sendToolStripMenuItem,            this.clearToolStripMenuItem});            this.alarmContextMenuStrip.Name = "alarmContextMenuStrip";            this.alarmContextMenuStrip.Size = new System.Drawing.Size(137, 70);            //            // acknowledgeToolStripMenuItem            //            this.acknowledgeToolStripMenuItem.Name = "acknowledgeToolStripMenuItem";            this.acknowledgeToolStripMenuItem.Size = new System.Drawing.Size(136, 22);            this.acknowledgeToolStripMenuItem.Text = "确认";            this.acknowledgeToolStripMenuItem.Click += new System.EventHandler(this.AcknowledgeButton_Click);            //            // sendToolStripMenuItem            //            this.sendToolStripMenuItem.Name = "sendToolStripMenuItem";            this.sendToolStripMenuItem.Size = new System.Drawing.Size(136, 22);            this.sendToolStripMenuItem.Text = "重新推送";            this.sendToolStripMenuItem.Click += new System.EventHandler(this.SendToolStripMenuItem_Click);            //            // clearToolStripMenuItem            //            this.clearToolStripMenuItem.Name = "clearToolStripMenuItem";            this.clearToolStripMenuItem.Size = new System.Drawing.Size(136, 22);            this.clearToolStripMenuItem.Text = "清空";            this.clearToolStripMenuItem.Click += new System.EventHandler(this.ClearButton_Click);            //            // columns            //            this.timestampColumn.DataPropertyName = "Timestamp";            this.timestampColumn.FillWeight = 15F;            this.timestampColumn.HeaderText = "时间";            this.timestampColumn.Name = "timestampColumn";            this.timestampColumn.ReadOnly = true;            this.timestampColumn.DefaultCellStyle.Format = "yyyy-MM-dd HH:mm:ss";            this.levelColumn.DataPropertyName = "Level";            this.levelColumn.FillWeight = 8F;            this.levelColumn.HeaderText = "级别";            this.levelColumn.Name = "levelColumn";            this.levelColumn.ReadOnly = true;            this.tagColumn.DataPropertyName = "TagName";            this.tagColumn.FillWeight = 17F;            this.tagColumn.HeaderText = "位号";            this.tagColumn.Name = "tagColumn";            this.tagColumn.ReadOnly = true;            this.messageColumn.DataPropertyName = "Message";            this.messageColumn.FillWeight = 30F;            this.messageColumn.HeaderText = "报警内容";            this.messageColumn.Name = "messageColumn";            this.messageColumn.ReadOnly = true;            this.areaColumn.DataPropertyName = "Area";            this.areaColumn.FillWeight = 13F;            this.areaColumn.HeaderText = "区域";            this.areaColumn.Name = "areaColumn";            this.areaColumn.ReadOnly = true;            this.stateColumn.DataPropertyName = "StateText";            this.stateColumn.FillWeight = 10F;            this.stateColumn.HeaderText = "状态";            this.stateColumn.Name = "stateColumn";            this.stateColumn.ReadOnly = true;            this.countColumn.DataPropertyName = "TriggerCount";            this.countColumn.FillWeight = 7F;            this.countColumn.HeaderText = "次数";            this.countColumn.Name = "countColumn";            this.countColumn.ReadOnly = true;            //            // AlarmPanel            //            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;            this.Controls.Add(this.rootLayoutPanel);            this.Name = "AlarmPanel";            this.Padding = new System.Windows.Forms.Padding(1);            this.Size = new System.Drawing.Size(900, 450);            this.rootLayoutPanel.ResumeLayout(false);            this.toolbarFlowLayoutPanel.ResumeLayout(false);            this.toolbarFlowLayoutPanel.PerformLayout();            ((System.ComponentModel.ISupportInitialize)(this.alarmGridView)).EndInit();            ((System.ComponentModel.ISupportInitialize)(this.alarmBindingSource)).EndInit();            this.statusStrip.ResumeLayout(false);            this.statusStrip.PerformLayout();            this.alarmContextMenuStrip.ResumeLayout(false);            this.ResumeLayout(false);        }    }}

第五步:注册到 WinCC

  1. 编译项目,生成 WinCCAlarm.dll
  2. 用管理员身份打开 cmd,执行:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe ^  WinCCAlarm.dll /codebase /tlb:WinCCAlarm.tlb
  1. 把 Newtonsoft.Json.dll 复制到 WinCC 的 bin 目录(通常是 C:\Program Files (x86)\SIEMENS\WinCC\bin)
  2. 打开 WinCC Graphics Designer → 工具箱右键 → 添加/删除项 → .NET Framework 组件 → 浏览选中 WinCCAlarm.dll
  3. 控件出现在工具箱中,拖到画面上即可

第六步:在 WinCC 中调用

在全局脚本中,当 WinCC 报警触发时调用插件:

如果需要手动触发(比如测试),可以直接在按钮点击事件里:

Dim panelSet panel = ScreenItems("AM1")Call panel.AddAlarmEx("R1101_TT01", "反应釜温度超过 85 度", 2, "一号车间", True)

第七步:配置企业微信机器人

  1. 登录企业微信 → 创建一个内部群
  2. 群设置 → 消息推送 → 添加
  3. 复制 Webhook 地址(形如 https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxx)
  4. 在 WinCC 画面初始化时传入:
alarmPanel.SetWeChatWebhook("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key");alarmPanel.EnableWeChat(true);

实例图片

回复“666”领取控件+配置文档

相关学习资料