/// /// Copyright (c) 2017 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Text; using log4net; 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; } } public int GetErrorFlags(TestRslt testRslt, bool getE9E10, bool getE11E12, int switchTimeStart, int switchTimeEnd) { if (Mode == Config.Entities.ErrorFlagsMode.Off) { return 0; /// return 0 when Mode == ErrorFlagsMode.Off } /// Any E# is 'true' on error, 'false' when OK /// Max. and min. flow bool E1 = ProcessData.RefFlowStat.Min < testRslt.Qfrom() || ProcessData.RefFlowStat.Max > 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 (getE9E10) { E9 = ((double)Math.Abs(switchTimeStart - switchTimeEnd) > errorsCfg.TestParams.Coef_E9 * (switchTimeStart + switchTimeEnd)); E10 = ((double)(switchTimeStart + switchTimeEnd) > errorsCfg.TestParams.Coef_E10 * 1000.0 * testRslt.TestTime); } bool E11 = false; bool E12 = false; if (getE11E12) { E11 = ((double)(switchTimeStart + switchTimeEnd) > errorsCfg.TestParams.Coef_E11 * 1000.0 * testRslt.TestTime); E12 = ((double)Math.Abs(switchTimeStart - switchTimeEnd) > errorsCfg.TestParams.Coef_E12 * (switchTimeStart + switchTimeEnd)); } /// 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; bool E15 = false; bool E16 = false; int ErrorFlags = 0; if (errorsCfg.TestParams.E1 && E1) ErrorFlags |= 0x0001; if (errorsCfg.TestParams.E2 && E2) ErrorFlags |= 0x0002; if (errorsCfg.TestParams.E3 && E3) ErrorFlags |= 0x0004; if (errorsCfg.TestParams.E4 && E4) ErrorFlags |= 0x0008; if (errorsCfg.TestParams.E5 && E5) ErrorFlags |= 0x0010; if (errorsCfg.TestParams.E6 && E6) ErrorFlags |= 0x0020; if (errorsCfg.TestParams.E7 && E7) ErrorFlags |= 0x0040; if (errorsCfg.TestParams.E8 && E8) ErrorFlags |= 0x0080; if (errorsCfg.TestParams.E9 && E9) ErrorFlags |= 0x0100; if (errorsCfg.TestParams.E10 && E10) ErrorFlags |= 0x0200; if (errorsCfg.TestParams.E11 && E11) ErrorFlags |= 0x0400; if (errorsCfg.TestParams.E12 && E12) ErrorFlags |= 0x0800; if (errorsCfg.TestParams.E13 && E13) ErrorFlags |= 0x1000; if (errorsCfg.TestParams.E14 && E14) ErrorFlags |= 0x2000; if (errorsCfg.TestParams.E15 && E15) ErrorFlags |= 0x4000; if (errorsCfg.TestParams.E16 && E16) ErrorFlags |= 0x8000; return ErrorFlags; } MeterTestRslt GetMtrTstRsltFromNames(IList 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 } /// /// Returns 'true' when all three test were found and all three are 'TestDone' /// /// /// mtrQ3 or null /// mtrQ2 or null /// mtrQ1 or null /// public bool GetSelectedMtrs(IList meterTestRslts, out MeterTestRslt mtrQ3, out MeterTestRslt mtrQ2, out MeterTestRslt mtrQ1) { mtrQ3 = GetMtrTstRsltFromNames(meterTestRslts, errorsCfg.Q3Names); mtrQ2 = GetMtrTstRsltFromNames(meterTestRslts, errorsCfg.Q2Names); mtrQ1 = GetMtrTstRsltFromNames(meterTestRslts, errorsCfg.Q1Names); return (mtrQ3 != null && mtrQ3.TestDone && mtrQ2 != null && mtrQ2.TestDone && mtrQ1 != null && mtrQ1.TestDone); } public int GetE15(MeterTestRslt mtrQ3, MeterTestRslt mtrQ2, MeterTestRslt mtrQ1) { if ((mtrQ3.Error > mtrQ3.ErrLimHi() / 2) && (mtrQ2.Error > mtrQ2.ErrLimHi() / 2) && (mtrQ1.Error > mtrQ1.ErrLimHi() / 2)) { return 0x4000; } else { return 0; } } public int GetE16(MeterTestRslt mtrQ3, MeterTestRslt mtrQ2, MeterTestRslt mtrQ1) { if ((mtrQ3.Error < mtrQ3.ErrLimLo() / 2) && (mtrQ2.Error < mtrQ2.ErrLimLo() / 2) && (mtrQ1.Error < mtrQ1.ErrLimLo() / 2)) { return 0x8000; } else { return 0; } } public int GetErrorFlags(IList meterTestRslts) { MeterTestRslt mtrQ3, mtrQ2, mtrQ1; int errorFlags = 0; if (GetSelectedMtrs(meterTestRslts, out mtrQ3, out mtrQ2, out mtrQ1)) { errorFlags |= GetE15(mtrQ3, mtrQ1, mtrQ1); errorFlags |= GetE16(mtrQ3, mtrQ1, mtrQ1); } return errorFlags; } public Errors() { } public Errors(Generic.IComponentCfg cfg, IList 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 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 } }