563 lines
15 KiB
C#
563 lines
15 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.ServiceModel;
|
||
using Aitex.Core.Account;
|
||
using Aitex.Core.RT.DataCenter;
|
||
using Aitex.Core.RT.Log;
|
||
using Aitex.Core.RT.OperationCenter;
|
||
using Aitex.Core.Util;
|
||
using Aitex.Core.WCF;
|
||
using MECF.Framework.Common.Equipment;
|
||
using MECF.Framework.Common.Event;
|
||
using MECF.Framework.Common.FAServices;
|
||
|
||
namespace Aitex.Core.RT.Event
|
||
{
|
||
public class EventManager : ICommonEvent
|
||
{
|
||
#region Variable
|
||
|
||
private const string INFORMATION_EVENT = "INFORMATION_EVENT";
|
||
|
||
private const string WARNING_EVENT = "WARNING_EVENT";
|
||
|
||
private const string ALARM_EVENT = "ALARM_EVENT";
|
||
|
||
public event Action<EventItem> FireEvent;
|
||
|
||
public event Action<EventItem> OnAlarmEvent;
|
||
|
||
public event Action<EventItem> OnEvent;
|
||
|
||
private FixSizeQueue<EventItem> _eventQueue;
|
||
|
||
private FixSizeQueue<EventItem> _alarmQueue;
|
||
|
||
private PeriodicJob _eventJob;
|
||
|
||
private EventDBWriter _eventDb;
|
||
|
||
private EventLogWriter _writerToLog;
|
||
|
||
private EventMailWriter _writerToMail;
|
||
|
||
private EventService _eventService;
|
||
|
||
private ServiceHost _eventServiceHost;
|
||
|
||
/// <summary>
|
||
/// 系统支持的事件类型。
|
||
/// </summary>
|
||
private readonly Dictionary<string, EventItem> _dictEvTypeSource = new();
|
||
|
||
private List<AlarmEventItem> _alarms;
|
||
|
||
#endregion
|
||
|
||
#region Properties
|
||
|
||
public EventService Service => _eventService;
|
||
|
||
public List<VIDItem> VidEventList
|
||
{
|
||
get
|
||
{
|
||
var list = new List<VIDItem>();
|
||
foreach (var item in _dictEvTypeSource)
|
||
{
|
||
list.Add(new VIDItem
|
||
{
|
||
DataType = "",
|
||
Description = item.Value.Description,
|
||
Index = 0,
|
||
Name = item.Key,
|
||
Unit = ""
|
||
});
|
||
}
|
||
return list;
|
||
}
|
||
}
|
||
|
||
public List<VIDItem> VidAlarmList
|
||
{
|
||
get
|
||
{
|
||
var list = new List<VIDItem>();
|
||
foreach (var alarm in _alarms)
|
||
{
|
||
list.Add(new VIDItem
|
||
{
|
||
DataType = "",
|
||
Description = alarm.Description,
|
||
Index = 0,
|
||
Name = alarm.EventEnum,
|
||
Unit = ""
|
||
});
|
||
}
|
||
return list;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Methods
|
||
|
||
public void Initialize(string commonEventListXmlFile, bool needCreateService = true, bool needSaveDb = true, bool needMailOut = false, string localEventListXmlFile = null)
|
||
{
|
||
InitData();
|
||
InitOp();
|
||
|
||
if (needSaveDb)
|
||
{
|
||
_eventDb = new EventDBWriter();
|
||
try
|
||
{
|
||
_eventDb.Initialize();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LOG.Write(ex);
|
||
}
|
||
}
|
||
_writerToLog = new EventLogWriter();
|
||
if (needMailOut)
|
||
{
|
||
_writerToMail = new EventMailWriter();
|
||
}
|
||
_eventService = new EventService();
|
||
if (needCreateService)
|
||
{
|
||
try
|
||
{
|
||
_eventServiceHost = new ServiceHost(_eventService);
|
||
_eventServiceHost.Open();
|
||
}
|
||
catch (Exception ex2)
|
||
{
|
||
throw new ApplicationException("创建Event服务失败," + ex2.Message);
|
||
}
|
||
}
|
||
_eventQueue = new FixSizeQueue<EventItem>(1000);
|
||
_alarmQueue = new FixSizeQueue<EventItem>(1000);
|
||
_alarms = new List<AlarmEventItem>(1000);
|
||
_eventJob = new PeriodicJob(100, PeriodicRun, "EventPeriodicJob", isStartNow: true);
|
||
try
|
||
{
|
||
var eventDefine = CustomXmlSerializer.Deserialize<EventDefine>(new FileInfo(commonEventListXmlFile));
|
||
foreach (var item in eventDefine.Types)
|
||
{
|
||
_dictEvTypeSource[item.EventEnum] = item;
|
||
}
|
||
}
|
||
catch (ArgumentNullException)
|
||
{
|
||
throw new ApplicationException("初始化EventManager没有设置Event列表文件");
|
||
}
|
||
catch (FileNotFoundException ex4)
|
||
{
|
||
throw new ApplicationException("没有找到Event列表文件," + ex4.Message);
|
||
}
|
||
catch (Exception ex5)
|
||
{
|
||
throw new ApplicationException("EventDefine文件格式不对," + commonEventListXmlFile + ",\r\n" + ex5.Message);
|
||
}
|
||
try
|
||
{
|
||
if (!string.IsNullOrEmpty(localEventListXmlFile))
|
||
{
|
||
var eventDefine2 = CustomXmlSerializer.Deserialize<EventDefine>(new FileInfo(localEventListXmlFile));
|
||
foreach (var item2 in eventDefine2.Types)
|
||
{
|
||
_dictEvTypeSource[item2.EventEnum] = item2;
|
||
}
|
||
}
|
||
}
|
||
catch (ArgumentNullException)
|
||
{
|
||
throw new ApplicationException("初始化EventManager没有设置Event列表文件");
|
||
}
|
||
catch (FileNotFoundException ex)
|
||
{
|
||
throw new ApplicationException("没有找到Event列表文件," + ex.Message);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new ApplicationException("EventDefine文件格式不对," + localEventListXmlFile + ",\r\n" + ex.Message);
|
||
}
|
||
|
||
Subscribe(new EventItem(INFORMATION_EVENT, EventType.EventUI_Notify, EventLevel.Information));
|
||
Subscribe(new EventItem(WARNING_EVENT, EventType.EventUI_Notify, EventLevel.Warning));
|
||
Subscribe(new EventItem(ALARM_EVENT, EventType.EventUI_Notify, EventLevel.Alarm));
|
||
EV.InnerEventManager = this;
|
||
}
|
||
|
||
private void InitData()
|
||
{
|
||
DATA.Subscribe("System.LiveAlarmEvent", GetAlarmEvent);
|
||
|
||
DATA.Subscribe("System.ActiveAlarm", () => _alarmQueue.ToList().FindAll(x => !x.IsAcknowledged));
|
||
DATA.Subscribe("System.HasActiveAlarm", () => _alarmQueue.ToList().Any(x => !x.IsAcknowledged));
|
||
|
||
DATA.Subscribe("System.HasActiveAlarmEvent", () => _alarmQueue.ToList().Any(x => x.Level == EventLevel.Alarm && !x.IsAcknowledged));
|
||
DATA.Subscribe("System.HasAckedAlarmEvent", () => _alarmQueue.ToList().Any(x => x.Level == EventLevel.Alarm && x.IsAcknowledged));
|
||
DATA.Subscribe("System.HasActiveWarningEvent", () => _alarmQueue.ToList().Any(x => x.Level == EventLevel.Warning && !x.IsAcknowledged));
|
||
DATA.Subscribe("System.HasAckedWarningEvent", () => _alarmQueue.ToList().Any(x => x.Level == EventLevel.Warning && x.IsAcknowledged));
|
||
}
|
||
|
||
private void InitOp()
|
||
{
|
||
OP.Subscribe("System.AckAllAlarms", InvokeAckAllAlarms);
|
||
OP.Subscribe("System.ResetAlarm", InvokeResetAlarm);
|
||
|
||
#region 以下为用于测试Event的操作
|
||
|
||
OP.Subscribe("System.Diagnosis.GenWarningEvent", (s, args) =>
|
||
{
|
||
PostWarningLog(ModuleName.System.ToString(), args[0].ToString());
|
||
return true;
|
||
});
|
||
|
||
OP.Subscribe("System.Diagnosis.GenAlarmEvent", (s, args) =>
|
||
{
|
||
PostAlarmLog(ModuleName.System.ToString(), args[0].ToString());
|
||
return true;
|
||
});
|
||
|
||
OP.Subscribe("System.Diagnosis.GenPjDoneEvent", (s, args) =>
|
||
{
|
||
//WriteEvent(ModuleName.System.ToString(), "PJ_DONE", "LoadLock", "0");
|
||
//EV.PostMessage(ModuleName.System.ToString(), EventEnum.PJ_DONE, "LoadLock", "0");
|
||
OP.DoOperation("System.AlertJobDone", ModuleName.LoadLock, 0);
|
||
return true;
|
||
});
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 响应所有报警事件。
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private bool InvokeAckAllAlarms(string arg1, object[] arg2)
|
||
{
|
||
AckAlarmEvents();
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 复位指定的Alarm。
|
||
/// <remarks>
|
||
/// 请参考UI.Client库中的ModuleAlarmViewModel对象。
|
||
/// <br/>
|
||
/// 在此视图中,可以复位单条Alarm.
|
||
/// </remarks>
|
||
/// </summary>
|
||
/// <param name="arg1"></param>
|
||
/// <param name="arg2"></param>
|
||
/// <returns></returns>
|
||
private bool InvokeResetAlarm(string arg1, object[] arg2)
|
||
{
|
||
ClearAlarmEvent();
|
||
if (arg2 != null && arg2.Length >= 2)
|
||
{
|
||
_alarms.FirstOrDefault(x => x.Source == (string)arg2[0] && x.EventEnum == (string)arg2[1])?.Reset();
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 终止事件管理器。
|
||
/// </summary>
|
||
public void Terminate()
|
||
{
|
||
if (_eventJob != null)
|
||
{
|
||
_eventJob.Stop();
|
||
_eventJob = null;
|
||
}
|
||
if (_eventServiceHost != null)
|
||
{
|
||
_eventServiceHost.Close();
|
||
_eventServiceHost = null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建指定的事件并将其写入列队。
|
||
/// </summary>
|
||
/// <param name="eventName">事件名称。</param>
|
||
public void WriteEvent(string eventName)
|
||
{
|
||
if (!_dictEvTypeSource.ContainsKey(eventName))
|
||
{
|
||
LOG.Write("Event name not registered, " + eventName);
|
||
}
|
||
else
|
||
{
|
||
WriteEvent(_dictEvTypeSource[eventName].Source, eventName);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建指定的事件并将其写入列队。
|
||
/// </summary>
|
||
/// <param name="module">事件所属模组名称。</param>
|
||
/// <param name="eventName">事件名称。</param>
|
||
/// <param name="message">事件消息。</param>
|
||
public void WriteEvent(string module, string eventName, string message)
|
||
{
|
||
if (!_dictEvTypeSource.ContainsKey(eventName))
|
||
{
|
||
LOG.Write("Event name not registered, " + eventName);
|
||
return;
|
||
}
|
||
var eventItem = _dictEvTypeSource[eventName].Clone();
|
||
eventItem.Source = module;
|
||
eventItem.Description = message;
|
||
eventItem.OccuringTime = DateTime.Now;
|
||
_eventQueue.Enqueue(eventItem);
|
||
if (eventItem.Level == EventLevel.Alarm || eventItem.Level == EventLevel.Warning)
|
||
{
|
||
_alarmQueue.Enqueue(eventItem);
|
||
OnAlarmEvent?.Invoke(eventItem);
|
||
|
||
}
|
||
|
||
OnEvent?.Invoke(eventItem);
|
||
_writerToLog.WriteEvent(eventItem);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建指定的事件并将其写入列队。
|
||
/// </summary>
|
||
/// <param name="eventName">事件名称。</param>
|
||
/// <param name="dvid"></param>
|
||
public void WriteEvent(string eventName, SerializableDictionary<string, string> dvid)
|
||
{
|
||
if (!_dictEvTypeSource.ContainsKey(eventName))
|
||
{
|
||
LOG.Write("Event name not registered, " + eventName);
|
||
}
|
||
else
|
||
{
|
||
WriteEvent(_dictEvTypeSource[eventName].Source, eventName, dvid);
|
||
}
|
||
}
|
||
|
||
public void WriteEvent(string eventName, SerializableDictionary<string, object> dvid)
|
||
{
|
||
if (!_dictEvTypeSource.ContainsKey(eventName))
|
||
{
|
||
LOG.Error("Event name not registered, " + eventName);
|
||
return;
|
||
}
|
||
var eventItem = _dictEvTypeSource[eventName].Clone(dvid);
|
||
eventItem.OccuringTime = DateTime.Now;
|
||
ProceedReceivedEvent(eventItem);
|
||
}
|
||
|
||
public void WriteEvent(string module, string eventName, params object[] args)
|
||
{
|
||
var eventItem = _dictEvTypeSource[eventName].Clone();
|
||
eventItem.Source = module;
|
||
if (_dictEvTypeSource[eventName].Description == null)
|
||
{
|
||
return;
|
||
}
|
||
eventItem.Description = string.Format(_dictEvTypeSource[eventName].Description, args);
|
||
if (!string.IsNullOrEmpty(_dictEvTypeSource[eventName].GlobalDescription_en))
|
||
{
|
||
eventItem.GlobalDescription_en = string.Format(_dictEvTypeSource[eventName].GlobalDescription_en, args);
|
||
}
|
||
if (!string.IsNullOrEmpty(_dictEvTypeSource[eventName].GlobalDescription_zh))
|
||
{
|
||
eventItem.GlobalDescription_zh = string.Format(_dictEvTypeSource[eventName].GlobalDescription_zh, args);
|
||
}
|
||
eventItem.OccuringTime = DateTime.Now;
|
||
_eventQueue.Enqueue(eventItem);
|
||
if (eventItem.Level == EventLevel.Alarm || eventItem.Level == EventLevel.Warning)
|
||
{
|
||
_alarmQueue.Enqueue(eventItem);
|
||
OnAlarmEvent?.Invoke(eventItem);
|
||
}
|
||
|
||
OnEvent?.Invoke(eventItem);
|
||
_writerToLog.WriteEvent(eventItem);
|
||
}
|
||
|
||
public void WriteEvent(string module, string eventName, SerializableDictionary<string, string> dvid, params object[] args)
|
||
{
|
||
var eventItem = _dictEvTypeSource[eventName].Clone();
|
||
eventItem.Source = module;
|
||
eventItem.Description = string.Format(_dictEvTypeSource[eventName].Description, args);
|
||
if (!string.IsNullOrEmpty(_dictEvTypeSource[eventName].GlobalDescription_en))
|
||
{
|
||
eventItem.GlobalDescription_en = string.Format(_dictEvTypeSource[eventName].GlobalDescription_en, args);
|
||
}
|
||
if (!string.IsNullOrEmpty(_dictEvTypeSource[eventName].GlobalDescription_zh))
|
||
{
|
||
eventItem.GlobalDescription_zh = string.Format(_dictEvTypeSource[eventName].GlobalDescription_zh, args);
|
||
}
|
||
eventItem.OccuringTime = DateTime.Now;
|
||
eventItem.DVID = dvid;
|
||
_eventQueue.Enqueue(eventItem);
|
||
if (eventItem.Level == EventLevel.Alarm || eventItem.Level == EventLevel.Warning)
|
||
{
|
||
_alarmQueue.Enqueue(eventItem);
|
||
OnAlarmEvent?.Invoke(eventItem);
|
||
}
|
||
|
||
OnEvent?.Invoke(eventItem);
|
||
_writerToLog.WriteEvent(eventItem);
|
||
}
|
||
|
||
private void ProceedReceivedEvent(EventItem item)
|
||
{
|
||
_eventQueue.Enqueue(item);
|
||
if (item.Level == EventLevel.Alarm || item.Level == EventLevel.Warning)
|
||
{
|
||
_alarmQueue.Enqueue(item);
|
||
OnAlarmEvent?.Invoke(item);
|
||
}
|
||
|
||
OnEvent?.Invoke(item);
|
||
_writerToLog.WriteEvent(item);
|
||
}
|
||
|
||
public void PostNotificationMessage(string message)
|
||
{
|
||
var eventItem = new EventItem
|
||
{
|
||
Type = EventType.UIMessage_Notify,
|
||
Description = message,
|
||
OccuringTime = DateTime.Now
|
||
};
|
||
_eventQueue.Enqueue(eventItem);
|
||
_writerToLog.WriteEvent(eventItem);
|
||
}
|
||
|
||
public void PostPopDialogMessage(EventLevel level, string title, string message)
|
||
{
|
||
var eventItem = new EventItem
|
||
{
|
||
Type = EventType.Dialog_Nofity,
|
||
Description = title,
|
||
Explaination = message,
|
||
OccuringTime = DateTime.Now,
|
||
Level = level
|
||
};
|
||
_eventQueue.Enqueue(eventItem);
|
||
_writerToLog.WriteEvent(eventItem);
|
||
}
|
||
|
||
public void PostKickoutMessage(string message)
|
||
{
|
||
var eventItem = new EventItem
|
||
{
|
||
Type = EventType.KickOut_Notify,
|
||
Description = message,
|
||
OccuringTime = DateTime.Now
|
||
};
|
||
_eventQueue.Enqueue(eventItem);
|
||
_writerToLog.WriteEvent(eventItem);
|
||
}
|
||
|
||
public void PostSoundMessage(string message)
|
||
{
|
||
var eventItem = new EventItem
|
||
{
|
||
Type = EventType.Sound_Notify,
|
||
Description = message,
|
||
OccuringTime = DateTime.Now
|
||
};
|
||
_eventQueue.Enqueue(eventItem);
|
||
_writerToLog.WriteEvent(eventItem);
|
||
}
|
||
|
||
private bool PeriodicRun()
|
||
{
|
||
while (_eventQueue.TryDequeue(out var ev))
|
||
{
|
||
try
|
||
{
|
||
_eventDb?.WriteEvent(ev);
|
||
_writerToMail?.WriteEvent(ev);
|
||
_eventService?.FireEvent(ev);
|
||
FireEvent?.Invoke(ev);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LOG.Error("Failed to post event", ex);
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回当前报警事件列表。
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public List<EventItem> GetAlarmEvent()
|
||
{
|
||
return _alarmQueue.ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将当前事件管理器中的所有报警事件设置为已响应。
|
||
/// </summary>
|
||
public void AckAlarmEvents()
|
||
{
|
||
_alarmQueue.ToList().ForEach(x=>
|
||
{
|
||
x.IsAcknowledged = true;
|
||
x.AcknowledgedTime = DateTime.Now;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清楚当前报警事件列表。
|
||
/// </summary>
|
||
public void ClearAlarmEvent()
|
||
{
|
||
_alarmQueue.Clear();
|
||
}
|
||
|
||
public List<EventItem> QueryDBEvent(string sql)
|
||
{
|
||
return _eventDb.QueryDBEvent(sql);
|
||
}
|
||
|
||
public void Subscribe(EventItem item)
|
||
{
|
||
if (!_dictEvTypeSource.ContainsKey(item.EventEnum))
|
||
{
|
||
_dictEvTypeSource[item.EventEnum] = item;
|
||
if (item is AlarmEventItem eventItem)
|
||
{
|
||
_alarms.Add(eventItem);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void PostInfoLog(string module, string message)
|
||
{
|
||
WriteEvent(module, INFORMATION_EVENT, message);
|
||
}
|
||
|
||
public void PostWarningLog(string module, string message)
|
||
{
|
||
WriteEvent(module, WARNING_EVENT, message);
|
||
}
|
||
|
||
public void PostAlarmLog(string module, string message)
|
||
{
|
||
WriteEvent(module, ALARM_EVENT, message);
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|