using CowainHmi.UIEditor; using PCHMI; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Drawing.Design; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers; using System.Windows.Forms; using static System.Net.Mime.MediaTypeNames; namespace CowainHmi.Alarm { public partial class AlarmNow : UserControl { private string fileName = ""; [Browsable(true)] [Category("PCHMI"), Description("设置报警文件名称")] [Editor(typeof(AlarmUIEditor), typeof(UITypeEditor))] public string FileName { get { return this.fileName; } set { this.fileName = value; } } private bool autoShow = true; [Category("PCHMI"), Description("是否自动弹出报警窗口")] public bool AutoShow { get { return autoShow; } set { autoShow = value; } } private bool linkErrEnable; [Category("PCHMI"), Description("通讯报警是否捕获")] public bool LinkErrEnable { get { return linkErrEnable; } set { linkErrEnable = value; } } private string upLoadAddr = ""; [Category("PCHMI"), Description("数据上传命令地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string UpLoadAddr { get { return upLoadAddr; } set { upLoadAddr = value; } } private string upCountAddr = ""; [Category("PCHMI"), Description("数据上传计数地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string UpCountAddr { get { return upCountAddr; } set { upCountAddr = value; } } private string levelAddr = ""; [Category("PCHMI"), Description("报警等级地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string LevelAddr { get { return levelAddr; } set { levelAddr = value; } } private string groupAddr = ""; [Category("PCHMI"), Description("报警组地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string GroupAddr { get { return groupAddr; } set { groupAddr = value; } } private string idAddr = ""; [Category("PCHMI"), Description("报警ID地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string IdAddr { get { return idAddr; } set { idAddr = value; } } private string sd1Addr = ""; [Category("PCHMI"), Description("报警SD1地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string Sd1Addr { get { return sd1Addr; } set { sd1Addr = value; } } private string sd2Addr = ""; [Category("PCHMI"), Description("报警SD2地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string Sd2Addr { get { return sd2Addr; } set { sd2Addr = value; } } private string sd3Addr = ""; [Category("PCHMI"), Description("报警SD3地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string Sd3Addr { get { return sd3Addr; } set { sd3Addr = value; } } private string errTextAddr = ""; [Category("PCHMI"), Description("报警文本地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string ErrTextAddr { get { return errTextAddr; } set { errTextAddr = value; } } private string retAddr = ""; [Category("PCHMI"), Description("报警反馈命令地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string RetAddr { get { return retAddr; } set { retAddr = value; } } private string retCountAddr = ""; [Category("PCHMI"), Description("报警反馈计数地址")] [Editor(typeof(StringText), typeof(UITypeEditor))] public string RetCountAddr { get { return retCountAddr; } set { retCountAddr = value; } } private int plcId = 0; [Category("PCHMI"), Description("PLC编号")] public int PLCId { get { return plcId; } set { plcId = value; } } public int ErrorCount { get; private set; } public bool Error { get; private set; } private int retCountSave; private bool newError; private bool chgError; private DataTable _errTable = new DataTable(); private List _errList = new List(); public AlarmNow() { InitializeComponent(); _errTable.Columns.Add("PLC", typeof(string)); _errTable.Columns.Add("DTIM", typeof(string)); _errTable.Columns.Add("报警类别", typeof(string)); _errTable.Columns.Add("报警组", typeof(string)); _errTable.Columns.Add("ID", typeof(string)); _errTable.Columns.Add("ErrText", typeof(string)); _errTable.Columns.Add("TP", typeof(string)); // 确保控件重绘时调用OnPaint this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true); } private void AlarmNow_Load(object sender, EventArgs e) { if (string.IsNullOrEmpty(FileName)) { FileName = this.Name; } InitErrExcel(); //刚打开时加载实时报警表格 var rt = AlarmExcelHelper.GetAlarmRT(FileName); if (rt != null) { var list = rt.Select("TP='1'"); foreach (var item in list) { _errTable.Rows.Add(item.ItemArray); } } //初始读一次,相当于注册变量 ushort level = PCHMI.RT.GET_UINT16(PLCId, LevelAddr); ushort group = PCHMI.RT.GET_UINT16(PLCId, GroupAddr); int id = PCHMI.RT.GET_UINT16(PLCId, IdAddr) + 10000; short sd1 = PCHMI.RT.GET_INT16(PLCId, Sd1Addr); int sd2 = PCHMI.RT.GET_INT32(PLCId, Sd2Addr); float sd3 = PCHMI.RT.GET_F32(PLCId, Sd3Addr); string errText = PCHMI.RT.GET_SIEMENS_STRING(PLCId, ErrTextAddr, 100); ushort count = PCHMI.RT.GET_UINT16(PLCId, UpCountAddr); short upLoad = PCHMI.RT.GET_INT16(PLCId, UpLoadAddr); timer1.Enabled = true; } private void InitErrExcel() { if (!string.IsNullOrEmpty(FileName)) { //读取报警表格文件 DataTable _errExcel = AlarmExcelHelper.ReadErrExcel(FileName); if (_errExcel != null && _errExcel.Rows.Count > 0) { for (int i = 0; i < _errExcel.Rows.Count; i++) { DataRow row = _errExcel.Rows[i]; AlarmModel model = new AlarmModel(); model.PLC = Convert.ToInt32(row["PLC"]); model.VarType = row["类型"].ToString(); model.Address = row["地址"].ToString(); model.ErrCode = row["代码"].ToString(); model.Level = row["等级"].ToString(); model.Language = new string[] { row["语言1"].ToString(), row["语言2"].ToString(), row["语言3"].ToString(), row["语言4"].ToString(), row["语言5"].ToString(), row["语言6"].ToString(), row["语言7"].ToString(), row["语言8"].ToString() }; if (!int.TryParse(row["触发条件"].ToString(), out int tp)) { continue; } model.TP = tp; if (!int.TryParse(row["报警组"].ToString(), out int group)) { continue; } model.Group = group; _errList.Add(model); } } } } private bool isFlg = false; private void timer1_Tick(object sender, EventArgs e) { if (isFlg) { return; } isFlg = true; if (this.DesignMode) { return; } if (!PClass.SystemRun) { return; } //通讯报警 if (LinkErrEnable) { for (int i = 0; i < 10; i++) { if (!PClass.IsPlcLink(i)) { //报警发生,查询表格中是否存在此报警 var dr = _errTable.Select($"报警类别='{AlarmType.错误.ToString()}' and 报警组='S' and ID='0'").FirstOrDefault(); if (dr == null) { //添加报警到table中 _errTable.Rows.Add(new object[] { PLCId.ToString(), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff"), AlarmType.错误.ToString(),//错误类型 "S",//组 "0",//ID $"PLC{PLCId},连接异常", //错误信息 "1" }); newError = true; } } else { //通讯报警离开 var dr = _errTable.Select($"报警类别='{AlarmType.错误.ToString()}' and 报警组='S' and ID='0'").FirstOrDefault(); if (dr != null) { //删除报警 _errTable.Rows.Remove(dr); } } } } if (PClass.IsPlcLink(PLCId) && !string.IsNullOrEmpty(UpLoadAddr)) { //循环读数据,PLC主动上传报警 ushort level = PCHMI.RT.GET_UINT16(PLCId, LevelAddr); ushort group = PCHMI.RT.GET_UINT16(PLCId, GroupAddr); int id = PCHMI.RT.GET_UINT16(PLCId, IdAddr) + 10000; short sd1 = PCHMI.RT.GET_INT16(PLCId, Sd1Addr); int sd2 = PCHMI.RT.GET_INT32(PLCId, Sd2Addr); float sd3 = PCHMI.RT.GET_F32(PLCId, Sd3Addr); string errText = PCHMI.RT.GET_SIEMENS_STRING(PLCId, ErrTextAddr, 100); ushort count = PCHMI.RT.GET_UINT16(PLCId, UpCountAddr); short upLoad = PCHMI.RT.GET_INT16(PLCId, UpLoadAddr); if (retCountSave != count && upLoad > 0) { //计数改变,需要上传数据 string errMsg = errText.Replace("{1}", sd1.ToString()).Replace("{2}", sd2.ToString()).Replace("{3}", sd3.ToString()); string alarmType = ((AlarmType)level).ToString(); if (upLoad == 1) { //报警发生,添加报警,还需要写到实时数据库中 var dr = _errTable.Select($"报警类别='{alarmType}' and 报警组='{group}' and ID='{id}'").FirstOrDefault(); if (dr == null) { _errTable.Rows.Add(new object[] { PLCId.ToString(), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff"), alarmType,//错误类型 group.ToString(),//组 id.ToString(),//ID errMsg, //错误信息 "1" }); AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), errMsg, true, FileName); AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), "1", errMsg); } PCHMI.RT.SEND_UINT16(PLCId, RetAddr, 1); PCHMI.RT.SEND_UINT16(PLCId, RetCountAddr, count); retCountSave = count; newError = true; } else if (upLoad == 2) { //报警离开 var dr = _errTable.Select($"报警类别='{alarmType}' and 报警组='{group}' and ID='{id}'").FirstOrDefault(); if (dr != null) { _errTable.Rows.Remove(dr); AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), errMsg, false, FileName); AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), "0", errMsg); } PCHMI.RT.SEND_UINT16(PLCId, RetAddr, 1); PCHMI.RT.SEND_UINT16(PLCId, RetCountAddr, count); retCountSave = count; } } } if (_errList.Count > 0) { //判断报警表格中是否有报警发生 foreach (var alarmModel in _errList) { if (CONFIG.PLC_OFF[alarmModel.PLC]) { continue; } switch (alarmModel.VarType) { case "BIT": alarmModel.CurValue = (int)PCHMI.RT.GET_BIT(alarmModel.PLC, alarmModel.Address); break; case "INT16": alarmModel.CurValue = (int)PCHMI.RT.GET_INT16(alarmModel.PLC, alarmModel.Address); break; case "UINT16": alarmModel.CurValue = (int)PCHMI.RT.GET_UINT16(alarmModel.PLC, alarmModel.Address); break; case "INT32": alarmModel.CurValue = PCHMI.RT.GET_INT32(alarmModel.PLC, alarmModel.Address); break; case "UINT32": alarmModel.CurValue = (int)PCHMI.RT.GET_UINT32(alarmModel.PLC, alarmModel.Address); break; default: break; } if (alarmModel.CurValue != alarmModel.LastValue) { //值改变 if (alarmModel.CurValue == alarmModel.TP) { //报警发生 var dr = _errTable.Select($"报警类别='{alarmModel.Level}' and 报警组='{alarmModel.Group}' and ID='{alarmModel.ErrCode}'").FirstOrDefault(); if (dr == null) { _errTable.Rows.Add(new object[] { PLCId.ToString(), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff"), alarmModel.Level,//错误类型 alarmModel.Group.ToString(),//组 alarmModel.ErrCode.ToString(),//ID alarmModel.Language[GLOBAL.Language], //错误信息 "1" }); //AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), alarmModel.Language[GLOBAL.Language], true, FileName); AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), "1", alarmModel.Language[GLOBAL.Language]); newError = true; } } else { //报警离开 var dr = _errTable.Select($"报警类别='{alarmModel.Level}' and 报警组='{alarmModel.Group.ToString()}' and ID='{alarmModel.ErrCode.ToString()}'").FirstOrDefault(); if (dr != null) { _errTable.Rows.Remove(dr); //AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), alarmModel.Language[GLOBAL.Language], false, FileName); AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), "0", alarmModel.Language[GLOBAL.Language]); } } } alarmModel.LastValue = alarmModel.CurValue; } } ErrorCount = _errTable.Rows.Count; Error = ErrorCount > 0 ? true : false; if (Error) { //有报警 chgError = !chgError; //控制报警图标闪烁 this.BackgroundImage = chgError ? global::CowainHmi.Properties.Resources.alarm1 : global::CowainHmi.Properties.Resources.Alarm; if (newError & this.AutoShow) { //有新报警出现,自动弹窗 ShowErrDlg(); } } else { //无报警 this.BackgroundImage = global::CowainHmi.Properties.Resources.alarm1; } isFlg = false; } DlgAlarmNow dlgAlarm; private void ShowErrDlg() { //弹出报警窗口 if (dlgAlarm == null) { dlgAlarm = new DlgAlarmNow(_errTable); } dlgAlarm.Show(); //显示窗体 dlgAlarm.WindowState = FormWindowState.Normal; dlgAlarm.Activate(); newError = false; } private void AlarmNow_MouseDown(object sender, MouseEventArgs e) { ShowErrDlg(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); if (ErrorCount == 0) { return; } using (Brush brush = new SolidBrush(ForeColor)) { // 获取Graphics对象 Graphics g = e.Graphics; // 获取控件的绘制区域 // 计算字符串绘制的起始位置(控件的右上角,留出一些内边距) //PointF textPosition = new PointF(this.Width - g.MeasureString(ErrorCount.ToString(), this.Font).Width - padding, padding); PointF textPosition = new PointF(1, 7); // 设置字符串格式,这里我们使用StringFormat来居中字符串 StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Near; sf.LineAlignment = StringAlignment.Center; g.DrawString(ErrorCount.ToString(), this.Font, brush, textPosition, sf); sf.Dispose(); } } } }