582 lines
22 KiB
C#
582 lines
22 KiB
C#
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<AlarmModel> _errList = new List<AlarmModel>();
|
||
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();
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
}
|