123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- 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;
- /// <summary>
- /// 存放实时数据的值,带入dataProvider中进行更新
- /// </summary>
- public string DataInfo
- {
- get { return dataInfo; }
- set { dataInfo = value; }
- }
- /// <summary>
- /// 规则解释类
- /// 在自动生成的规则解析代码中实现该方法
- /// </summary>
- /// <param name="objectId"></param>
- /// <param name="objectType"></param>
- /// <returns></returns>
- public abstract bool Interpret(string objectId, AlertObjectType objectType);
- #region 扩展方法
- /// <summary>
- /// 判定状态保持的方法
- /// 应用场景:读取实时库某一点的历史值,时间区间为:当前时间向前追溯{duration}分钟,
- /// 若时间段范围内无值或只有一个值,返回false
- /// 若时间段内有若干值(大于1)且都相同,则认为该状态一直持续未变
- /// </summary>
- /// <param name="testPointName">测点名称</param>
- /// <param name="duration">持续时间,单位:分钟</param>
- /// <param name="objectId">对象ID</param>
- /// <param name="objectType">对象类型</param>
- /// <returns>
- /// true:时间段内状态不变
- /// false:时间段内数据不足或者状态变动过
- /// </returns>
- 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<arr.Length;i++)
- {
- if (arr[i] != arr[0])
- return false;
- }
- return true;
- }
- return false;
- }
- /// <summary>
- /// 取测点与给定的时间之前的差值
- /// 算法:读取实时库某一点当前值及给定时间前的值,返回当前值与前值的差
- /// </summary>
- /// <param name="testPointName">测点名称</param>
- /// <param name="minutes">时间差, 单位: 分钟</param>
- /// <param name="objectId">对象ID</param>
- /// <param name="objectType">对象类型</param>
- /// <returns>
- /// 当前值 - 前值
- /// </returns>
- 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];
- }
- }
- /// <summary>
- /// 判定状态突然大幅变化的方法
- /// 算法:读取实时库某一点的历史值(2次),时间区间分别为
- /// a) Datetime.Now —— Datetime.Now - duration
- /// b)Datetime.Now - duration —— Datetime.Now - duration*2
- /// 分别计算出两个时间段的平均值和方差,
- /// 若均值的比率 或者方差的比率大于制定的值时,则认为是数据突变
- /// </summary>
- /// <param name="testPointName">测点名称</param>
- /// <param name="duration">持续时间,单位:分钟</param>
- /// <param name="objectId">对象ID</param>
- /// <param name="objectType">对象类型</param>
- /// <returns>
- /// true:时间段内状态不变
- /// false:时间段内数据不足或者状态变动过
- /// </returns>
- 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<arr1.Length;i++)
- {
- sum += arr1[i];
- }
- avg1 = sum / arr1.Length;
- sum = 0;
- for (int i = 0; i < arr1.Length; i++)
- {
- sum += Math.Pow(arr1[i] - avg1, 2);
- }
- fc1 = Math.Sqrt(sum/arr1.Length);
- }
- sum = 0;
- for (int i = 0; i < arr.Length; i++)
- {
- sum += arr[i];
- }
- avg2 = sum / arr.Length;
- double ratio2 = avg2 / avg1;
- if (ratio2 > 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;
- }
- /// <summary>
- /// 获取测点最近收到数据的时间
- /// 应用场景:读取实时库某一点的当前值(对应EDos的GetRtValue方法),返回改值对应的时间,
- /// </summary>
- /// <param name="testPointName">测点名称</param>
- /// <param name="objectId">对象ID</param>
- /// <param name="objectType">对象类型</param>
- /// <returns>
- /// 时间,单位为秒(近似值)
- /// </returns>
- 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
- }
- }
|