From 6cd0be4c1759a5014910db3af9f28f4cdfbf3fc9 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Mon, 16 Oct 2017 16:55:10 +0200 Subject: [PATCH] TestMethods.SensitivityTest added. --- Results/Entities/WaterMeter.cs | 2 +- Results/ItemID.cs | 17 +- Results/Properties/AssemblyInfo.cs | 4 +- Results/Resources/Strings.Designer.cs | 9 + Results/Resources/Strings.resx | 3 + Results/WMeterRsltItemSpec.cs | 1 + .../BenchControl/TbfComponents.cs | 1 + .../SensitivityTest/SensitivityTestParams.cs | 143 ++++ .../SensitivityTest/SensitivityTestSeq.cs | 608 ++++++++++++++++++ .../TestMethods/SensitivityTest/TestMethod.cs | 37 ++ .../SensitivityTest/TestMethodCfg.cs | 50 ++ .../SensitivityTest/TestMethodCfgCtrl.cs | 71 ++ .../TestMethodCfgCtrl.designer.cs | 86 +++ .../SensitivityTest/TestMethodCfgCtrl.resx | 120 ++++ .../SensitivityTest/TestMethodFactory.cs | 26 + TestBenchFramework/TBF.csproj | 14 + 16 files changed, 1181 insertions(+), 11 deletions(-) create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestParams.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestSeq.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethod.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfg.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodFactory.cs diff --git a/Results/Entities/WaterMeter.cs b/Results/Entities/WaterMeter.cs index 9504b4087..7adc50da1 100644 --- a/Results/Entities/WaterMeter.cs +++ b/Results/Entities/WaterMeter.cs @@ -48,7 +48,7 @@ namespace Results.Entities public virtual int WMPosition { get; set; } public virtual string EndState { get; set; } /// End state (of the main water meter) public virtual string EndStateAux { get; set; } /// End state of the auxiliary water meter - public virtual double QRise { get; set; } /// [m3/h] detected Q_rise of a composed meter + public virtual double QRise { get; set; } /// [m3/h] detected Q_rise of a composed meter or 'sensitivity' of a single meter public virtual double QFall { get; set; } /// [m3/h] detected Q_fall of a composed meter public virtual int ErrorFlags { get; set; } /// bitfield : bit14=E15, bit15=E16 public virtual bool Passed { get; set; } diff --git a/Results/ItemID.cs b/Results/ItemID.cs index d2fa62ab0..4bad864c1 100644 --- a/Results/ItemID.cs +++ b/Results/ItemID.cs @@ -83,14 +83,14 @@ namespace Results Lite_per_pulse_Read, /// 73 Result_code, /// 74 Remark, /// 75 - T_Hi_mean, /// 76 - T_Hi_start, /// 77 - T_Hi_end, /// 78 - T_Hi_avg, /// 79 - T_Lo_mean, /// 80 - T_Lo_start, /// 81 - T_Lo_end, /// 82 - T_Lo_avg, /// 83 + T_Hi_mean, /// 76 + T_Hi_start, /// 77 + T_Hi_end, /// 78 + T_Hi_avg, /// 79 + T_Lo_mean, /// 80 + T_Lo_start, /// 81 + T_Lo_end, /// 82 + T_Lo_avg, /// 83 P_delta_mean, /// 84 P_delta_start, /// 85 P_delta_end, /// 86 @@ -180,6 +180,7 @@ namespace Results Diverter_start_time, /// 159 Diverter_end_time, /// 160 + Q_sensitivity, /// 161 Count, } diff --git a/Results/Properties/AssemblyInfo.cs b/Results/Properties/AssemblyInfo.cs index a77f14d44..19e78983c 100644 --- a/Results/Properties/AssemblyInfo.cs +++ b/Results/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.17.695.0")] -[assembly: AssemblyFileVersion("2.17.695.0")] +[assembly: AssemblyVersion("2.17.700.0")] +[assembly: AssemblyFileVersion("2.17.700.0")] diff --git a/Results/Resources/Strings.Designer.cs b/Results/Resources/Strings.Designer.cs index d12c2bc19..9157464dd 100644 --- a/Results/Resources/Strings.Designer.cs +++ b/Results/Resources/Strings.Designer.cs @@ -798,6 +798,15 @@ namespace Results.Resources { } } + /// + /// Looks up a localized string similar to sensitivity. + /// + internal static string sensitivity { + get { + return ResourceManager.GetString("sensitivity", resourceCulture); + } + } + /// /// Looks up a localized string similar to Single. /// diff --git a/Results/Resources/Strings.resx b/Results/Resources/Strings.resx index 39179f6a7..48935a081 100644 --- a/Results/Resources/Strings.resx +++ b/Results/Resources/Strings.resx @@ -642,4 +642,7 @@ Passed meters count + + sensitivity + \ No newline at end of file diff --git a/Results/WMeterRsltItemSpec.cs b/Results/WMeterRsltItemSpec.cs index 2eee47ebd..3b1895432 100644 --- a/Results/WMeterRsltItemSpec.cs +++ b/Results/WMeterRsltItemSpec.cs @@ -184,6 +184,7 @@ namespace Results AllItems.Add(new WMeterRsltItemSpec(ItemID.Q_ref_mean, string.Format("{0} rim ()", Strings.VName_Flow), Strings.Tooltip_Q_rim, Quantity.Flow, ItemCategory.TestResult, (w, t, u, f, p) => (w.GetTestRslt(t) == null) ? "" : DblFormat(u, f, p, "V3", w.GetTestRslt(t).FlowMean))); AllItems.Add(new WMeterRsltItemSpec(ItemID.Q_rise, string.Format("{0} {1}", Strings.VName_Flow, Strings.rise), Quantity.Flow, ItemCategory.MeterResult, (w, t, u, f, p) => (string.IsNullOrEmpty(t) || (w.GetTestRslt(t) != null)) ? ((w.QRise == 0) ? "-" : DblFormat(u, f, p, "V3", w.QRise)) : "")); AllItems.Add(new WMeterRsltItemSpec(ItemID.Q_fall, string.Format("{0} {1}", Strings.VName_Flow, Strings.fall), Quantity.Flow, ItemCategory.MeterResult, (w, t, u, f, p) => (string.IsNullOrEmpty(t) || (w.GetTestRslt(t) != null)) ? ((w.QFall == 0) ? "-" : DblFormat(u, f, p, "V3", w.QFall)) : "")); + AllItems.Add(new WMeterRsltItemSpec(ItemID.Q_sensitivity, string.Format("{0} {1}", Strings.VName_Flow, Strings.sensitivity), Quantity.Flow, ItemCategory.MeterResult, (w, t, u, f, p) => (string.IsNullOrEmpty(t) || (w.GetTestRslt(t) != null)) ? ((w.QRise == 0) ? "-" : DblFormat(u, f, p, "V3", w.QRise)) : "")); /// /// Temperature diff --git a/TestBenchFramework/BenchControl/TbfComponents.cs b/TestBenchFramework/BenchControl/TbfComponents.cs index 710c3bb7e..e7ce5b63e 100644 --- a/TestBenchFramework/BenchControl/TbfComponents.cs +++ b/TestBenchFramework/BenchControl/TbfComponents.cs @@ -61,6 +61,7 @@ namespace TBF.BenchControl Factories.Add(new TestMethods.OuterLoop.Start.Factory()); Factories.Add(new TestMethods.OuterLoop.End.Factory()); Factories.Add(new TestMethods.PMaxTest.TestMethodFactory()); + Factories.Add(new TestMethods.SensitivityTest.TestMethodFactory()); Factories.Add(new TestMethods.iPerlCommunication.TestMethodFactory()); /// iPerlCommunication Factories.Add(new TestMethods.RoiDetection.RoiDetectionFactory()); Factories.Add(new TestMethods.ReferenceFlowmeterCalibration.TestMethodFactory()); diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestParams.cs b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestParams.cs new file mode 100644 index 000000000..dce1f0337 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestParams.cs @@ -0,0 +1,143 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.IO; +using System.Text; +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.TestMethods.SensitivityTest +{ + public class SensitivityTestParams : TestParamsBase, IParamsProvider, ITestParams + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(SensitivityTestParams) })[0]; + protected override XmlSerializer GetSerializer() { return Serializer; } + + public float TargetQ; /// Target=terminal flow durning detection when increasing or decreasing the flow + public float RateOfChange; /// Each step is calculated as (TargetQfrom - Qfrom) * RateOfChange, text form is displayed in % (*100) + public float DetectionThreshold; /// Drop of frequency for the detection, text form is displayed in % (*100) + public bool SupressTrills; /// Main meter readings are ignored during test (suitable for small flows) + + public override void InitializeAll() + { + TargetQ = 3.0f; + RateOfChange = 0.05f; + DetectionThreshold = 0.25f; + SupressTrills = false; + } + + + string[] paramNames = new string[] + { + Strings.TargetQ, + Strings.RateOfChangePct, + Strings.DetectionThresholdPct, + Strings.SupressWMTrills, + }; + public override string ParamName(int i) { return paramNames[i]; } + public override int ParamsCount() { return paramNames.Length; } + + public override string ToString(int i) + { + switch (i) + { + case 0: return TargetQ.ToString(); + case 1: return (100.0f * RateOfChange).ToString(); + case 2: return (100.0f * DetectionThreshold).ToString(); + case 3: return (SupressTrills ? Strings.yes : Strings.no); + default: return string.Empty; + } + } + + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: TargetQ = Utils.ParseUFloat(strValue); return; + case 1: RateOfChange = Utils.ParseUFloat(strValue) / 100.0f; return; + case 2: DetectionThreshold = Utils.ParseUFloat(strValue) / 100.0f; return; + case 3: SupressTrills = strValue.Equals(Strings.yes); return; + default: return; + } + } + + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + float dummy; + switch (i) + { + case 0: + case 1: + case 2: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; + break; + case 3: + if (strValue.Equals(Strings.yes) || strValue.Equals(Strings.no)) return true; + break; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + void CopyContentTo(SensitivityTestParams prms) + { + prms.TargetQ = this.TargetQ; + prms.RateOfChange = this.RateOfChange; + prms.DetectionThreshold = this.DetectionThreshold; + prms.SupressTrills = this.SupressTrills; + } + + public IParamsProvider Clone() + { + SensitivityTestParams pars = new SensitivityTestParams(); + CopyContentTo(pars); + return pars; + } + + public override void UpdateTestParams(ComponentTest dbEntity) + { + if (dbEntity == null) return; + try + { + SensitivityTestParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as SensitivityTestParams; + + testParamsEntity = dbEntity; + componentName = dbEntity.CmpntName; + test = dbEntity.Test; + + if (tmp != null) tmp.CopyContentTo(this); + } + catch + { + } + } + + /// + /// Parameterless constructor initializes the parameters + /// + public SensitivityTestParams() + { + } + + public SensitivityTestParams(bool initialize) + { + if (initialize) InitializeAll(); + } + + public SensitivityTestParams(ComponentTest testParamsEntity, string componentName, Test test) + { + this.testParamsEntity = testParamsEntity; + this.componentName = componentName; + this.test = test; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestSeq.cs b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestSeq.cs new file mode 100644 index 000000000..1fa9ba4f2 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/SensitivityTestSeq.cs @@ -0,0 +1,608 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using TBF.BenchControl; +using TBF.Resources; +using TBF.UiBridge; + +namespace TBF.BenchControl.TestMethods.SensitivityTest +{ + public class SensitivityTestSeq : Sequences.SequenceBase + { + private static readonly ILog log = LogManager.GetLogger(typeof(SensitivityTestSeq)); + + const int DetectionBufferSize = 9; + const int DetectionKernelSize = 5; + + public IList Execute(Config.Entities.Test test, bool outerLoopMode, int outerLoopCounter, + SensitivityTestParams testParams, + Config.Entities.DebugMode debugLevel) + { + IList e = new List(); /// Events from currently running operations + checkUiOp = new Operations.CheckUIOp(true); /// Runs in more then one state + + float switchTimeStart = 0.001f; /// in seconds, original vale is 1 ms + float switchTimeEnd = 0.001f; /// in seconds, original vale is 1 ms + + if (test.Part < 1 || test.Part > Config.Data.CompoundWMsCount) + { + UiBridge.Bridge.OnError(this, string.Format("Test 'Part' should be 1 .. {0}", Config.Data.CompoundWMsCount)); + IList retval = new List(1); + retval.Add(Event.ConfigurationError); + return retval; + } + + if (debugLevel == Config.Entities.DebugMode.Simulate) + { + /// + /// Test method simulation + /// + TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 }); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Config.Entities.Progress.JustStarted)); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Config.Entities.Progress.FlowSetting)); + + if (test.Name.ToLower().Contains("rise") || test.Name.ToLower().Contains("steig")) + { + MakeSimulatedCompound(test.Name, 1, 1, 0, 0.7f, 0.0f); + } + else + { + MakeSimulatedCompound(test.Name, 1, 1, 0, 0.7f, 0.9f); + } + + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Config.Entities.Progress.Completed)); + Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, BatchRslts.GetTestRslt(Results.Utils.GetTestName(test.Name, 1, 1), 0))); + allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file + + for (int i = 0; i < Config.Data.WMsCount; i++) + { + TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = ((sensPath.RegisterReaders != null) && (i < sensPath.RegisterReaders.Length)) + ? (sensPath.RegisterReaders[i] as TestMethods.iPerlCommunication.iPerlHead.IperlHead) + : null; + if (iPerl != null) + { + /// TODO: Reimplement + //iPerl.LastTestResult = meterRslt; /// Save this water meter test result to iPerl WM + iPerl.NominalTestFlowLph = 500.0 * (double)(test.Qfrom + test.Qto); /// Ave. + convert to liter/hour + } + } + + //------------------------------------------------ + Bridge.OnActivity(this, string.Format("Simulating {0}", test.Name)); + //------------------------------------------------ + + State.Create(string.Format("{0}({1}) : Simulating", test.Method, test.Name)) + .AddOperation(checkUiOp) + .EnterState(); + e = StateMachine.WaitRunDevsRunOps(); + + Event retVal = Event.Done; + if (TestAndLogUiCmdStop(test, e)) retVal = Event.UiCmdStop; + + /// Create a list with one item 'retVal' (default is Event.Done) and return it + IList retListSim = new List(1); + retListSim.Add(retVal); + return retListSim; + } + + + Elde.ControlBoardDev cBrd = StateMachine.ControlBoard; + + /// Specific for combined meters + int[] lastWMPulses = new int[2 * Config.Data.CompoundWMsCount]; + + //-------------------------------- + State.Create(string.Format("{0}({1}) : stopTest diverter gate etc", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (TestAndLogUiCmdStop(test,e)) goto stopTest; + } + while (!e.Contains(Event.PreviousStopped)); + + + LtrPerRefPulse = outPath.FlowMeter.LtrPerPulse; /// [ltr/pulse], nominal flow in [m3/h] + + /// Notes: + /// float timeHr = volumeLtr / (1000.0f * targetFlow); + /// float timeSec = 3600.0f * timeHr; + /// int refPulses = (int)(timeSec * (2000.0f * targetFlow / pOut.FlowMeter.NominalFlow)); + int totalPulses = (int)(test.Volume / LtrPerRefPulse + 0.5f); + + processDataLoggingOp = new TBF.BenchControl.Operations.ProcessDataLoggingOp(processDataLogger, this, false); + + /// Meters path is required for the following: + readRegistersOp = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders); + + int repetitionNr = outerLoopMode ? outerLoopCounter : 1; /// First test: repetitionNr=1 + + //==================================== + // Transition or SetRoute - Start + //==================================== + switch (Transition(transitionBefore, TransitionContext.BeforeTest)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stopTest; + } + + //==================================== + loop: + /// Start the test, initialize test results + Bridge.OnTestSelected(this, new TestSelectedEventArgs(test, repetitionNr, inPath, benchPath, outPath, sensPath, (int)totalPulses)); + string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr); + TestStartTime = DateTime.Now; + TestProgressEventArgs.SetEstimatedTimes(new int[] { 1, 1, 120, 30, 0, Convert.ToInt32(test.TstTime) + 15, 0, 0 }); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.JustStarted)); + + Qrise = 0; + + if (!test.DoDraining) /// Do not skip emptying if test.Emptying==true + { + //-------------------------------- + State.Create(string.Format("{0}({1}) : Mesuring mass of water in the tank", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperation(outPath.Scale.ReadMassOp(ref Mass)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (TestAndLogUiCmdStop(test,e)) goto stopTest; + } + while (!e.Contains(Event.BalanceDone)); + + double estimatedEndMass = Mass.Val + test.Volume; + if (estimatedEndMass < outPath.Scale.Capacity * Constants.TankFullFactor) + { + goto switching_flow_detection; /// Enough room in the tank -> skip emptying + } + } + + // Empty the water tank + switch (DrainTheTank(outPath.Scale.DrainValve, outPath.Scale)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stopTest; + } + + switching_flow_detection: + + int flowDetectTime0 = StateMachine.Time; + int flowDetectTime = 0; + float estFlowSetTime = 100.0f; + + + /// + /// Prepare cameras, ROI-s and measurementOperations + /// + + /// Find ROI-s + IList rois = new List(); + foreach (var rr in sensPath.RegisterReaders) + { + GenericDevices.IRoi roi = rr as GenericDevices.IRoi; + if (roi != null && roi.Detected) + { + rois.Add(roi); + } + } + + /// Find cameras + IList cameras = new List(); + foreach (var roi in rois) + { + if (roi.Camera != null && !cameras.Contains(roi.Camera)) + { + roi.Camera.ClearRoiParams(); + cameras.Add(roi.Camera); + } + } + + /// Register ROI-parameters to cameras + foreach (var roi in rois) roi.RegisterRoiToCamera(); + + /// Prepare measurementOperations + IList measureOperations = new List(); + foreach (var camera in cameras) measureOperations.Add(camera.MeasurementOp()); + + + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Switching_flow_detection); + //------------------------------------------------ + State.Create(string.Format("{0}({1}) : Starting the pump", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation((inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOnOp(test.PumpPower) : null) + .AddOperation(cBrd.SetValvesOp(inPath.Pump, null)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.SwitchingFlowDetection)); + + if (TestAndLogUiCmdStop(test,e)) goto stopTest; + } + while (!e.Contains(Event.ValvesSet)); + + //-------------------------------- + State.Create(string.Format("{0}({1}) : Setting the initial flow", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.RegulValve.SetFlowAndMeasureOp(outPath.FlowMeter, test.Qfrom, test.Qto, outPath.PidCoef, RefFlow, 600, (float)test.TolerRed)) /// timeout = 10 min. + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.SwitchingFlowDetection)); + + if (TestAndLogUiCmdStop(test,e)) goto stopTest; + if (e.Contains(Event.RegulValveTimeOut)) + { + Bridge.OnError(this, Strings.Timeout); + goto error; + } + } + while (!e.Contains(Event.FlowReached)); + + //-------------------------------- + switch (ReadRegistersTempPressAmbient(measureOperations, false)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stopTest; + } + + //==================================== + // Find the switching flow + //==================================== + + int flowSetTime0 = StateMachine.Time; + + /// Allocate detection buffers + double[] flowsForDetection = new double[DetectionBufferSize]; + double[] pulseFreqsForDetection = new double[DetectionBufferSize]; + + /// Current values + flowsForDetection[0] = RefFlow.Val; + pulseFreqsForDetection[0] = 0.0f; + int startTime = StateMachine.Time; + int lastTime = StateMachine.Time; + + /// Detection parameters + float rvPulse = (testParams.TargetQ > (test.Qfrom + test.Qto) / 2.0f) ? 0.05f : -0.05f; // rise or fall? + rvPulse *= (100.0f * testParams.RateOfChange); + + bool detected = false; + bool targetReached = false; + double detectedFlow = 0; + + int detectionStartTime = StateMachine.Time; + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.SwitchingFlowDetection)); + + do + { + //-------------------------------- + State.Create(string.Format("{0}({1}) : Changing the RV position", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.RegulValve.ChangeRegulValvePositionOp(rvPulse)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.SwitchingFlowDetection)); + + if (TestAndLogUiCmdStop(test,e)) goto stopTest; + } + while (!e.Contains(Event.PositionReached)); + + // Last pulses are kept to calculate differences + for (int i = 0; i < 2 * Config.Data.CompoundWMsCount; i++) lastWMPulses[i] = RegisterReaders[i].WMPulses; + + // Shift data in the detection buffers + for (int i = DetectionBufferSize - 2; i >= 0; i--) + { + flowsForDetection[i+1] = flowsForDetection[i]; + pulseFreqsForDetection[i+1] = pulseFreqsForDetection[i]; + } + + switch (ReadRegistersTempPressAmbient(measureOperations, false)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stopTest; + } + + int time = StateMachine.Time; + int diff = RegisterReaders[(test.Part - 1) * 2 + 1].WMPulses - lastWMPulses[(test.Part - 1) * 2 + 1]; + flowsForDetection[0] = cBrd.ReferenceFreq * outPath.FlowMeter.NominalFlow / 2000.0f; + pulseFreqsForDetection[0] = (float)diff / (float)(time - lastTime); + lastTime = StateMachine.Time; + + if (StateMachine.Time - detectionStartTime > 15) + { + if ((flowsForDetection[0] > 0) && (flowsForDetection[DetectionBufferSize - 1] > 0)) + { + double[] flowBefore = new double[DetectionKernelSize]; + double[] flowAfter = new double[DetectionKernelSize]; + double[] freqBefore = new double[DetectionKernelSize]; + double[] freqAfter = new double[DetectionKernelSize]; + for (int i = 0; i < DetectionKernelSize; i++) + { + flowBefore[i] = flowsForDetection[DetectionBufferSize - DetectionKernelSize + i]; + freqBefore[i] = pulseFreqsForDetection[DetectionBufferSize - DetectionKernelSize + i]; + flowAfter[i] = flowsForDetection[i]; + freqAfter[i] = pulseFreqsForDetection[i]; + } + Array.Sort(flowBefore); + Array.Sort(flowAfter); + Array.Sort(freqBefore); + Array.Sort(freqAfter); + flowBefore[0] = 0; + flowAfter[0] = 0; + //freqBefore[0] = 0; + //freqAfter[0] = 0; + flowBefore[DetectionKernelSize - 1] = 0; + flowAfter[DetectionKernelSize - 1] = 0; + //freqBefore[DetectionKernelSize - 1] = 0; + //freqAfter[DetectionKernelSize - 1] = 0; + double aveFlowBefore = 0; + double aveFlowAfter = 0; + double aveFreqBefore = 0; + double aveFreqAfter = 0; + foreach (var f in flowBefore) aveFlowBefore += f; + foreach (var f in flowAfter) aveFlowAfter += f; + foreach (var f in freqBefore) aveFreqBefore += f; + foreach (var f in freqAfter) aveFreqAfter += f; + aveFlowBefore /= (double)(DetectionKernelSize - 2); + aveFlowAfter /= (double)(DetectionKernelSize - 2); + aveFreqBefore /= (double)(DetectionKernelSize); + aveFreqAfter /= (double)(DetectionKernelSize); + + UiBridge.Bridge.OnLog(this, string.Format("time={0}, flow{1}, aveFlowB={2}, aveFlowA={3}, pulseFreq={4}, aveFreqB={5}, aveFreqA={6}\r\n", + time - startTime, + flowsForDetection[0].ToString("F2"), + aveFlowBefore.ToString("F2"), + aveFlowAfter.ToString("F2"), + pulseFreqsForDetection[0].ToString("F2"), + aveFreqBefore.ToString("F2"), + aveFreqAfter.ToString("F2"))); + + //detectedFlow = (aveFlowBefore + aveFlowAfter) / 2.0f; + detectedFlow = aveFlowBefore; + + if (rvPulse > 0) + { + detected = (aveFreqAfter < aveFreqBefore * (1.0f - testParams.DetectionThreshold)); + targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) > testParams.TargetQ; + } + else + { + detected = (aveFreqAfter > aveFreqBefore * (1.0f + testParams.DetectionThreshold)); + targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) < testParams.TargetQ; + } + } + } + } + while (!detected && !targetReached); + + Qrise = detectedFlow; + UiBridge.Bridge.OnLog(this, string.Format("detected flow={0}\r\n", detectedFlow.ToString("F2"))); + + int flowSetTime1 = StateMachine.Time; + + Bridge.OnProcessData(this, new ProcessDataEventArgs(test, repetitionNr, Config.Entities.Progress.FlowSetting)); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.FlowSetting)); + + //-------------------------------- + //State.Create(string.Format("{0}({1}) : Flow sensitivity detected", test.Method, test.Name)) + + TestEndTime = DateTime.Now; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Test_completed); + //------------------------------------------------ + State.Create(string.Format("{0}({1}) : {2}", test.Method, test.Name, Strings.Stop_the_pump)) + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOffOp() : null) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation(cBrd.UpdateTankWeightOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (TestAndLogUiCmdStop(test,e)) goto stopTest; + } + while (!e.Contains(Event.ValvesSet)); + + + //-------------------------------- + State.Create(string.Format("{0}({1}) : Stopping diverter, gate, etc.", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (TestAndLogUiCmdStop(test,e)) goto stopTest; + } + while (!e.Contains(Event.PreviousStopped)); + + /// Make sure the CycleBeginForm is closed so that water meter data (s/n) can be copied into results + if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stopTest; + + /// + /// Populate TestResult data entity with data + /// + Results.Entities.TestRslt tstRslt = BatchRslts.GetTestRslt(testName, test.Part); + + if (tstRslt != null) + { + UpdateTempPressDensAmb(tstRslt); + + /// Main results + tstRslt.StartTime = TestStartTime; + tstRslt.EndTime = TestEndTime; + tstRslt.FlowSetTime = flowSetTime1 - flowSetTime0; + tstRslt.TestTime = cBrd.TTime; /// [s] measurement time + tstRslt.PulsesMaster = 0; /// Pulses of the master flow meter (test total) + tstRslt.MassStartRaw = 0; + tstRslt.MassStart = 0; + tstRslt.MassEndRaw = 0; + tstRslt.MassEnd = 0; + tstRslt.FlowMass = 0; + tstRslt.FlowVolume = 0; + tstRslt.Buoyancy = Formulas.Buoyancy(); + tstRslt.VolumeCTV = 0; + tstRslt.VolumeMaster = 0; + tstRslt.ConstMaster = 0; + tstRslt.ErrorMaster = 0; + + tstRslt.FlowMean = (float)RefFlowStat.Average; + tstRslt.FlowStart = (float)RefFlowStat.First; + tstRslt.FlowEnd = (float)RefFlowStat.Last; + tstRslt.FlowMin = (float)RefFlowStat.Min; + tstRslt.FlowMax = (float)RefFlowStat.Max; + + tstRslt.DiverterStart = switchTimeStart; + tstRslt.DiverterEnd = switchTimeEnd; + tstRslt.ErrorFlagsMd = (ErrorFlagsComp != null) ? (sbyte)ErrorFlagsComp.Mode : (sbyte)0; + tstRslt.ErrorFlags = (ErrorFlagsComp != null) ? ErrorFlagsComp.GetErrorFlags(tstRslt, true, false, switchTimeStart, switchTimeEnd) : 0; + + for (int i = 0; i < BatchRslts.WMPositionsCount; i++) + { + Results.Entities.MeterTestRslt meterRslt = BatchRslts.GetMeterTestRslt(testName, i, Config.Entities.CompoundMeterId.Single); + + GenericDevices.IRegisterReader regReader = sensPath.RegisterReaders[i]; + + if (meterRslt != null && regReader != null) + { + meterRslt.PulsesPerLiter = regReader.PulsesPerLtr; + + meterRslt.Passed = (Qrise <= test.Qto) && (tstRslt.ErrorFlags == 0 || tstRslt.ErrorFlagsMode() != Config.Entities.ErrorFlagsMode.On); + meterRslt.TestDone = true; + tstRslt.TestDone = true; + + if (Qrise != 0) + { + BatchRslts.WaterMeters[i].QRise = Qrise; + } + BatchRslts.WaterMeters[i].QFall = 0; + } + } + + tstRslt.Components = Results.Entities.Components + .UpdateList(BatchRslts.ComponentsList, + new Results.Entities.Components((BenchInfo != null) ? BenchInfo.TestBenchId : 1, + (BenchInfo != null) ? BenchInfo.TestBenchName : "testbench", + inPath.Pump != null ? inPath.Pump.Name : string.Empty, + outPath.FlowMeter != null ? outPath.FlowMeter.Name : string.Empty, + outPath.Scale != null ? outPath.Scale.Name : string.Empty, + outPath.RegulValve != null ? outPath.RegulValve.Name : string.Empty, + outPath.Diverter != null ? outPath.Diverter.Name : string.Empty)); + + /// Update water meter error flags + if (ErrorFlagsComp != null) + { + for (int i = 0; i < BatchRslts.WMPositionsCount; i++) + { + if (BatchRslts.WaterMeters[i] != null) + { + BatchRslts.WaterMeters[i].ErrorFlags = ErrorFlagsComp.GetWMtrErrorFlags(BatchRslts.WaterMeters[i].MeterTestRslts); + } + } + } + + /// Update results + Bridge.OnTestCompleted(this, new TestCompletedEventArgs(testName, tstRslt)); + } + + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.TransitionAfter)); + + /// Append the results to the CSV-file + allResults.Info(TestResult2CsvLine(testName, test.Part)); + + if (!outerLoopMode && (++repetitionNr <= test.Repeats)) + { + goto loop; + } + + ///----------------------/// + /// Quit this sequence /// + ///----------------------/// + + /// Stop the pump + State.Create(string.Format("{0}({1}) : Test(s) completed -> Stopping the pump", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOffOp() : null) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet) || ((inPath.Pump is GenericDevices.IPumpFM) && !e.Contains(Event.TurnPumpOnOffDone))); + + /// Transition or SetRoute - End + switch (Transition(transitionAfter, TransitionContext.AfterTest)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stopTest; + } + + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Config.Entities.Progress.Completed)); + + /// Create the return value - a list with one event Event.Done - and return + IList retval1 = new List(1); + retval1.Add(Event.Done); + return retval1; + + //==================================== + stopTest: + + State.Create(string.Format("{0}({1}) : User selected STOP -> Closing the valves", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOffOp() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, 1, Config.Entities.Progress.Aborted)); + + IList retval2 = new List(1); + retval2.Add(Event.UiCmdStop); + return retval2; + + //==================================== + error: + State.Create(string.Format("{0}({1}) : close_before_error", test.Method, test.Name)) + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOffOp() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, 1, Config.Entities.Progress.Aborted)); + + IList retval3 = new List(1); + retval3.Add(Event.Error); + return retval3; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethod.cs b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethod.cs new file mode 100644 index 000000000..84f6bbf4b --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethod.cs @@ -0,0 +1,37 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Collections.Generic; +using log4net; +using Config.Entities; +using TBF.BenchControl; + +namespace TBF.BenchControl.TestMethods.SensitivityTest +{ + public class TestMethod : ComponentBase, GenericDevices.ITestMethod + { + private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod)); + public override string ToString() { return string.Format("TestMethods.CombinedWithDetection({0})", Cfg.ToString(1)); } + + readonly TestMethodCfg testMethodCfg; + + public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; } + + public TestMethod() + { + } + + public TestMethod(Generic.IComponentCfg cfg) + : base(cfg) + { + testMethodCfg = cfg as TestMethodCfg; + log.Debug(this.ToString()); + } + + public IList Execute(Test test, bool outerLoopMode, int outerLoopCounter) + { + return (new SensitivityTestSeq()).Execute(test, outerLoopMode, outerLoopCounter, testMethodCfg.TestParams, DebugLevel); + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfg.cs b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfg.cs new file mode 100644 index 000000000..889f999bb --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfg.cs @@ -0,0 +1,50 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.SensitivityTest +{ + public class TestMethodCfg : ComponentCfgBase, Generic.IComponentCfg + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TestMethodCfg) })[0]; + protected override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl() { return new TestMethodCfgCtrl(); } + + /// Test parameters + [XmlIgnore] + public SensitivityTestParams TestParams; + public override IParamsProvider GetTestParams() { return TestParams; } + public override IParamsProvider CreateTestParams(Test test) + { + SensitivityTestParams testParams = new SensitivityTestParams(true); + testParams.UpdateTestParams(Name, test); + return testParams; + } + + /// Private parameterless constructor invoked by all other (public) constructors + TestMethodCfg() + { + TestParams = new SensitivityTestParams(true); + } + + public TestMethodCfg(string name, IComponentFactory factory) + : this() + { + Name = name; + ParentName = string.Empty; + Factory = factory; + } + + public string ToString(int i) + { + return string.Format("Name={0}", Name); + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.cs b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.cs new file mode 100644 index 000000000..9703a5652 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.cs @@ -0,0 +1,71 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.SensitivityTest +{ + public partial class TestMethodCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(TestMethodCfgCtrl)); + + public bool ShowMore { get { return false; } } + + TestMethodCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as TestMethodCfg; + Redraw(); + } + } + + public TestMethodCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + public void Closing() + { + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgUpdateFlags VerifyCfg(ref string message) + { + CfgUpdateFlags flags = CfgUpdateFlags.None; + return flags; + } + + public CfgUpdateFlags UpdateCfg() + { + CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd; + + if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + + return flags; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.designer.cs new file mode 100644 index 000000000..6aa2c766e --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.designer.cs @@ -0,0 +1,86 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +namespace TBF.BenchControl.TestMethods.SensitivityTest +{ + partial class TestMethodCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // BasicPrinterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "BasicPrinterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.resx b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodFactory.cs b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodFactory.cs new file mode 100644 index 000000000..4b04026e9 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/SensitivityTest/TestMethodFactory.cs @@ -0,0 +1,26 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.SensitivityTest +{ + public class TestMethodFactory : IComponentFactory + { + public string ClassName { get { return this.GetType().Namespace.Substring(17) + ".Single"; } } + + public void ResetStaticProperties() { TestMethod.ResetStaticProperties(); } + + public IComponent DummyComponent() { return new TestMethod(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new TestMethod(cfg); } + + public IComponentCfg DefaultConfig() { return new TestMethodCfg(this.GetType().Namespace.Substring(29), this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(TestMethodCfg.Serializer, component, this); + } + } +} diff --git a/TestBenchFramework/TBF.csproj b/TestBenchFramework/TBF.csproj index 722695ff1..e312c1580 100644 --- a/TestBenchFramework/TBF.csproj +++ b/TestBenchFramework/TBF.csproj @@ -982,6 +982,17 @@ + + + + + + UserControl + + + TestMethodCfgCtrl.cs + + @@ -2261,6 +2272,9 @@ TestMethodCfgCtrl.cs + + TestMethodCfgCtrl.cs + ErrorsCfgCtrl.cs