Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/Aitex/Core/RT/Event/EventManager.cs

560 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
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");
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
}
}