using GDNXFD.Data; using System; using System.Collections.Generic; namespace GDNXFD.Alert.Interpreter { public abstract class AlertRuleInterpreter { private AlertRule _alertRule; private string[] _windturbines; private string[] _stations; private string[] _projects; private string[] _lines; private string[] _electricals; protected IDataProvider dataProvider; public AlertRuleInterpreter(AlertRule ar) { _alertRule = ar; dataProvider = InterpreterFactory.Instance.DataProvider; } public string Category { get { return _alertRule.Category; } } public AlertRule AlertRule { get { return _alertRule; } } public string[] Windturbines { get { if (_windturbines == null && Category == "1" && !string.IsNullOrWhiteSpace(_alertRule.Windturbine)) { _windturbines = _alertRule.Windturbine.Split(','); } return _windturbines; } } public string[] Stations { get { if (_stations == null && Category == "2" && !string.IsNullOrWhiteSpace(_alertRule.Station)) { _stations = _alertRule.Station.Split(','); } return _stations; } } public string[] Projects { get { if (_projects == null && Category == "3" && !string.IsNullOrWhiteSpace(_alertRule.Project)) { _projects = _alertRule.Project.Split(','); } return _projects; } } public string[] Lines { get { if (_lines == null && Category == "4" && !string.IsNullOrWhiteSpace(_alertRule.Line)) { _lines = _alertRule.Line.Split(','); } return _lines; } } public string[] Electricals { get { if (_electricals == null && Category == "5" && !string.IsNullOrWhiteSpace(_alertRule.Station)) { _electricals = _alertRule.Station.Split(','); } return _electricals; } } protected string dataInfo; /// /// 存放实时数据的值,带入dataProvider中进行更新 /// public string DataInfo { get { return dataInfo; } set { dataInfo = value; } } /// /// 规则解释类 /// 在自动生成的规则解析代码中实现该方法 /// /// /// /// public abstract bool Interpret(string objectId, AlertObjectType objectType); #region 扩展方法 /// /// 判定状态保持的方法 /// 应用场景:读取实时库某一点的历史值,时间区间为:当前时间向前追溯{duration}分钟, /// 若时间段范围内无值或只有一个值,返回false /// 若时间段内有若干值(大于1)且都相同,则认为该状态一直持续未变 /// /// 测点名称 /// 持续时间,单位:分钟 /// 对象ID /// 对象类型 /// /// true:时间段内状态不变 /// false:时间段内数据不足或者状态变动过 /// protected bool StatusContinued(string testPointName, int duration, string objectId, AlertObjectType objectType) { testPointName = testPointName.TrimStart('S', 'T', 'R'); DateTime tEnd = DateTime.Now; DateTime tStart = tEnd.AddMinutes(0 - duration); double[] arr = dataProvider.FindHistoryRaw(testPointName, objectId, objectType, tStart, tEnd); if (arr != null && arr.Length >1) { for (int i=1;i /// 取测点与给定的时间之前的差值 /// 算法:读取实时库某一点当前值及给定时间前的值,返回当前值与前值的差 /// /// 测点名称 /// 时间差, 单位: 分钟 /// 对象ID /// 对象类型 /// /// 当前值 - 前值 /// protected double DiffMinutes(string testPointName, int minutes, string objectId, AlertObjectType objectType) { if (minutes <= 0) return 0; testPointName = testPointName.TrimStart('S', 'T', 'R'); DateTime tEnd = DateTime.Now; DateTime tStart = tEnd.AddMinutes(0 - minutes); double[] arr = dataProvider.FindAIHistorySnap(testPointName, objectId, objectType, tStart, tEnd, minutes*60); if (arr.Length != 2) return 0; else { return arr[1] - arr[0]; } } protected double DiffSeconds(string testPointName, int seconds, string objectId, AlertObjectType objectType) { if (seconds <= 0) return 0; testPointName = testPointName.TrimStart('S', 'T', 'R'); DateTime tEnd = DateTime.Now; DateTime tStart = tEnd.AddSeconds(0 - seconds); double[] arr = dataProvider.FindAIHistorySnap(testPointName, objectId, objectType, tStart, tEnd, seconds); if (arr.Length != 2) return 0; else { return arr[1] - arr[0]; } } /// /// 判定状态突然大幅变化的方法 /// 算法:读取实时库某一点的历史值(2次),时间区间分别为 /// a) Datetime.Now —— Datetime.Now - duration /// b)Datetime.Now - duration —— Datetime.Now - duration*2 /// 分别计算出两个时间段的平均值和方差, /// 若均值的比率 或者方差的比率大于制定的值时,则认为是数据突变 /// /// 测点名称 /// 持续时间,单位:分钟 /// 对象ID /// 对象类型 /// /// true:时间段内状态不变 /// false:时间段内数据不足或者状态变动过 /// protected bool SuddenChange(string testPointName, int duration, double ratio, string objectId, AlertObjectType objectType) { if (ratio <= 0) return false; double fc1, fc2, avg1, avg2, sum; testPointName = testPointName.TrimStart('S', 'T', 'R'); DateTime tEnd = DateTime.Now; DateTime tStart = tEnd.AddMinutes(0 - duration); DateTime tStart1 = tStart.AddMinutes(0 - duration); double[] arr = dataProvider.FindHistoryRaw(testPointName, objectId, objectType, tStart, tEnd); double[] arr1 = dataProvider.FindHistoryRaw(testPointName, objectId, objectType, tStart1, tStart); if (arr == null || arr.Length < 1) return false; if (arr1 == null || arr1.Length < 1) { fc1 = 0; avg1 = arr[0]; } else { sum = 0; for(int i=0;i ratio || ratio2 < 1 / ratio) return true; sum = 0; for (int i = 0; i < arr.Length; i++) { sum += Math.Pow(arr[i] - avg2, 2); } fc2 = Math.Sqrt(sum / arr.Length); if (fc1 == 0 && fc2 != 0) return true; if (fc1 == 0 && fc2 == 0) return false; ratio2 = fc2 / fc1; if (ratio2 > ratio || ratio2 < 1 / ratio) return true; return false; } /// /// 获取测点最近收到数据的时间 /// 应用场景:读取实时库某一点的当前值(对应EDos的GetRtValue方法),返回改值对应的时间, /// /// 测点名称 /// 对象ID /// 对象类型 /// /// 时间,单位为秒(近似值) /// protected int LastUpdateTime(string testPointName, string objectId, AlertObjectType objectType) { testPointName = testPointName.TrimStart('S', 'T', 'R'); int t1 = dataProvider.GetLastUpdateTime(testPointName, objectId, objectType, ref dataInfo); return CommonMethod.ConvertDateTimeInt(DateTime.Now) - t1; } #endregion } }