using HMI.Core.Api; using HMI.Core.Entity; using HMI.Core.Setting; using HMI.Core.Util; using S7Driver; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Timers; namespace HMI.Util.Alarm { public class AlarmHelper : IDisposable { public event EventHandler> OnAlarm; public event EventHandler LoadMessageAppend; internal AlarmHelper() { } public ObservableCollection BlockSettings { get; private set; } Dictionary> BlockMap = new Dictionary>(); Dictionary BlockReadCache = new Dictionary(); public ObservableCollection MarkSettings { get; private set; } private string blockFilePath = PathHelper.BlockAlarmSettingPath(); private string markFilePath = PathHelper.MarkAlarmSettingPath(); /// /// 接收报警的队列 /// private MSMQHelper alarmQueue = new MSMQHelper("HMI_Alarm"); /// /// 刷新报警的队列 /// private MSMQHelper alarmRefershToMain = new MSMQHelper("LTHMI_Alarm_Rrfresh"); private PLCS7Driver pLCS7Driver; private Timer plcTimer; private Timer mqTimer; /// /// 报警信息缓存 /// private List currentPLCAlarmCache = new List(); /// /// 报警信息缓存 /// private List currentMQAlarmCache = new List(); private bool isHaveAlarm = false; private volatile bool isClosing = false; public void InitInstance() { LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.INIT, Message = "加载报警设置..." }); LoadAlarmSetting(); var systemSetting = SystemSetting.Instance; pLCS7Driver = new PLCS7Driver(systemSetting.PlcIp, systemSetting.PlcPort); plcTimer = new Timer { Interval = 1000, AutoReset = false }; plcTimer.Elapsed += PLCTimer_Elapsed; if (pLCS7Driver.Connect(out string errMSg)) { plcTimer.Start(); } else { LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.INIT, Message = "连接PLC失败", Result = false }); } mqTimer = new Timer { Interval = 1000, AutoReset = false }; mqTimer.Elapsed += MQTimer_Elapsed; mqTimer.Enabled = true; } public void Dispose() { isClosing = true; mqTimer.Enabled = false; mqTimer?.Dispose(); plcTimer.Enabled = false; plcTimer?.Dispose(); pLCS7Driver?.Dispose(); } /// /// PLC报警读取 /// /// /// private void PLCTimer_Elapsed(object sender, ElapsedEventArgs e) { try { plcTimer.Enabled = false; isHaveAlarm = false; List cache = new List(); foreach (var key in BlockMap.Keys) { if (pLCS7Driver.ReadShort(key, out short alarmVal, out string errMsg) && BlockMap[key].ContainsKey(alarmVal.ToString())) { //if(BlockReadCache.ContainsKey(key) && alarmCode) var alarmCode = alarmVal.ToString(); isHaveAlarm = true; var text = BlockMap[key][alarmCode]?.Description; var newAlarm = new AlarmText { PLC_DB_BLOCK = key, Source = "PLC", AlarmCode = alarmCode, VirtualId = $"{key}.{alarmCode}", Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmInfo = $"{text}", Level = BlockMap[key][alarmCode]?.Level ?? 0d }; if (currentPLCAlarmCache .Find(alarm => alarm.VirtualId == newAlarm.VirtualId && alarm.PLC_DB_BLOCK == newAlarm.PLC_DB_BLOCK) == null) { currentPLCAlarmCache.Add(newAlarm); } } } foreach (var item in MarkSettings) { var name = $"{item.DBAddress}.{item.StartAddress}"; if (pLCS7Driver.ReadShort(name, out short alarmVal, out string errMsg) && alarmVal != 0) { var alarmCode = alarmVal.ToString(); isHaveAlarm = true; var newAlarm = new AlarmText { Source = "PLC", VirtualId = alarmCode, Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmInfo = item.Description }; if (currentPLCAlarmCache .Find(d => d.AlarmInfo == newAlarm.AlarmInfo) == null) { currentPLCAlarmCache.Add(newAlarm); } } } RefershAlarm(); //if (!isHaveAlarm) currentAlarmCachePlc.Clear(); } catch (Exception ex) { //log.Error("Read OPCServer Data Error.", ex); } finally { if (!isClosing) plcTimer.Enabled = true; } } private void RefershAlarm() { alarmRefershToMain.Send("AlarmRefersh", string.Empty); List alarms = new List(); foreach (AlarmText alarm in currentPLCAlarmCache) { alarm.IsPLCAlarm = true; if (AlarmShowHelper.ShowAlarm(alarm)) { alarms.Add(alarm); } } currentPLCAlarmCache.Clear(); foreach (AlarmText alarm in currentMQAlarmCache) { alarm.IsPLCAlarm = false; if (AlarmShowHelper.ShowAlarm(alarm)) { alarms.Add(alarm); } } currentMQAlarmCache.Clear(); OnAlarm?.Invoke(this, alarms); } private void MQTimer_Elapsed(object sender, ElapsedEventArgs e) { try { mqTimer.Enabled = false; alarmQueue.Receive(100, out string MessageID, out string MsgStr); if (MessageID != string.Empty) { switch (MessageID) { case "Clear": currentMQAlarmCache.Clear(); RefershAlarm(); break; case "AlarmCode": //AlarmText aalarm = AlarmTexts.FirstOrDefault(alarm => alarm.AlarmCode == MsgStr); //if (aalarm == null) break; //var data = new AlarmText //{ // Source = "PC", // AlarmCode = aalarm.AlarmCode, // AlarmInfo = aalarm.AlarmInfo, // Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") //}; ////aalarm.Source = "PC"; ////aalarm.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") //if (currentMQAlarmCache.Find(alarm => alarm.AlarmCode == aalarm.AlarmCode) == null) //{ // currentMQAlarmCache.Add(data); // RefershAlarm(); //} break; default: string[] arr = MsgStr.Split(','); string source = "PC"; string info = string.Empty; if (arr.Length > 1) { source = arr[0]; info = arr[1]; } else { info = MsgStr; } AlarmText newAlarm = new AlarmText { Source = source, VirtualId = $"{source}:{info}", AlarmInfo = info, Level = 3, Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; if (currentMQAlarmCache .Find(alarm => alarm.Source == newAlarm.Source && alarm.AlarmInfo == newAlarm.AlarmInfo) == null) { currentMQAlarmCache.Add(newAlarm); RefershAlarm(); } break; } } } catch (Exception ex) { //log.Error("PcTimer Execute Failed", ex); } finally { if (!isClosing) mqTimer.Enabled = true; } } public void RefreshBlockSettings() { BlockMap.Clear(); BlockReadCache.Clear(); try { BlockSettings = XmlHelper.DeserializeFromXml>(blockFilePath); } catch (Exception ex) { //log.Error("LoadAlarmSetting Error.", ex); BlockSettings = new ObservableCollection(); } foreach (var setting in BlockSettings) { string key = $"{setting.DBAddress}.{setting.StartAddress}"; if (!BlockMap.ContainsKey(key)) { BlockMap[key] = new Dictionary(); } var codes = BlockMap[key]; codes[setting.AlarmCode] = setting; } } public void RefreshMarkSettings() { try { MarkSettings = XmlHelper.DeserializeFromXml>(markFilePath); } catch (Exception ex) { //log.Error("LoadAlarmSetting Error.", ex); MarkSettings = new ObservableCollection(); } } public void LoadAlarmSetting() { RefreshBlockSettings(); RefreshMarkSettings(); } public void UpdateBlockSettings(IEnumerable settings) { XmlHelper.SerializeToXml(blockFilePath, settings); RefreshBlockSettings(); } public void UpdateMarkSettings(IEnumerable settings) { XmlHelper.SerializeToXml(markFilePath, settings); RefreshMarkSettings(); } } public class AlarmUtil { static AlarmHelper Instance { get; set; } public static event EventHandler> OnAlarm; public static event EventHandler LoadMessageAppend; public static ObservableCollection BlockSettings { get => Instance?.BlockSettings; } public static ObservableCollection MarkSettings { get => Instance?.MarkSettings; } public static void Init() { Instance = new AlarmHelper(); Instance.LoadMessageAppend += Instance_LoadMessageAppend; ; Instance.InitInstance(); Instance.OnAlarm += Instance_OnAlarm; } private static void Instance_LoadMessageAppend(object sender, LoadMsg e) { LoadMessageAppend?.Invoke(sender, e); } private static void Instance_OnAlarm(object sender, List e) { OnAlarm?.Invoke(sender, e); } public static void Release() { if (Instance != null) { Instance.OnAlarm -= Instance_OnAlarm; } Instance?.Dispose(); Instance = null; } public static void UpdateBlockSettings(IEnumerable settings) { Instance?.UpdateBlockSettings(settings); } public static void UpdateMarkSettings(IEnumerable settings) { Instance?.UpdateBlockSettings(settings); } } }