tbf/TBF/BenchControl/Various/ErrorFlags/Errors.cs

231 lines
9.7 KiB
C#

///
/// Copyright (c) 2017-2019 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using Config.Entities;
using Results.Entities;
using TBF.BenchControl.Sequences;
namespace TBF.BenchControl.Various.ErrorFlags
{
public class Errors : ComponentBase, GenericDevices.IErrorFlags
{
private static readonly ILog log = LogManager.GetLogger(typeof(Errors));
public override string ToString()
{
return string.Format("{0}({1})", this.GetType().Namespace.Substring(17), Cfg.ToString(1));
}
///
/// Cfg
///
readonly ErrorsCfg errorsCfg;
public Config.Entities.ErrorFlagsMode Mode { get { return errorsCfg.TestParams.Mode; } }
/// <summary>
/// Ger error flags for a test
/// </summary>
/// <param name="testRslt">A valid test result</param>
/// <param name="diverter">true = diverter was used (times apply)</param>
/// <param name="startStopValve">true = start/stop valve was used (times apply)</param>
/// <param name="switchTimeStart">Diverter or valve switch time in s on test start</param>
/// <param name="switchTimeEnd">Diverter or valve switch time in s on test end</param>
/// <returns>Error flags</returns>
public int GetErrorFlags(TestRslt testRslt, bool diverter, bool startStopValve, float switchTimeStart, float switchTimeEnd)
{
if (Mode == Config.Entities.ErrorFlagsMode.Off)
{
return 0; /// return 0 when Mode == ErrorFlagsMode.Off
}
/// Any E# is 'true' on error, 'false' when OK
/// Average flow
double aveFlow = 3.6 * testRslt.VolumeCTV / testRslt.TestTime;
bool E1 = (aveFlow < testRslt.Qfrom()) || (aveFlow > testRslt.Qto());
/// Max. and min. up and down water temperature
bool E2 = ProcessData.TempUpStat.Min < testRslt.TempLimLo()
|| ProcessData.TempUpStat.Max > testRslt.TempLimHi()
|| ProcessData.TempDownStat.Min < testRslt.TempLimLo()
|| ProcessData.TempDownStat.Max > testRslt.TempLimHi();
/// Max. flow deviation
bool E3 = ProcessData.RefFlowStat.Min < ProcessData.RefFlowStat.Average * (1.0f - errorsCfg.TestParams.Delta_Q_pct / 100.0f)
|| ProcessData.RefFlowStat.Max > ProcessData.RefFlowStat.Average * (1.0f + errorsCfg.TestParams.Delta_Q_pct / 100.0f);
/// Max. up and down water temperature deviation
bool E4 = ProcessData.TempUpStat.Min < ProcessData.TempUpStat.Average - errorsCfg.TestParams.Delta_T
|| ProcessData.TempUpStat.Max > ProcessData.TempUpStat.Average + errorsCfg.TestParams.Delta_T
|| ProcessData.TempDownStat.Min < ProcessData.TempDownStat.Average - errorsCfg.TestParams.Delta_T
|| ProcessData.TempDownStat.Max > ProcessData.TempDownStat.Average + errorsCfg.TestParams.Delta_T;
/// Max. absolute value of up and down water temperature difference
bool E5 = ProcessData.TempDiffStat.Max > errorsCfg.TestParams.Delta_Tup_Tdn;
bool E6 = false;
/// Test time (min)
bool E7 = testRslt.TestTime < errorsCfg.TestParams.TestTime_min;
/// Test time (max)
bool E8 = testRslt.TestTime > errorsCfg.TestParams.TestTime_max;
bool E9 = false;
bool E10 = false;
if (diverter)
{
E9 = (Math.Abs(switchTimeStart - switchTimeEnd) > errorsCfg.TestParams.Coef_E9 * (switchTimeStart + switchTimeEnd) + errorsCfg.TestParams.Offset_E9);
E10 = ((switchTimeStart + switchTimeEnd) > errorsCfg.TestParams.Coef_E10 * testRslt.TestTime);
}
bool E11 = false;
bool E12 = false;
if (startStopValve)
{
E11 = ((switchTimeStart + switchTimeEnd) > errorsCfg.TestParams.Coef_E11 * testRslt.TestTime);
E12 = (Math.Abs(switchTimeStart - switchTimeEnd) > errorsCfg.TestParams.Coef_E12 * (switchTimeStart + switchTimeEnd) + errorsCfg.TestParams.Offset_E12);
}
/// Ambient temperature
bool E13 = ProcessData.AmbTempStat.Min < errorsCfg.TestParams.AmbTemp_min
|| ProcessData.AmbTempStat.Max > errorsCfg.TestParams.AmbTemp_max;
/// Water pressure
bool E14 = ProcessData.PressUpStat.Min < errorsCfg.TestParams.Pressure_min
|| ProcessData.PressUpStat.Max > errorsCfg.TestParams.Pressure_max
|| ProcessData.PressDownStat.Min < errorsCfg.TestParams.Pressure_min
|| ProcessData.PressDownStat.Max > errorsCfg.TestParams.Pressure_max;
/// Max. and min. flow
bool E21 = ProcessData.RefFlowStat.Min < testRslt.Qfrom()
|| ProcessData.RefFlowStat.Max > testRslt.Qto();
int ErrorFlags = 0;
if (errorsCfg.TestParams.E1 && E1) ErrorFlags |= (int)ErrorFlagMask.E1;
if (errorsCfg.TestParams.E2 && E2) ErrorFlags |= (int)ErrorFlagMask.E2;
if (errorsCfg.TestParams.E3 && E3) ErrorFlags |= (int)ErrorFlagMask.E3;
if (errorsCfg.TestParams.E4 && E4) ErrorFlags |= (int)ErrorFlagMask.E4;
if (errorsCfg.TestParams.E5 && E5) ErrorFlags |= (int)ErrorFlagMask.E5;
if (errorsCfg.TestParams.E6 && E6) ErrorFlags |= (int)ErrorFlagMask.E6;
if (errorsCfg.TestParams.E7 && E7) ErrorFlags |= (int)ErrorFlagMask.E7;
if (errorsCfg.TestParams.E8 && E8) ErrorFlags |= (int)ErrorFlagMask.E8;
if (errorsCfg.TestParams.E9 && E9) ErrorFlags |= (int)ErrorFlagMask.E9;
if (errorsCfg.TestParams.E10 && E10) ErrorFlags |= (int)ErrorFlagMask.E10;
if (errorsCfg.TestParams.E11 && E11) ErrorFlags |= (int)ErrorFlagMask.E11;
if (errorsCfg.TestParams.E12 && E12) ErrorFlags |= (int)ErrorFlagMask.E12;
if (errorsCfg.TestParams.E13 && E13) ErrorFlags |= (int)ErrorFlagMask.E13;
if (errorsCfg.TestParams.E14 && E14) ErrorFlags |= (int)ErrorFlagMask.E14;
//E15
//E16
//E17
//E18
//E19
//E20
if (errorsCfg.TestParams.E21 && E21) ErrorFlags |= (int)ErrorFlagMask.E21;
return ErrorFlags;
}
MeterTestRslt GetMtrTstRsltFromNames(IList<MeterTestRslt> meterTestRslts, string testNames)
{
if (string.IsNullOrEmpty(testNames)) return null;
string[] names = testNames.Split(new char[] { ';' });
foreach (var nm in names)
{
foreach (var mtr in meterTestRslts) if (mtr.Name() == nm) return mtr;
}
return null; /// No matching MeterTestRslt found
}
/// <summary>
/// Get water meter error flags E15 and E16 (evaluated from three meter test results)
/// </summary>
/// <param name="meterTestRslts">Meter test results</param>
/// <returns>Error flags</returns>
public int GetWMtrErrorFlags(IList<MeterTestRslt> meterTestRslts)
{
int errorIndicators = 0;
MeterTestRslt mtrQ3 = GetMtrTstRsltFromNames(meterTestRslts, errorsCfg.Q3Names);
MeterTestRslt mtrQ2 = GetMtrTstRsltFromNames(meterTestRslts, errorsCfg.Q2Names);
MeterTestRslt mtrQ1 = GetMtrTstRsltFromNames(meterTestRslts, errorsCfg.Q1Names);
if (mtrQ3 == null || !mtrQ3.TestDone || mtrQ2 == null || !mtrQ2.TestDone || mtrQ1 == null || !mtrQ1.TestDone)
{
/// No error indicator;
}
else if ((mtrQ3.Error > mtrQ3.ErrLimHi() / 2) &&
(mtrQ2.Error > mtrQ2.ErrLimHi() / 2) &&
(mtrQ1.Error > mtrQ1.ErrLimHi() / 2))
{
errorIndicators |= (int)ErrorFlagMask.E15; /// Set E15
}
else if ((mtrQ3.Error < mtrQ3.ErrLimLo() / 2) &&
(mtrQ2.Error < mtrQ2.ErrLimLo() / 2) &&
(mtrQ1.Error < mtrQ1.ErrLimLo() / 2))
{
errorIndicators |= (int)ErrorFlagMask.E15; /// Set E15
}
foreach (var mtr in meterTestRslts)
{
errorIndicators |= mtr.ErrorIndicators; /// Set any error flag from mtr.ErrorIndicators (iPerl)
}
return errorIndicators;
}
public Errors()
{
}
public Errors(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
errorsCfg = cfg as ErrorsCfg;
StartChangeHandler();
log.Debug(this.ToString());
}
#region Configuration Change Handling
public static void OnCfgChange(object sender, CfgChangeArgs args)
{
if (CfgChangeHandler == null) return;
try { CfgChangeHandler(sender, args); }
catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); }
}
public static event EventHandler<CfgChangeArgs> CfgChangeHandler;
public override void StartChangeHandler()
{
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
{
ErrorsCfg tmpcfg = args.Cfg as ErrorsCfg;
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
{
if (args.Command == CfgChangeCmd.CfgChange)
{
errorsCfg.Q3Names = tmpcfg.Q3Names;
errorsCfg.Q2Names = tmpcfg.Q2Names;
errorsCfg.Q1Names = tmpcfg.Q1Names;
}
}
};
}
#endregion Configuration Change Handling
}
}