using Aitex.Core.RT.DBCore; using Aitex.Core.RT.Event; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.DBCore; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; namespace MECF.Framework.Common.Aitex.Core.RT.EMS { /// /// 监控膜生长厚度,超出阈值后报警提示 /// [DataContract] public class PMThicknessMaintainer:IObserver { #region Variables protected DateTime _startDate = DateTime.Now; protected DateTime? _trigDate = null; protected double _value = 0; protected bool _isTimeOut = false; protected double _timeExceeded = 0; protected readonly R_TRIG _trigTimeOut = new(); protected double _threshold = 1000000; protected double _valueElapsed = 0; protected double _valueExceeded = 0; public Func GetProcessing; [DataMember] MaintainerItemCollection _itemcollection; [Subscription("UnMaintainedCount")] public int UnMaintainedCount => _itemcollection.UnMaintainCount; public delegate bool Save(); public event Save OnSave; [Subscription("ValueElapsed")] public double ValueElapsed => _valueElapsed; [DataMember] public string Name { get; set; } [DataMember] public string Module { get; set; } [DataMember] public int Index { get; set; } [DataMember] public string Description { get; set; } [DataMember] public bool Enable { get; set; } [DataMember] public TimeUnit TimeDisplayUnit { get; set; } #region OutputOnly [Subscription("IsTrigger")] public bool IsTrigger => _isTimeOut; [Subscription("StartDate")] public DateTime StartDate => _startDate; [Subscription("Value")] /// /// 厚度,单位mm /// public double Value => _value; /// /// 单位mm /// [Subscription("Threshold")] public double Threshold => _threshold; /// /// 触发日期 /// [Subscription("TrigDate")] public DateTime? TrigDate => _trigDate; /// /// 超出时间,单位TimeDisplayUnit /// [Subscription("TimeExceeded")] public double TimeExceeded => _timeExceeded; /// /// 超出阈值,mm /// [Subscription("ValueExceeded")] public double ValueExceeded => _valueExceeded; [Subscription("IsProcessing")] public bool IsProcessing => (GetProcessing == null) ? false : GetProcessing(); #endregion #endregion #region Constructors public PMThicknessMaintainer() { } public PMThicknessMaintainer(MaintainerItemCollection item, string name, string module, int index, string description, bool enabled, DateTime startdate, double threshold, TimeUnit timedisplayunit) { _itemcollection = item; Name = name; Module = module; Index = index; Description = description; Enable = enabled; TimeDisplayUnit = timedisplayunit; _threshold = threshold; _startDate = startdate; } #endregion #region Methods /// /// 检查膜厚度并做出动作 /// public void Monitor() { DateTime now = DateTime.Now; ////①确认未使能;没有维护项也不进行计算 if (!Enable || _itemcollection.Count == 0) { _isTimeOut = false; _timeExceeded = 0; _valueElapsed = 0; _value = 0; return; } UpdateValue(); _itemcollection.CheckAllItemMaintained(StartDate); if (UnMaintainedCount == 0) { Reset(); //所有项都维护,翻转沙漏 } _valueExceeded = _value - Threshold; if (_valueExceeded <= 0) { _valueExceeded = 0; } if (_valueExceeded > 0) { if (!_isTimeOut && !_trigDate.HasValue) { _trigDate = now; } _isTimeOut = true; if (UnMaintainedCount != 0) { if (TrigDate.HasValue) { _timeExceeded = DateTimeHelper.DateTimeSubtraction(TrigDate.Value, now, TimeDisplayUnit); } _valueElapsed = 0; } } else { _timeExceeded = 0; _valueElapsed = DateTimeHelper.SecondsTransform(Threshold - _value, TimeDisplayUnit); } _trigTimeOut.CLK = _isTimeOut; if (_trigTimeOut.Q) { bool iswarning = true; if (SC.ContainsItem("System.IgnoreMaintainTimeOutWarning")) { iswarning = !SC.GetValue("System.IgnoreMaintainTimeOutWarning"); } if (iswarning) EV.PostWarningLog("Maintainance", $"Plan {Name} reach the deadline, please check as soon as possible."); else EV.PostInfoLog("Maintainance", $"Plan {Name} reach the deadline, please check as soon as possible."); } } private void UpdateValue() { string sql = $"Select \"thickness\" from \"pm_thickness_data\" where \"startdate\"='{StartDate.ToString()}' and \"pm_name\"='{Module}';"; DataSet dataSet = DB.ExecuteDataSet(sql); if (dataSet != null && dataSet.Tables != null && dataSet.Tables.Count == 1) { if (dataSet.Tables[0].Rows.Count == 1) { _value = Convert.ToDouble(dataSet.Tables[0].Rows[0]["thickness"].ToString()); } else if (dataSet.Tables[0].Rows.Count == 0) { ThinknessDataRecorder.InsertPMThinkness(_startDate.ToString(), Module, 0); } } } /// /// 重新开始计时,未使能时或不满足条件无法复位 /// /// public bool Reset() { if (!CanReset()) { return false; } _isTimeOut = false; DateTime now = DateTime.Now; _startDate = now; _trigDate = null; OnSave?.Invoke(); _value = 0; ThinknessDataRecorder.InsertPMThinkness(_startDate.ToString(),Module,0); _timeExceeded = 0; _valueExceeded = 0; _valueElapsed = DateTimeHelper.SecondsTransform(Threshold, TimeDisplayUnit); _itemcollection.CheckAllItemMaintained(StartDate); return true; } /// /// 阈值设置 /// /// 必须大于0 /// public bool SetThreshold(double threshold) { if (threshold <= 0) { EV.PostWarningLog("Maintainance", $"threshold must be greater than zero"); return false; } _threshold = threshold; return true; } public bool SetStartDate(DateTime t) { _startDate = t; return true; } public bool CanReset() { return UnMaintainedCount == 0; } public bool SetMaintain(string parentname, string name, int itemid, DateTime date) { return _itemcollection.SetMaintain(parentname, name, itemid, date); } public Dictionary> GetAllMaintainerItemsDic() { return _itemcollection.GetAllItemsDic(); } public bool SetMaintainerItemEnable(string parentname, string name, int itemid, bool enable) { return _itemcollection.SetMaintainerItemEnable(parentname, name, itemid, enable); } public void AddMaintainerItem(string parentname, MaintainerItem item) { _itemcollection.AddMaintainerItem(parentname, item); } public void RemoveMaintainerItem(string parentname, string itemname, int id) { _itemcollection.RemoveMaintainerItem(parentname, itemname, id); } #endregion } }