using AutoMapper; using FLY.OBJComponents.Server; using FLY.Thick.Base.Common; using FLY.Thick.Blowing.IService; using FLY.Thick.Blowing.Server.Model; using Misc; using Newtonsoft.Json; using System; using System.ComponentModel; using System.IO; namespace FLY.Thick.Blowing.Server { public class ScanWarning : INotifyPropertyChanged, IScanWarningService { private WarningSystem2 mWarning; private IShareDbService shareDb; /// /// 使能 /// public bool Enable { get; set; } /// /// 自动目标值 /// public bool IsAutoTarget { get; set; } = true; /// /// 连续N个点,大于规格线(公差)才算报警 /// public int AlarmCnt_Tolerance { get; set; } = 10; public event ScanWarningCheckEventHandler ScanWarningCheck; public enum CheckResult { Idle, ToleranceWarning, } /// /// 数据是环形的。 /// /// /// /// /// public 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(WarningSystem2 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(new { ScanDataID = lc_ScanData.ID }); switch (result) { case CheckResult.ToleranceWarning: //报警 mWarning.Update( ERRNOs.Instance.SCAN_ERRNO_OVERTOL.Code, ERRNOs.Instance.SCAN_ERRNO_OVERTOL.Descrption, accessory ); break; case CheckResult.Idle: { //报警解除 mWarning.Remove(ERRNOs.Instance.SCAN_ERRNO_OVERTOL.Code); } break; } ScanWarningCheck?.Invoke(this, new ScanWarningCheckEventArgs() { isWarning = (result != CheckResult.Idle), profile = dB_Profile, scandata = lc_ScanData }); } string file_path = "scanwarning.json"; public bool Load() { try { if (File.Exists(file_path)) { string json = File.ReadAllText(file_path); var jsonDb = JsonConvert.DeserializeObject(json); ScanWarningJsonDb.Mapper.Map(jsonDb, this); return true; } } catch { //异常,没有json 解码失败 } return false; } bool Save() { try { var jsonDb = ScanWarningJsonDb.Mapper.Map(this); string json = JsonConvert.SerializeObject(jsonDb, Formatting.Indented); File.WriteAllText(file_path, json); return true; } catch { //异常,没有json 编码失败 } return false; } #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion } public class ScanWarningJsonDb { public static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c => { c.CreateMap().ReverseMap(); })); public bool Enable; public bool IsAutoTarget; public int AlarmCnt_Tolerance; } public class ScanWarningCheckEventArgs { public bool isWarning; public Db_Profile profile; public Lc_ScanData scandata; } public delegate void ScanWarningCheckEventHandler(object sender, ScanWarningCheckEventArgs e); }