using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using FLY.OBJComponents.Server; using FLY.OBJComponents.Common; using FLY.Thick.Blowing.IService; using FLY.Thick.Blowing.Common; using Misc; using FLY.Thick.Blowing.Server.Model; namespace FLY.Thick.Blowing.Server { public class ScanWarning : Misc.ISaveToXml, INotifyPropertyChanged, IScanWarningService { private WarningSystem mWarning; private IShareDbService shareDb; /// <summary> /// 使能 /// </summary> public bool Enable { get; set; } /// <summary> /// 自动目标值 /// </summary> public bool IsAutoTarget { get; set; } = true; /// <summary> /// 连续N个点,大于规格线(公差)才算报警 /// </summary> public int AlarmCnt_Tolerance { get; set; } = 10; public event ScanWarningCheckEventHandler ScanWarningCheck; enum CheckResult { Idle, ToleranceWarning, } /// <summary> /// 数据是环形的。 /// </summary> /// <param name="target"></param> /// <param name="tolerancePercent"></param> /// <param name="data"></param> /// <returns></returns> CheckResult Check(double target, double tolerancePercent, double[] data) { double avg = data.AverageNoNull(); if (double.IsNaN(avg)) return CheckResult.Idle; if (IsAutoTarget) target = avg; double tolerance = target * tolerancePercent; int cnt_tolerance = 0; int valid_index = -1;//第1个合格范围数据 for (int i = 0; i < data.Length; i++) { double d = data[i]; if (double.IsNaN(d)) continue; double delta = Math.Abs(d - target); if (delta > tolerance) { //触发 cnt_tolerance++; if (cnt_tolerance >= AlarmCnt_Tolerance) { //需要报警 return CheckResult.ToleranceWarning; } } else { cnt_tolerance = 0; if(valid_index==-1) valid_index = i; } } if (cnt_tolerance > 0) { for (int i = 0; i < valid_index; i++) { double d = data[i]; if (double.IsNaN(d)) continue; double delta = Math.Abs(d - target); if (delta > tolerance) { //触发 cnt_tolerance++; if (cnt_tolerance >= AlarmCnt_Tolerance) { //需要报警 return CheckResult.ToleranceWarning; } } } } return CheckResult.Idle; } public void Apply() { Save(); } public ScanWarning() { Load(); } public void Init(WarningSystem warning, IShareDbService shareDB) { mWarning = warning; shareDb = shareDB; shareDb.ScanDataAdded += MshareDB_ScanDataAdded; } private void MshareDB_ScanDataAdded(object sender, EventArgs _e) { var e = (ScanDataAddedEventArgs)_e; if (!Enable) return; shareDb.GetProfile((asyncContext, retData) => { Db_Profile dB_Profile = retData as Db_Profile; if (dB_Profile == null) return; GetFrameCB(dB_Profile, e.scandata); }, null); } void GetFrameCB(Db_Profile dB_Profile,Lc_ScanData lc_ScanData) { CheckResult result = Check(dB_Profile.Target, dB_Profile.TolerancePercent, lc_ScanData.Thicks); string accessory = ""; if (result != CheckResult.Idle) accessory = Newtonsoft.Json.JsonConvert.SerializeObject(lc_ScanData.ID); switch (result) { case CheckResult.ToleranceWarning: //报警 mWarning.Add( ERRNOs.SCAN_ERRNO_OVERTOL.Code, ERRNOs.SCAN_ERRNO_OVERTOL.Descrption, ERR_STATE.ON, accessory ); break; case CheckResult.Idle: { //报警解除 mWarning.Add( ERRNOs.SCAN_ERRNO_OVERTOL.Code, ERRNOs.SCAN_ERRNO_OVERTOL.Descrption, ERR_STATE.OFF); } break; } ScanWarningCheck?.Invoke(this, new ScanWarningCheckEventArgs() { isWarning = (result != CheckResult.Idle), profile = dB_Profile, scandata = lc_ScanData }); } public void Save() { Misc.SaveToXmlHepler.Save("scanwarning.xml", this); } public bool Load() { return Misc.SaveToXmlHepler.Load("scanwarning.xml", this); } #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion public string[] GetSavePropertyNames() { return new string[]{ "Enable","IsAutoTarget","AlarmCnt_Tolerance"}; } } public class ScanWarningCheckEventArgs { public bool isWarning; public Db_Profile profile; public Lc_ScanData scandata; } public delegate void ScanWarningCheckEventHandler(object sender, ScanWarningCheckEventArgs e); }