Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/Temps/TempDataFilter.cs

135 lines
3.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps;
public sealed class TempDataFilter
{
#region Variables
private int _wsMAF;
private readonly object _qLocker = new();
private readonly List<TempPoint> _lstTemps = new();
#endregion
#region Ctor
public TempDataFilter(ITempSensor owner, string channel, double minimalTemp = 600, string scBasePath = "TempSensors")
{
Debug.Assert(owner != null, "The parameter owner can not be null.");
Raw = minimalTemp;
FilteredMAF = minimalTemp;
FeedBack = minimalTemp;
Parent = owner;
Channel = channel;
var filterScMAF = $"{scBasePath}.Filters.MAF";
_wsMAF = SC.SafeGetValue($"{filterScMAF}.WindowSize", 1);
SC.RegisterValueChangedCallback($"{filterScMAF}.WindowSize", value =>
{
if (value is int ws)
_wsMAF = ws;
else
_wsMAF = 1;
});
}
#endregion
#region Properties
internal ITempSensor Parent { get; }
internal string Channel { get; }
/// <summary>
/// 返回测温原始温度值。
/// </summary>
internal double Raw { get; private set; }
/// <summary>
/// 返回滤波后的温度。
/// </summary>
internal double FilteredMAF { get; private set;}
/// <summary>
/// 返回PID使用的温度反馈值。
/// </summary>
public double FeedBack { get; private set;}
#endregion
#region Methods
/// <summary>
/// 添加一个新温度值。
/// </summary>
/// <param name="temp"></param>
public void AddRawTemp(double temp)
{
Raw = temp;
FilteredMAF = MoveAverageFilter(temp, _wsMAF);
}
/// <summary>
/// 更改MAF滤波窗口。
/// </summary>
/// <param name="ws"></param>
public void ChangeWindowSize(int ws)
{
_wsMAF = ws;
}
#region MAF
private readonly R_TRIG _rTrigMafFailed = new ();
private double MoveAverageFilter(double temp, int windowSize)
{
// make sure that minimal window size is 1.
if (windowSize < 0)
windowSize = 0;
try
{
if (windowSize <= 0)
return temp;
lock (_qLocker)
{
var tp = new TempPoint(temp);
var filterRange = tp.TimeStamp - TimeSpan.FromMilliseconds(windowSize).Ticks;
var filteredTemp = temp;
_lstTemps.Add(tp);
_lstTemps.RemoveAll(x => x.TimeStamp < filterRange);
var ave = _lstTemps.Average(x => x.Value);
if (!double.IsNaN(ave) && !double.IsInfinity(ave))
filteredTemp = ave;
_rTrigMafFailed.CLK = false;
return filteredTemp;
}
}
catch (Exception e)
{
_rTrigMafFailed.CLK = true;
if (_rTrigMafFailed.Q)
LOG.Error($"{Parent.Module}.{Parent.Name}.{Channel} Unable to perform MAF, {e.Message}.");
return temp;
}
}
#endregion
#endregion
}