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);
}