using HMI.Core.Api;
|
using HMI.Core.Entity;
|
using HMI.Core.Setting;
|
using HMI.Core.Util;
|
using HMI.Simple.Util;
|
using log4net;
|
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<List<AlarmText>> OnAlarm;
|
|
public event EventHandler<LoadMsg> LoadMessageAppend;
|
|
internal static ILog log = LogManager.GetLogger("AlarmHelper");
|
|
internal AlarmHelper()
|
{
|
|
}
|
|
public ObservableCollection<AlarmSetting> BlockSettings { get; private set; }
|
Dictionary<string, Dictionary<string, AlarmSetting>> BlockMap = new Dictionary<string, Dictionary<string, AlarmSetting>>();
|
Dictionary<string, string> BlockReadCache = new Dictionary<string, string>();
|
|
public ObservableCollection<AlarmSetting> MarkSettings { get; private set; }
|
|
private string blockFilePath = PathHelper.BlockAlarmSettingPath();
|
private string markFilePath = PathHelper.MarkAlarmSettingPath();
|
|
/// <summary>
|
/// 接收报警的队列
|
/// </summary>
|
private MSMQHelper alarmQueue = new MSMQHelper("HMI_Alarm");
|
/// <summary>
|
/// 刷新报警的队列
|
/// </summary>
|
private MSMQHelper alarmRefershToMain = new MSMQHelper("LTHMI_Alarm_Rrfresh");
|
|
|
private PLCS7Driver pLCS7Driver;
|
|
private Timer plcTimer;
|
private Timer mqTimer;
|
|
/// <summary>
|
/// 报警信息缓存
|
/// </summary>
|
private List<AlarmText> currentPLCAlarmCache = new List<AlarmText>();
|
|
/// <summary>
|
/// 报警信息缓存
|
/// </summary>
|
private List<AlarmText> currentMQAlarmCache = new List<AlarmText>();
|
|
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();
|
}
|
|
/// <summary>
|
/// PLC报警读取
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void PLCTimer_Elapsed(object sender, ElapsedEventArgs e)
|
{
|
try
|
{
|
plcTimer.Enabled = false;
|
isHaveAlarm = false;
|
List<AlarmText> cache = new List<AlarmText>();
|
|
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 PLC Alarm Data Error.", ex);
|
}
|
finally
|
{
|
if (!isClosing) plcTimer.Enabled = true;
|
}
|
}
|
|
private void RefershAlarm()
|
{
|
alarmRefershToMain.Send("AlarmRefersh", string.Empty, string.Empty, 0);
|
List<AlarmText> alarms = new List<AlarmText>();
|
|
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 MQAlarm alarm);
|
if (MessageID != string.Empty && alarm != null)
|
{
|
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 source = string.IsNullOrEmpty(alarm.Source) ? "PC" : alarm.Source;
|
string info = alarm.Content;
|
|
AlarmText newAlarm = new AlarmText
|
{
|
Source = source,
|
VirtualId = $"{source}:{info}",
|
AlarmInfo = info,
|
Level = alarm.Level,
|
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
};
|
if (currentMQAlarmCache
|
.Find(a => a.Source == newAlarm.Source && a.AlarmInfo == newAlarm.AlarmInfo) == null)
|
{
|
currentMQAlarmCache.Add(newAlarm);
|
RefershAlarm();
|
}
|
break;
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
log.Error("Read MSMQ Alarm Data Failed", ex);
|
}
|
finally
|
{
|
if (!isClosing) mqTimer.Enabled = true;
|
}
|
}
|
|
public void RefreshBlockSettings()
|
{
|
BlockMap.Clear();
|
BlockReadCache.Clear();
|
try
|
{
|
BlockSettings = HMI.Core.Util.XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(blockFilePath);
|
}
|
catch (Exception ex)
|
{
|
//log.Error("LoadAlarmSetting Error.", ex);
|
BlockSettings = new ObservableCollection<AlarmSetting>();
|
}
|
|
foreach (var setting in BlockSettings)
|
{
|
string key = $"{setting.DBAddress}.{setting.StartAddress}";
|
if (!BlockMap.ContainsKey(key))
|
{
|
BlockMap[key] = new Dictionary<string, AlarmSetting>();
|
}
|
var codes = BlockMap[key];
|
codes[setting.AlarmCode] = setting;
|
}
|
}
|
|
public void RefreshMarkSettings()
|
{
|
try
|
{
|
MarkSettings = HMI.Core.Util.XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(markFilePath);
|
}
|
catch (Exception ex)
|
{
|
//log.Error("LoadAlarmSetting Error.", ex);
|
MarkSettings = new ObservableCollection<AlarmSetting>();
|
}
|
}
|
|
public void LoadAlarmSetting()
|
{
|
RefreshBlockSettings();
|
RefreshMarkSettings();
|
}
|
|
public void UpdateBlockSettings(IEnumerable<AlarmSetting> settings)
|
{
|
HMI.Core.Util.XmlHelper.SerializeToXml(blockFilePath, settings);
|
RefreshBlockSettings();
|
}
|
|
public void UpdateMarkSettings(IEnumerable<AlarmSetting> settings)
|
{
|
HMI.Core.Util.XmlHelper.SerializeToXml(markFilePath, settings);
|
RefreshMarkSettings();
|
}
|
}
|
|
public class AlarmUtil
|
{
|
static AlarmHelper Instance { get; set; }
|
public static event EventHandler<List<AlarmText>> OnAlarm;
|
|
public static event EventHandler<LoadMsg> LoadMessageAppend;
|
|
public static ObservableCollection<AlarmSetting> BlockSettings { get => Instance?.BlockSettings; }
|
public static ObservableCollection<AlarmSetting> MarkSettings { get => Instance?.MarkSettings; }
|
|
public static void Init()
|
{
|
AlarmHelper.log.Info("AlarmUtil initing...");
|
Instance = new AlarmHelper();
|
Instance.LoadMessageAppend += Instance_LoadMessageAppend; ;
|
Instance.InitInstance();
|
Instance.OnAlarm += Instance_OnAlarm;
|
AlarmHelper.log.Info("AlarmUtil inited finished.");
|
}
|
|
private static void Instance_LoadMessageAppend(object sender, LoadMsg e)
|
{
|
LoadMessageAppend?.Invoke(sender, e);
|
}
|
|
private static void Instance_OnAlarm(object sender, List<AlarmText> 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<AlarmSetting> settings)
|
{
|
Instance?.UpdateBlockSettings(settings);
|
}
|
|
public static void UpdateMarkSettings(IEnumerable<AlarmSetting> settings)
|
{
|
Instance?.UpdateBlockSettings(settings);
|
}
|
}
|
}
|