1056 lines
46 KiB
C#
1056 lines
46 KiB
C#
///
|
|
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using log4net;
|
|
using Config.Entities;
|
|
using TBF.BenchControl.GenericDevices;
|
|
using TBF.BenchControl.Operations;
|
|
using TBF.Boxes;
|
|
using TBF.Resources;
|
|
using TBF.UiBridge;
|
|
|
|
namespace TBF.BenchControl.Sequences
|
|
{
|
|
/// <summary>
|
|
/// Sequence is a group of states that can be dynamically added to
|
|
/// and removed from the state machine
|
|
/// </summary>
|
|
public class SequenceBase : ProcessData
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(SequenceBase));
|
|
|
|
protected static readonly ILog processDataLogger = LogManager.GetLogger("ProcessData");
|
|
protected static readonly ILog allResults = LogManager.GetLogger("AllResults");
|
|
protected static readonly ILog summaryResults = LogManager.GetLogger("SummaryResults");
|
|
|
|
///------------------------------------------------------------
|
|
/// Global static variables set only once.
|
|
///------------------------------------------------------------
|
|
public static IList<IFlowMeter> FlowMeters; /// list of reference flowmeters
|
|
public static IList<IRegulValve> RegulValves; /// list of regulation valves
|
|
public static IList<IPumpFM> PumpsWithFM; /// list of FM controlled pumps
|
|
public static IList<IWaterMeter> WaterMeters; /// list of water meters
|
|
public static IList<ICamera> Cameras; /// list of cameras
|
|
|
|
///------------------------------------------------------------
|
|
/// Procedure related (static) variables.
|
|
/// They are re-initialized when LoadProcedure() is called
|
|
///------------------------------------------------------------
|
|
public static int ReferenceFlowmetersCount;
|
|
public static float[] CalibratedLtrPerRefPulse; /// Reference flowmeter coefficients
|
|
public static double Qrise;
|
|
public static double Qfall;
|
|
|
|
|
|
///------------------------------------------------------------
|
|
/// Test related (instance) variables.
|
|
/// Created when test sequence is open.
|
|
/// They persist during all repetitions of the same test
|
|
///------------------------------------------------------------
|
|
protected static BenchControl.FeedingPath inPath;
|
|
protected static BenchControl.BenchPath benchPath;
|
|
protected static BenchControl.OutputPath outPath;
|
|
protected static BenchControl.MetersPath sensPath;
|
|
protected static TransitionSequence transitionBefore;
|
|
protected static TransitionSequence transitionAfter;
|
|
|
|
|
|
protected IOperation readRegistersOp;
|
|
protected IOperation queryEnd1;
|
|
protected IOperation queryEnd2;
|
|
protected IOperation checkUiOp;
|
|
|
|
protected IOperation processDataLoggingOp;
|
|
|
|
|
|
///
|
|
/// Process data logging
|
|
///
|
|
public void LogProcessHeader(ILog logger)
|
|
{
|
|
LogProcessHeader(logger, null);
|
|
}
|
|
|
|
public void LogProcessHeader(ILog logger, string sectionName)
|
|
{
|
|
logger.Info(Environment.NewLine);
|
|
if (sectionName != null) logger.Info(sectionName);
|
|
logger.Info("Time Flow TstTime Ref.cnt Ref.vol Tin Tout Tdiv Pin Pout Mass VolMM Tamb Hamb Pamb Rv");
|
|
logger.Info(Environment.NewLine);
|
|
}
|
|
|
|
public void LogProcessData(ILog logger)
|
|
{
|
|
logger.InfoFormat("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14} {15}",
|
|
DateTime.Now.ToLongTimeString(),
|
|
Utils.FloatToStr(RefFlow.Val, 4),
|
|
StateMachine.ControlBoard.TTime.ToString("F3"),
|
|
StateMachine.ControlBoard.EtPulses(0),
|
|
Formulas.VolumeFromPulses(StateMachine.ControlBoard.EtPulses(0), 1.0f / LtrPerRefPulse).ToString("F3"),
|
|
TempIn,
|
|
TempOut,
|
|
TempDiv,
|
|
PressureUp,
|
|
PressureDown,
|
|
Mass,
|
|
"VolMM",
|
|
AmbientTemp,
|
|
AmbientHumidity,
|
|
AmbientPressure,
|
|
outPath.RegulValve.Position.ToString("F1"));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Empties the tank: opens the emptying valve and measures the weight.
|
|
/// </summary>
|
|
/// <param name="EmptyTankValve">Valve to empty the tank</param>
|
|
/// <param name="Balance">Balance underneath the tank</param>
|
|
/// <returns>Event.Done or Event.Error</returns>
|
|
protected Event EmptyTheTank(IValve EmptyTankValve, IBalance Balance)
|
|
{
|
|
//------------------------------------------------
|
|
Bridge.OnActivity(this, TBF.Resources.Strings.Emptying_tank);
|
|
//------------------------------------------------
|
|
|
|
IList<Event> e;
|
|
Bridge.Bench2UI(ButtonsEtc.StopBtnEn);
|
|
|
|
State.Create("SequenceBase : Opening the emptying valve")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(StateMachine.ControlBoard.SetValvesOp(EmptyTankValve, null))
|
|
.EnterState();
|
|
do { e = StateMachine.WaitRunDevsRunOps(); }
|
|
while (!e.Contains(Event.ValvesSet));
|
|
|
|
do
|
|
{
|
|
//--------------------------------
|
|
State.Create("SequenceBase : Emptying the tank")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(Balance.ReadMassOp(ref Mass))
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) return Event.Error;
|
|
if (TestAndLogUiCmdStop(e)) goto quit_emptying;
|
|
if (e.Contains(Event.BalanceOverload)) { }; /// Tank should be emptying now
|
|
}
|
|
while (!e.Contains(Event.BalanceDone));
|
|
}
|
|
while (!Balance.IsEmpty(Mass.Val));
|
|
|
|
quit_emptying:
|
|
//--------------------------------
|
|
State.Create("SequenceBase : Closing the emptying valve")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(Balance.ReadMassOp(ref Mass))
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation(StateMachine.ControlBoard.SetValvesOp(null, EmptyTankValve))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) return Event.Error;
|
|
}
|
|
while (!e.Contains(Event.ValvesSet) || !e.Contains(Event.BalanceDone));
|
|
|
|
State.Create("SequenceBase : Updating the weight")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(Balance.ReadMassOp(ref Mass))
|
|
.AddOperation(new Operations.TimerOp(5))
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) return Event.Error;
|
|
}
|
|
while (!e.Contains(Event.BalanceDone) || !e.Contains(Event.TimerExpired));
|
|
|
|
return Event.Done;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Passed as an argument to Transition(sequence, context)
|
|
/// </summary>
|
|
public enum TransitionContext
|
|
{
|
|
PurgeBegin,
|
|
BeforeTest,
|
|
AfterTest,
|
|
PurgeEnd,
|
|
Stop,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes steps of a transition sequence
|
|
/// </summary>
|
|
/// <param name="transitionSequence">TransitionSequence entity</param>
|
|
/// <param name="context">Calling context (see above)</param>
|
|
/// <returns>
|
|
/// Event.Done Transition sequence completed OK
|
|
/// Event.UiCmdStop Transition sequence interrupted by the STOP on-screen button
|
|
/// Event.Error Error (e.g. RegulValveTimeOut returned by Run() of SetRegulValvePositionOp)
|
|
/// </returns>
|
|
protected Event Transition(TransitionSequence transitionSequence, TransitionContext context)
|
|
{
|
|
bool stopFlag = false;
|
|
bool errorFlag = false;
|
|
IList<Event> e;
|
|
string message;
|
|
///
|
|
switch (context)
|
|
{
|
|
case TransitionContext.PurgeBegin: message = Strings.Purging_i_n; break;
|
|
case TransitionContext.BeforeTest: message = Strings.Test_start_sequence_i_n; break;
|
|
case TransitionContext.AfterTest: message = Strings.Test_stop_sequence_i_n; break;
|
|
case TransitionContext.PurgeEnd: message = Strings.Emptying_i_n; break;
|
|
case TransitionContext.Stop: message = Strings.Test_stop_sequence_i_n; break;
|
|
default: message = "Transition"; break;
|
|
}
|
|
|
|
if (transitionSequence == null)
|
|
{
|
|
log.WarnFormat("Transition(null, context={0})", context);
|
|
|
|
///
|
|
/// No transition sequence defined --> Default action
|
|
///
|
|
if (context == TransitionContext.AfterTest)
|
|
{
|
|
if (inPath.Pump is GenericDevices.IPumpFM) (inPath.Pump as GenericDevices.IPumpFM).TurnOff();
|
|
|
|
State.Create("SequenceBase : Transition : TestEnd - Default action")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(new MettlerToledo.KeepReadingMassesOp())
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen,
|
|
StateMachine.DefaultValvesClose))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (TestAndLogUiCmdStop(e)) return Event.UiCmdStop;
|
|
}
|
|
while (!e.Contains(Event.ValvesSet));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
///
|
|
/// Execute the transition sequence
|
|
///
|
|
IList<TransitionStep> transitionSteps = StateMachine.WtSession
|
|
.CreateQuery("FROM TransitionStep WHERE TransitionSequence = :tsId ORDER BY ItemNr")
|
|
.SetParameter("tsId", transitionSequence.Id)
|
|
.List<TransitionStep>();
|
|
|
|
int stepsCount = transitionSteps.Count;
|
|
|
|
log.WarnFormat("Transition(sequence={0} ({1} steps), context={2})", transitionSequence.Name, stepsCount, context);
|
|
|
|
foreach (var step in transitionSteps)
|
|
{
|
|
//------------------------------------------------
|
|
string activity = string.Format(message, transitionSequence.Name, step.ItemNr + 1, stepsCount);
|
|
Bridge.OnActivity(this, activity);
|
|
Bridge.OnMessage(this, step.Message);
|
|
log.Info(activity + " " +step.Message);
|
|
//------------------------------------------------
|
|
|
|
/// FM controlled pumps are canged imediately without using any state operations
|
|
log.DebugFormat("step.PumpWithFMPcts = {0}", step.PumpWithFMPcts);
|
|
float[] allFMPumpPcts = Utils.GetPumpWithFMPcts(step);
|
|
for (int i = 0; i < allFMPumpPcts.Length; i++)
|
|
{
|
|
float pwr = allFMPumpPcts[i];
|
|
if (pwr > 0) /// Negative value means no power change
|
|
{
|
|
PumpsWithFM[i].TurnOn(pwr);
|
|
}
|
|
else if (pwr == 0)
|
|
{
|
|
PumpsWithFM[i].TurnOff();
|
|
}
|
|
}
|
|
|
|
/// Get new regulation valve positions,
|
|
float[] allRegvPositions = Utils.GetRegulValvesPositions(step);
|
|
|
|
/// Prepare necessary SetRegValvePositionOp operations for RV-s with changed positions
|
|
IList<IOperation> rvPosOps = new List<IOperation>();
|
|
IList<string> rvPosStr = new List<string>();
|
|
for (int i = 0; i < allRegvPositions.Length; i++)
|
|
{
|
|
if (allRegvPositions[i] >= 0) /// Negative value means no position change
|
|
{
|
|
if (RegulValves[i].IsCoax)
|
|
{
|
|
rvPosOps.Add(RegulValves[i].SetRegulValvePositionOp(allRegvPositions[i], allRegvPositions[i], 60));
|
|
rvPosStr.Add(string.Format("RV{0}.SetRegulValvePositionOp({1}, {1}, 60s)", i, allRegvPositions[i]));
|
|
}
|
|
else
|
|
{
|
|
float lo = Math.Max(0, allRegvPositions[i] - 0.05f);
|
|
float hi = Math.Min(100.0f, allRegvPositions[i] + 0.05f);
|
|
rvPosOps.Add(RegulValves[i].SetRegulValvePositionOp(lo, hi, 60));
|
|
rvPosStr.Add(string.Format("RV{0}.SetRegulValvePositionOp({1}, {2}, 60s)", i, lo, hi));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Max. one SetRegulValvePositionOp can be started or stopped in one sub-step.
|
|
/// Therefore SetRegulValvePositionOp operations are added and removed to subsequent states one by one.
|
|
int delay = Math.Max(2, step.Duration - rvPosOps.Count + 2);
|
|
|
|
///
|
|
int lastStartedRV = -1;
|
|
for (int i = 0; i < rvPosOps.Count; i++)
|
|
{
|
|
log.DebugFormat("SequenceBase.Transition() : Step {0} start, opening={1}, closing={2}", step.ItemNr + 1, step.ValvesOpen, step.ValvesClose);
|
|
State stepStrt = State
|
|
.Create(string.Format("SequenceBase.Transition() : Step {0} start, opening={1}, closing={2}", step.ItemNr + 1, step.ValvesOpen, step.ValvesClose))
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(new MettlerToledo.KeepReadingMassesOp())
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation(StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step)));
|
|
for (int j = 0; j <= i; j++)
|
|
{
|
|
stepStrt.AddOperation(rvPosOps[j]);
|
|
log.Debug(rvPosStr[j]);
|
|
}
|
|
lastStartedRV = i;
|
|
stepStrt.EnterState();
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error) || e.Contains(Event.RegulValveTimeOut)) { errorFlag = true; break; }
|
|
if (TestAndLogUiCmdStop(e)) { stopFlag = true; break; }
|
|
}
|
|
/// Max. valaue of lastStartedRV after exitting the loop is (rvPosOps.Count - 1)
|
|
|
|
if (!stopFlag && !errorFlag)
|
|
{
|
|
log.DebugFormat("SequenceBase.Transition() : Step {0} delay {1}s, opening={2}, closing={3}", step.ItemNr + 1, delay, step.ValvesOpen, step.ValvesClose);
|
|
State stepDelay = State
|
|
.Create(string.Format("SequenceBase.Transition() : Step {0} delay {1}s, opening={2}, closing={3}", step.ItemNr + 1, delay, step.ValvesOpen, step.ValvesClose))
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(new MettlerToledo.KeepReadingMassesOp())
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation(StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step)))
|
|
.AddOperation(new TimerOp(delay));
|
|
for (int j = 0; j <= lastStartedRV; j++)
|
|
{
|
|
stepDelay.AddOperation(rvPosOps[j]);
|
|
log.Debug(rvPosStr[j]);
|
|
}
|
|
stepDelay.EnterState();
|
|
bool endContitionFulfilled = false;
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error) || e.Contains(Event.RegulValveTimeOut)) { errorFlag = true; break; }
|
|
if (TestAndLogUiCmdStop(e)) { stopFlag = true; break; }
|
|
|
|
switch (step.EndCondition)
|
|
{
|
|
case StepCondition.Scale1Empty:
|
|
endContitionFulfilled = (StateMachine.Balance1 == null) || StateMachine.Balance1.IsEmpty();
|
|
break;
|
|
case StepCondition.Scale2Empty:
|
|
endContitionFulfilled = (StateMachine.Balance2 == null) || StateMachine.Balance2.IsEmpty();
|
|
break;
|
|
case StepCondition.Scale3Empty:
|
|
endContitionFulfilled = (StateMachine.Balance3 == null) || StateMachine.Balance3.IsEmpty();
|
|
break;
|
|
case StepCondition.AllScalesEmpty:
|
|
endContitionFulfilled = ((StateMachine.Balance1 == null) || StateMachine.Balance1.IsEmpty()) &&
|
|
((StateMachine.Balance2 == null) || StateMachine.Balance2.IsEmpty()) &&
|
|
((StateMachine.Balance3 == null) || StateMachine.Balance3.IsEmpty());
|
|
break;
|
|
}
|
|
}
|
|
while (e.Contains(Event.ValvesBusy) || (!endContitionFulfilled && e.Contains(Event.TimerBusy)));
|
|
}
|
|
|
|
for (int first = 1; first <= lastStartedRV; first++)
|
|
{
|
|
log.DebugFormat("SequenceBase.Transition() : Step {0} stop, opening={1}, closing={2}", step.ItemNr + 1, step.ValvesOpen, step.ValvesClose);
|
|
State stepStop = State.Create(string.Format("SequenceBase.Transition() : Step {0} stop, opening={1}, closing={2}", step.ItemNr + 1, step.ValvesOpen, step.ValvesClose))
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(new MettlerToledo.KeepReadingMassesOp())
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation(StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step)));
|
|
for (int j = first; j <= lastStartedRV; j++)
|
|
{
|
|
stepStop.AddOperation(rvPosOps[j]);
|
|
log.Debug(rvPosStr[j]);
|
|
}
|
|
stepStop.EnterState();
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error) || e.Contains(Event.RegulValveTimeOut)) { errorFlag = true; }
|
|
if (TestAndLogUiCmdStop(e)) { stopFlag = true; }
|
|
}
|
|
|
|
if (errorFlag || stopFlag) break;
|
|
}
|
|
|
|
Bridge.OnMessage(this, string.Empty); /// Clear the last step message
|
|
}
|
|
|
|
///
|
|
/// Do this after executing the transition sequence
|
|
///
|
|
if (context == TransitionContext.Stop || errorFlag || stopFlag)
|
|
{
|
|
///
|
|
/// On error or when STOP pressed
|
|
///
|
|
foreach (var fmPump in PumpsWithFM) fmPump.TurnOff();
|
|
|
|
if (inPath != null)
|
|
{
|
|
/// Stop the pump
|
|
///
|
|
State.Create("SequenceBase.Transition() : Test stopped -> Stopping the pump")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation((inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOffOp() : null)
|
|
.AddOperation(StateMachine.ControlBoard.SetValvesOp(null, inPath.Pump))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) return Event.Error;
|
|
}
|
|
while (!e.Contains(Event.ValvesSet) || ((inPath.Pump is GenericDevices.IPumpFM) && !e.Contains(Event.TurnPumpOnOffDone)));
|
|
}
|
|
}
|
|
else if (context == TransitionContext.BeforeTest)
|
|
{
|
|
if (inPath != null && benchPath != null && outPath != null)
|
|
{
|
|
State.Create("SequenceBase : Transition : TestStart - Default action")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(new MettlerToledo.KeepReadingMassesOp())
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation(StateMachine.ControlBoard
|
|
.SetValvesOp(GenericDevices.ValveBase.Merge(inPath.ValvesOpen, benchPath.ValvesOpen, outPath.ValvesOpen),
|
|
GenericDevices.ValveBase.Merge(inPath.ValvesClose, benchPath.ValvesClose, outPath.ValvesClose)))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) return Event.Error;
|
|
if (TestAndLogUiCmdStop(e)) return Event.UiCmdStop;
|
|
}
|
|
while (e.Contains(Event.ValvesBusy));
|
|
}
|
|
}
|
|
|
|
|
|
if (errorFlag)
|
|
return Event.Error;
|
|
else if (stopFlag)
|
|
return Event.UiCmdStop;
|
|
else
|
|
return Event.Done;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Opens a modeless dialog for entering data at the beginning of a procedure (serial numbers)
|
|
/// </summary>
|
|
/// <returns>false = OK, true = stop pressed</returns>
|
|
protected bool OpenCycleBeginForm()
|
|
{
|
|
IList<Event> e;
|
|
GenericDevices.IDataEntry dataEntryCmpnt =
|
|
TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IDataEntry;
|
|
if (dataEntryCmpnt is IHasCycleBeginForm)
|
|
{
|
|
Bridge.OnActivity(this, Strings.Enter_water_meter_data);
|
|
State.Create("MainSeq : Enter begin data")
|
|
.AddPermanentOperation((dataEntryCmpnt as IHasCycleBeginForm).ShowCycleBeginFormOp())
|
|
.AddOperation(checkUiOp)
|
|
.EnterState();
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (TestAndLogUiCmdStop(e)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Waits until a modeless dialog for entering data at the beginnig of a procedure is closed.
|
|
/// This function is typically called at the end of the first test of the procedure.
|
|
/// </summary>
|
|
/// <returns>false = OK, true = stop pressed</returns>
|
|
protected UIFlowControl WaitBeginFormClosed()
|
|
{
|
|
GenericDevices.IDataEntry dataEntryCmpnt =
|
|
TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IDataEntry;
|
|
|
|
bool stopPressed = false; /// true when STOP button pressed
|
|
|
|
if (dataEntryCmpnt is IHasCycleBeginForm)
|
|
{
|
|
IList<Event> e;
|
|
|
|
///
|
|
/// Wait until modeless form is closed by the user if it is stil open
|
|
///
|
|
if ( State.LastEvents.Contains(Event.ModelessFormIsOpen))
|
|
{
|
|
State.Create("MainSeq : Wait until the entry form is closed")
|
|
.AddOperation(checkUiOp)
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (TestAndLogUiCmdStop(e))
|
|
{
|
|
stopPressed = true;
|
|
break;
|
|
}
|
|
}
|
|
while (!e.Contains(Event.ModelessFormClosed));
|
|
}
|
|
|
|
///
|
|
/// A state without any dataEntryCmpnt operation so that Stop() when entering
|
|
/// this state and Start() when entering the following state are executed.
|
|
///
|
|
State.Create("MainSeq : Stopping modeless form")
|
|
.AddOperation(checkUiOp)
|
|
.RemovePermanentOperation(dataEntryCmpnt as IOperation)
|
|
.EnterState();
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
|
|
if (TestAndLogUiCmdStop(e)) { stopPressed = true; }
|
|
}
|
|
|
|
return stopPressed ? UIFlowControl.Stop : UIFlowControl.Continue;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Forces closing of a modeless dialog for entering data at the beginnig of a procedure.
|
|
/// This function is typically called before starting a new cycle
|
|
/// in case previous cycle was aborted.
|
|
/// </summary>
|
|
protected void CloseBeginForm()
|
|
{
|
|
if (StateMachine.Procedure == null || StateMachine.Procedure.DataEntry == null) return;
|
|
|
|
GenericDevices.IDataEntry dataEntryCmpnt =
|
|
TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IDataEntry;
|
|
|
|
if ((dataEntryCmpnt is IHasCycleBeginForm) &&
|
|
(State.LastEvents.Contains(Event.ModelessFormIsOpen) || State.LastEvents.Contains(Event.ModelessFormClosed)))
|
|
{
|
|
IList<Event> e;
|
|
|
|
/// A state without any dataEntryCmpnt operation so that Stop() when entering
|
|
/// this state and Start() when entering the following state are executed.
|
|
State.Create("MainSeq : Stopping modeless form")
|
|
.RemovePermanentOperation(dataEntryCmpnt as IOperation)
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
}
|
|
while (e.Contains(Event.ModelessFormIsOpen));
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Main loop where measurements are collected.
|
|
/// </summary>
|
|
/// <param name="realTest">false = a flow setting or a switching flow detection, true = measurement</param>
|
|
/// <returns>Event.MeasurementCompleted, Event.UiCmdStop, Event.Error or Event.Done</returns>
|
|
protected Event ReadRegistersTempPressAmbient(IList<IOperation> measureOperations, bool realTest)
|
|
{
|
|
IList<Event> e;
|
|
|
|
State.Create("Read water meters")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperations(measureOperations)
|
|
.AddOperation(readRegistersOp)
|
|
.AddOperation(benchPath.TempIn.ReadTempOp(ref TempIn))
|
|
.AddOperation(benchPath.TempOut.ReadTempOp(ref TempOut))
|
|
.AddOperation(outPath.TempDiv.ReadTempOp(ref TempDiv))
|
|
.AddOperation(benchPath.PressIn.ReadPressureOp(ref PressureUp))
|
|
.AddOperation(benchPath.PressOut.ReadPressureOp(ref PressureDown))
|
|
.AddOperation(realTest ? outPath.Balance.ReadMassOp(ref Mass) : null)
|
|
.AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp())
|
|
.AddOperation((StateMachine.Ambient != null)
|
|
? StateMachine.Ambient.ReadAmbientOp(AmbientTemp, AmbientPressure, AmbientHumidity)
|
|
: null)
|
|
//.AddOperation(realTest ? (ticTac ? queryEnd1 : queryEnd2) : null)
|
|
.AddOperation(realTest ? queryEnd1 : null)
|
|
.AddOperation(realTest ? processDataLoggingOp : null)
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) return Event.Error;
|
|
if (TestAndLogUiCmdStop(e)) return Event.UiCmdStop;
|
|
if (e.Contains(Event.MeasurementCompleted)) return Event.MeasurementCompleted;
|
|
}
|
|
while ( (realTest && !e.Contains(Event.BalanceDone)) ||
|
|
!e.Contains(Event.ReadAllRegistersDone));
|
|
|
|
return Event.Done;
|
|
}
|
|
|
|
|
|
protected string TestResult2CsvLine(string testName, int part)
|
|
{
|
|
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(testName, part);
|
|
|
|
if (tstRslt == null) return string.Empty;
|
|
|
|
return TestResult2CsvLine(tstRslt);
|
|
}
|
|
|
|
|
|
protected string TestResult2CsvLine(Results.Entities.TestRslt tstRslt)
|
|
{
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
sb.Append(tstRslt.StartTime);
|
|
sb.Append(";"); sb.Append(tstRslt.Batch.BatchNr);
|
|
sb.Append(";"); sb.Append(tstRslt.Name());
|
|
sb.Append(";"); sb.Append(tstRslt.RepetitionNr);
|
|
sb.Append(";"); sb.Append("1");
|
|
sb.Append(";"); sb.Append(tstRslt.Method());
|
|
sb.Append(";"); sb.Append(tstRslt.TargetVolume());
|
|
sb.Append(";"); sb.Append(tstRslt.Qfrom());
|
|
sb.Append(";"); sb.Append(tstRslt.Qto());
|
|
sb.Append(";"); sb.Append(tstRslt.ErrLimLo() + tstRslt.Uncertainty());
|
|
sb.Append(";"); sb.Append(tstRslt.ErrLimHi() - tstRslt.Uncertainty());
|
|
sb.Append(";"); sb.Append("0");
|
|
sb.Append(";"); sb.Append("60");
|
|
sb.Append(";"); sb.Append("0");
|
|
sb.Append(";"); sb.Append("0");
|
|
sb.Append(";"); sb.Append(outPath.FlowMeter.Idx1);
|
|
sb.Append(";"); sb.Append(" ");
|
|
sb.Append(";"); if (outPath.Balance != null) sb.Append(outPath.Balance.Name);
|
|
sb.Append(";"); sb.Append(tstRslt.AmbientTempAve);
|
|
sb.Append(";"); sb.Append(tstRslt.AmbientPressAve);
|
|
sb.Append(";"); sb.Append(tstRslt.AmbientHumiAve);
|
|
sb.Append(";"); sb.Append(tstRslt.PressUpAvrg);
|
|
sb.Append(";"); sb.Append(tstRslt.PressDownAvrg);
|
|
sb.Append(";"); sb.Append(tstRslt.PressUpStart);
|
|
sb.Append(";"); sb.Append(tstRslt.PressDownStart);
|
|
sb.Append(";"); sb.Append(tstRslt.PressUpEnd);
|
|
sb.Append(";"); sb.Append(tstRslt.PressDownEnd);
|
|
sb.Append(";"); sb.Append(tstRslt.TempInAvrg);
|
|
sb.Append(";"); sb.Append(tstRslt.TempOutAvrg);
|
|
sb.Append(";"); sb.Append(tstRslt.TempDivAvrg);
|
|
sb.Append(";"); sb.Append(tstRslt.TempInStart);
|
|
sb.Append(";"); sb.Append(tstRslt.TempOutStart);
|
|
sb.Append(";"); sb.Append(tstRslt.TempDivStart);
|
|
sb.Append(";"); sb.Append(tstRslt.TempInEnd);
|
|
sb.Append(";"); sb.Append(tstRslt.TempOutEnd);
|
|
sb.Append(";"); sb.Append(tstRslt.TempDivEnd);
|
|
sb.Append(";"); sb.Append(tstRslt.MassStartRaw);
|
|
sb.Append(";"); sb.Append(tstRslt.MassStart);
|
|
sb.Append(";"); sb.Append(tstRslt.MassEndRaw);
|
|
sb.Append(";"); sb.Append(tstRslt.MassEnd);
|
|
sb.Append(";"); sb.Append(tstRslt.MassEnd - tstRslt.MassStart);
|
|
sb.Append(";"); sb.Append(tstRslt.DensityDiv);
|
|
sb.Append(";"); sb.Append(tstRslt.DensityIn);
|
|
sb.Append(";"); sb.Append(tstRslt.DensityOut);
|
|
sb.Append(";"); sb.Append(" "); /// d_air: Hustota vzduchu: Sheet1 - K9
|
|
sb.Append(";"); sb.Append(" "); /// Buoyancy: Sheet1 - X9
|
|
sb.Append(";"); sb.Append(Program.LocalSettings.RealDensity);
|
|
sb.Append(";"); sb.Append(Program.LocalSettings.AtTemperature);
|
|
sb.Append(";"); sb.Append(" "); /// pipe expansion: teraz vynechat
|
|
sb.Append(";"); sb.Append(tstRslt.FlowMass); /// Qm [kg/h]
|
|
sb.Append(";"); sb.Append(tstRslt.FlowVolume); /// Qv [l/h]
|
|
sb.Append(";"); sb.Append(tstRslt.VolumeCTV); /// Vet . . . komercne prava hodnota - podla vahy
|
|
sb.Append(";"); sb.Append(tstRslt.VolumeMaster); /// Velm . . . . objem podla etalonu
|
|
sb.Append(";"); sb.Append(" "); /// Vmass . . . objem podla druheho etalonu / prietokomeru pred tratou (teraz vynechavame)
|
|
sb.Append(";"); sb.Append(tstRslt.TestTime); /// t
|
|
sb.Append(";"); sb.Append(tstRslt.ErrorMaster); /// Eelm . . . chyba etalonu voci komercne pravej hodnote
|
|
sb.Append(";"); sb.Append(" "); /// Emass . . . chyba druheho etalonu voci komercne pravej hodnote (teraz vynechavame)
|
|
sb.Append(";"); if (outPath.FlowMeter != null && outPath.FlowMeter.LtrPerPulse != 0)
|
|
{
|
|
sb.Append(1.0f / outPath.FlowMeter.LtrPerPulse); /// Const.MID . konstanta eatlonu
|
|
}
|
|
sb.Append(";"); sb.Append(" "); /// Const.MA . . konstanta druheho etalonu
|
|
sb.Append(";"); sb.Append("0"); /// Time Div Start celkovy cas v [ms]
|
|
sb.Append(";"); sb.Append("0"); /// Time Div Start1
|
|
sb.Append(";"); sb.Append("0"); /// Time Div Start2
|
|
sb.Append(";"); sb.Append("0"); /// Time Div Start3
|
|
sb.Append(";"); sb.Append("0"); /// Time Div Start4
|
|
sb.Append(";"); sb.Append("0"); /// Time Div Start5
|
|
sb.Append(";"); sb.Append("0"); /// Time Div End celkovy cas v [ms]
|
|
sb.Append(";"); sb.Append("0"); /// Time Div End1
|
|
sb.Append(";"); sb.Append("0"); /// Time Div End2
|
|
sb.Append(";"); sb.Append("0"); /// Time Div End3
|
|
sb.Append(";"); sb.Append("0"); /// Time Div End4
|
|
sb.Append(";"); sb.Append("0"); /// Time Div End5
|
|
sb.Append(";"); sb.Append(tstRslt.PulsesMaster); /// Celkovy pocet et. pulzov skusky
|
|
sb.Append(";"); sb.Append(" "); /// - '' - pre druhy
|
|
for (int i = 0; i < ProcessData.BatchRslts.WMPositionsCount; i++)
|
|
{
|
|
if (ProcessData.BatchRslts.WaterMeters[i] != null)
|
|
{
|
|
if (!ProcessData.BatchRslts.WaterMeters[i].Compound())
|
|
{
|
|
Results.Entities.MeterTestRslt mtrRslt = ProcessData.BatchRslts.GetMeterTestRslt(tstRslt.Name(), i, CompoundMeterId.Single);
|
|
|
|
if (mtrRslt != null)
|
|
{
|
|
sb.Append(";"); sb.Append(ProcessData.BatchRslts.WaterMeters[i].SerialNr); /// WM Ser.No.
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeStart); /// WM Vstart - pociatocny stav pri pevnom starte alebo zachyteny pri data streame
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeEnd); /// WM Vend - konecny stav pri pevnom starte alebo zachyteny pri data streame
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeMeter); /// WM Vmer - objem namerany vodomerom
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeRef); /// WM Vref - objem namerany stanicou
|
|
sb.Append(";"); sb.Append(mtrRslt.Error); /// WM Emt - chyba vodomerom nameraneho objemu
|
|
#if IPERLST || IPERLST_SPECIAL
|
|
sb.Append(";"); sb.Append(ProcessData.BatchRslts.WaterMeters[i].CalibFactor); /// iPerl calibration factor used during the test / ...
|
|
#else
|
|
sb.Append(";"); sb.Append(" "); /// nechat prazdne
|
|
#endif
|
|
sb.Append(";"); sb.Append(mtrRslt.PulsesMeter); /// WM Np met - pocet impulzov zo skusaneho meradla
|
|
sb.Append(";"); sb.Append(mtrRslt.PulsesMaster); /// WM Np elm - pocet impulzov etalonu pocas merania pre prislusny vodomer
|
|
sb.Append(";"); sb.Append(mtrRslt.TestTime); /// WM Tmet - cas merania (obmedzany pri synchro skuske)
|
|
sb.Append(";"); sb.Append(mtrRslt.Passed ? "OK" : "NOK"); /// WM Vysledok (t.j. ci je v hraniciach chyb) - OK/NOK
|
|
#if IPERLST || IPERLST_SPECIAL
|
|
sb.Append(";"); sb.Append(mtrRslt.WaterMeter.Q2Correction.ToString("F1")); /// iPerl Q2 correction factor used during the test / AN value - hodnota z analogoveho prevodnika
|
|
#else
|
|
sb.Append(";"); sb.Append(" "); /// nechat prazdne
|
|
#endif
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeStart); /// WM Volume_start - pri datastreamovych hodnotach (alebo kamera)
|
|
sb.Append(";"); sb.Append(mtrRslt.TimestampStart); /// WM Time_start - ' ' -
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeEnd); /// WM Volume_end - ' ' -
|
|
sb.Append(";"); sb.Append(mtrRslt.TimestampEnd); /// WM Time_end - ' ' -
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (byte b = (byte)CompoundMeterId.CompoundMain; b <= (byte)CompoundMeterId.Compound; b++)
|
|
{
|
|
Results.Entities.MeterTestRslt mtrRslt = ProcessData.BatchRslts.GetMeterTestRslt(tstRslt.Name(), i, (CompoundMeterId)b);
|
|
|
|
if (mtrRslt != null)
|
|
{
|
|
sb.Append(";");
|
|
switch ((CompoundMeterId)b)
|
|
{
|
|
case CompoundMeterId.CompoundMain:
|
|
sb.Append(ProcessData.BatchRslts.WaterMeters[i].SerialNr);
|
|
break;
|
|
case CompoundMeterId.CompoundAux:
|
|
sb.Append(ProcessData.BatchRslts.WaterMeters[i].SerialNrAux);
|
|
break;
|
|
case CompoundMeterId.Compound:
|
|
sb.Append(ProcessData.BatchRslts.WaterMeters[i].SerialNr);
|
|
break;
|
|
}
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeStart); /// WM Vinit - pri pevnom starte pociatocny stav natukany alebo cez inteligentny system
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeEnd); /// WM Vfin - pri pevnom starte konecny stav natukany alebo cez inteligentny system
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeMeter); /// WM Vmer - objem namerany vodomerom
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeRef); /// WM Vet - objem namerany stanicou
|
|
sb.Append(";"); sb.Append(mtrRslt.Error); /// WM Emt - chyba vodomerom nameraneho objemu
|
|
sb.Append(";"); sb.Append(" "); /// WM U - neistota (zatial nechat prazdne)
|
|
sb.Append(";"); sb.Append(mtrRslt.PulsesMeter); /// WM Np met - pocet impulzov zo skusaneho meradla
|
|
sb.Append(";"); sb.Append(mtrRslt.PulsesMaster); /// WM Np elm - pocet impulzov etalonu pocas merania pre prislusny vodomer
|
|
sb.Append(";"); sb.Append(mtrRslt.TestTime); /// WM Tmet - cas merania (obmedzany pri synchro skuske)
|
|
sb.Append(";"); sb.Append(mtrRslt.Passed ? "OK" : "NOK"); /// WM Vysledok (t.j. ci je v hraniciach chyb) - OK/NOK
|
|
sb.Append(";"); sb.Append(" "); /// WM AN value - hodnota z analogoveho prevodnika (teraz nic)
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeStart); /// WM Volume_start - pri datastreamovych hodnotach (alebo kamera)
|
|
sb.Append(";"); sb.Append(mtrRslt.TimestampStart); /// WM Time_start - ' ' -
|
|
sb.Append(";"); sb.Append(mtrRslt.VolumeEnd); /// WM Volume_end - ' ' -
|
|
sb.Append(";"); sb.Append(mtrRslt.TimestampEnd); /// WM Time_end - ' ' -
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sb.Append(";");
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Create a simulated test result (single meter).
|
|
/// </summary>
|
|
/// <param name="test">Test to be simulated</param>
|
|
/// <returns>Test result</returns>
|
|
protected void MakeSimulated(string testName, int repeats, int repetitionNr, int part, float errorPctBase)
|
|
{
|
|
string fullTestName = Results.Utils.GetTestName(testName, repeats, repetitionNr);
|
|
|
|
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(fullTestName, part);
|
|
|
|
tstRslt.StartTime = DateTime.Now;
|
|
tstRslt.EndTime = DateTime.Now;
|
|
tstRslt.FlowSetTime = 10;
|
|
tstRslt.TestTime = tstRslt.TargetTime();
|
|
/// TODO: Verify whether 'ltrPerRefPulse' is up to date
|
|
tstRslt.PulsesMaster = (LtrPerRefPulse > 1E-6) ? (tstRslt.TargetVolume() / LtrPerRefPulse) : 1;
|
|
tstRslt.ConstMaster = LtrPerRefPulse;
|
|
tstRslt.MassStartRaw = 0;
|
|
tstRslt.MassStart = 0;
|
|
tstRslt.MassEndRaw = tstRslt.TargetVolume() * Program.LocalSettings.RealDensity / 1000.0f;
|
|
tstRslt.MassEnd = tstRslt.MassEndRaw;
|
|
tstRslt.DensityIn = Program.LocalSettings.RealDensity;
|
|
tstRslt.DensityOut = Program.LocalSettings.RealDensity;
|
|
tstRslt.DensityDiv = Program.LocalSettings.RealDensity;
|
|
tstRslt.Buoyancy = 0; /// TODO
|
|
tstRslt.FlowMass = 3600.0 * tstRslt.MassEnd / tstRslt.TargetTime();
|
|
tstRslt.FlowVolume = 3.6 * tstRslt.TargetVolume() / tstRslt.TargetTime();
|
|
tstRslt.VolumeCTV = tstRslt.TargetVolume();
|
|
tstRslt.VolumeMaster = tstRslt.TargetVolume();
|
|
tstRslt.ErrorMaster = 0;
|
|
|
|
tstRslt.AmbientTempAve = 20.0f;
|
|
tstRslt.AmbientPressAve = 1000.0f;
|
|
tstRslt.AmbientHumiAve = 50.0f;
|
|
|
|
tstRslt.PressUpStart = 1000.0f;
|
|
tstRslt.PressDownStart = 1000.0f;
|
|
tstRslt.TempInStart = 20.0f;
|
|
tstRslt.TempOutStart = 20.0f;
|
|
tstRslt.TempDivStart = 20.0f;
|
|
tstRslt.PressUpEnd = 1000.0f;
|
|
tstRslt.PressDownEnd = 1000.0f;
|
|
tstRslt.TempInEnd = 20.0f;
|
|
tstRslt.TempOutEnd = 20.0f;
|
|
tstRslt.TempDivEnd = 20.0f;
|
|
tstRslt.PressUpAvrg = 1000.0f;
|
|
tstRslt.PressDownAvrg = 1000.0f;
|
|
tstRslt.TempInAvrg = 20.0f;
|
|
tstRslt.TempOutAvrg = 20.0f;
|
|
tstRslt.TempDivAvrg = 20.0f;
|
|
tstRslt.PressUpMin = 1000.0f;
|
|
tstRslt.PressDownMin = 1000.0f;
|
|
tstRslt.TempInMin = 20.0f;
|
|
tstRslt.TempOutMin = 20.0f;
|
|
tstRslt.TempDivMin = 20.0f;
|
|
tstRslt.PressUpMax = 1000.0f;
|
|
tstRslt.PressDownMax = 1000.0f;
|
|
tstRslt.TempInMax = 20.0f;
|
|
tstRslt.TempOutMax = 20.0f;
|
|
tstRslt.TempDivMax = 20.0f;
|
|
|
|
tstRslt.FlowMin = 0; /// TODO
|
|
tstRslt.FlowMax = 0; /// TODO
|
|
|
|
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
|
|
{
|
|
float errorPct = errorPctBase + 0.05f * i;
|
|
|
|
Results.Entities.MeterTestRslt meterRslt = ProcessData.BatchRslts.GetMeterTestRslt(fullTestName, i, CompoundMeterId.Single);
|
|
IRegisterReader regReader = sensPath.RegisterReaders[i];
|
|
|
|
if (meterRslt != null && regReader != null)
|
|
{
|
|
meterRslt.VolumeMeter = tstRslt.TargetVolume() * (1.0 + 0.01 * errorPct);
|
|
|
|
meterRslt.PulsesMeter = regReader.PulsesPerLtr * meterRslt.VolumeMeter;
|
|
meterRslt.PulsesMaster = tstRslt.PulsesMaster;
|
|
meterRslt.PulsesPerLiter = regReader.PulsesPerLtr;
|
|
meterRslt.VolumeStart = 0;
|
|
meterRslt.VolumeEnd = meterRslt.VolumeMeter;
|
|
meterRslt.VolumeRef = tstRslt.TargetVolume();
|
|
meterRslt.TimestampStart = 0;
|
|
meterRslt.TimestampEnd = tstRslt.TargetTime();
|
|
meterRslt.TestTime = tstRslt.TargetTime();
|
|
meterRslt.Error = errorPct;
|
|
meterRslt.Passed = (errorPct >= tstRslt.ErrLimLo() + tstRslt.Uncertainty())
|
|
&& (errorPct <= tstRslt.ErrLimHi() - tstRslt.Uncertainty());
|
|
meterRslt.TestDone = true;
|
|
}
|
|
}
|
|
|
|
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.Balance != null ? outPath.Balance.Name : string.Empty,
|
|
outPath.RegulValve != null ? outPath.RegulValve.Name : string.Empty,
|
|
outPath.Diverter != null ? outPath.Diverter.Name : string.Empty));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Create a simulated test result (compound meter).
|
|
/// </summary>
|
|
/// <param name="test">Test to be simulated</param>
|
|
/// <returns>Test result</returns>
|
|
protected void MakeSimulatedCompound(string testName, int repeats, int repetitionNr, int part, float errorPct, float mainPart)
|
|
{
|
|
string fullTestName = Results.Utils.GetTestName(testName, repeats, repetitionNr);
|
|
|
|
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(fullTestName, part);
|
|
|
|
tstRslt.StartTime = DateTime.Now;
|
|
tstRslt.EndTime = DateTime.Now;
|
|
tstRslt.FlowSetTime = 10;
|
|
tstRslt.TestTime = tstRslt.TargetTime();
|
|
/// TODO: Verify whether 'ltrPerRefPulse' is up to date
|
|
tstRslt.PulsesMaster = (LtrPerRefPulse > 1E-6) ? (tstRslt.TargetVolume() / LtrPerRefPulse) : 1;
|
|
tstRslt.ConstMaster = LtrPerRefPulse;
|
|
tstRslt.MassStartRaw = 0;
|
|
tstRslt.MassStart = 0;
|
|
tstRslt.MassEndRaw = tstRslt.TargetVolume() * Program.LocalSettings.RealDensity / 1000.0f;
|
|
tstRslt.MassEnd = tstRslt.MassEndRaw;
|
|
tstRslt.DensityIn = Program.LocalSettings.RealDensity;
|
|
tstRslt.DensityOut = Program.LocalSettings.RealDensity;
|
|
tstRslt.DensityDiv = Program.LocalSettings.RealDensity;
|
|
tstRslt.Buoyancy = 0; /// TODO
|
|
tstRslt.FlowMass = tstRslt.MassEnd / tstRslt.TargetTime();
|
|
tstRslt.FlowVolume = tstRslt.TargetVolume() / tstRslt.TargetTime();
|
|
tstRslt.VolumeCTV = tstRslt.TargetVolume();
|
|
tstRslt.VolumeMaster = tstRslt.TargetVolume();
|
|
tstRslt.ErrorMaster = 0;
|
|
|
|
tstRslt.AmbientTempAve = 20.0f;
|
|
tstRslt.AmbientPressAve = 1000.0f;
|
|
tstRslt.AmbientHumiAve = 50.0f;
|
|
|
|
tstRslt.PressUpStart = 1000.0f;
|
|
tstRslt.PressDownStart = 1000.0f;
|
|
tstRslt.TempInStart = 20.0f;
|
|
tstRslt.TempOutStart = 20.0f;
|
|
tstRslt.TempDivStart = 20.0f;
|
|
tstRslt.PressUpEnd = 1000.0f;
|
|
tstRslt.PressDownEnd = 1000.0f;
|
|
tstRslt.TempInEnd = 20.0f;
|
|
tstRslt.TempOutEnd = 20.0f;
|
|
tstRslt.TempDivEnd = 20.0f;
|
|
tstRslt.PressUpAvrg = 1000.0f;
|
|
tstRslt.PressDownAvrg = 1000.0f;
|
|
tstRslt.TempInAvrg = 20.0f;
|
|
tstRslt.TempOutAvrg = 20.0f;
|
|
tstRslt.TempDivAvrg = 20.0f;
|
|
tstRslt.PressUpMin = 1000.0f;
|
|
tstRslt.PressDownMin = 1000.0f;
|
|
tstRslt.TempInMin = 20.0f;
|
|
tstRslt.TempOutMin = 20.0f;
|
|
tstRslt.TempDivMin = 20.0f;
|
|
tstRslt.PressUpMax = 1000.0f;
|
|
tstRslt.PressDownMax = 1000.0f;
|
|
tstRslt.TempInMax = 20.0f;
|
|
tstRslt.TempOutMax = 20.0f;
|
|
tstRslt.TempDivMax = 20.0f;
|
|
|
|
tstRslt.FlowMin = 0; /// TODO
|
|
tstRslt.FlowMax = 0; /// TODO
|
|
|
|
|
|
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
|
|
{
|
|
Results.Entities.MeterTestRslt compoundRslt = ProcessData.BatchRslts.GetMeterTestRslt(fullTestName, i, CompoundMeterId.Compound);
|
|
Results.Entities.MeterTestRslt mainRslt = ProcessData.BatchRslts.GetMeterTestRslt(fullTestName, i, CompoundMeterId.CompoundMain);
|
|
Results.Entities.MeterTestRslt auxRslt = ProcessData.BatchRslts.GetMeterTestRslt(fullTestName, i, CompoundMeterId.CompoundAux);
|
|
|
|
double compoundVolume = tstRslt.TargetVolume() * (1.0 + 0.01 * errorPct);
|
|
double mainVolume = compoundVolume * mainPart;
|
|
double auxVolume = compoundVolume * (1.0 - mainPart);
|
|
|
|
for (int isAux = 0; isAux <= 1; isAux++) /// 0=main, 1=aux
|
|
{
|
|
GenericDevices.IRegisterReader regReader = sensPath.RegisterReaders[2 * i + isAux];
|
|
Results.Entities.MeterTestRslt meterRslt = (isAux == 0) ? mainRslt : auxRslt;
|
|
|
|
if (meterRslt != null && regReader != null)
|
|
{
|
|
meterRslt.VolumeMeter = (isAux == 0) ? mainVolume : auxVolume;
|
|
|
|
meterRslt.PulsesMeter = regReader.PulsesPerLtr * meterRslt.VolumeMeter;
|
|
meterRslt.PulsesMaster = tstRslt.PulsesMaster;
|
|
meterRslt.PulsesPerLiter = regReader.PulsesPerLtr;
|
|
meterRslt.VolumeStart = 0;
|
|
meterRslt.VolumeEnd = meterRslt.VolumeMeter;
|
|
meterRslt.VolumeRef = tstRslt.TargetVolume();
|
|
meterRslt.TimestampStart = 0;
|
|
meterRslt.TimestampEnd = tstRslt.TargetTime();
|
|
meterRslt.TestTime = tstRslt.TargetTime();
|
|
meterRslt.Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, tstRslt.VolumeCTV);
|
|
meterRslt.Passed = (errorPct >= tstRslt.ErrLimLo() + tstRslt.Uncertainty())
|
|
&& (errorPct <= tstRslt.ErrLimHi() - tstRslt.Uncertainty());
|
|
meterRslt.TestDone = true;
|
|
}
|
|
}
|
|
|
|
compoundRslt.VolumeRef = tstRslt.VolumeCTV; /// [l] must be calculated before main & aux. meter error
|
|
compoundRslt.VolumeMeter = mainRslt.VolumeMeter + auxRslt.VolumeMeter;
|
|
|
|
compoundRslt.PulsesMaster = tstRslt.PulsesMaster;
|
|
compoundRslt.TestTime = tstRslt.TargetTime();
|
|
compoundRslt.Error = Formulas.ErrorFromVolumes(compoundRslt.VolumeMeter, tstRslt.VolumeCTV);
|
|
compoundRslt.Passed = (compoundRslt.Error >= tstRslt.ErrLimLo() + tstRslt.Uncertainty())
|
|
&& (compoundRslt.Error <= tstRslt.ErrLimHi() - tstRslt.Uncertainty());
|
|
compoundRslt.TestDone = true;
|
|
}
|
|
|
|
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.Balance != null ? outPath.Balance.Name : string.Empty,
|
|
outPath.RegulValve != null ? outPath.RegulValve.Name : string.Empty,
|
|
outPath.Diverter != null ? outPath.Diverter.Name : string.Empty));
|
|
}
|
|
|
|
protected bool TestAndLogUiCmdStop(IList<Event> e)
|
|
{
|
|
return TestAndLogUiCmdStop(null, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true and makes a log when 'e' contains Event.UiCmdStop
|
|
/// </summary>
|
|
/// <param name="test"></param>
|
|
/// <param name="e"></param>
|
|
/// <returns></returns>
|
|
protected bool TestAndLogUiCmdStop(Test test, IList<Event> e)
|
|
{
|
|
if (!e.Contains(Event.UiCmdStop)) return false;
|
|
|
|
log.FatalFormat("STOP pressed: Procedure={0}, Test={1}, State={2}",
|
|
(StateMachine.Procedure == null) ? "?" : StateMachine.Procedure.Name,
|
|
(test == null) ? "?" : test.Name,
|
|
State.CurrentState.Name);
|
|
|
|
if (test != null)
|
|
{
|
|
log.FatalFormat("Process values:");
|
|
log.FatalFormat(" Method: {0}", test.Method);
|
|
log.FatalFormat(" Test start time: {0}", TestStartTime.ToShortTimeString());
|
|
log.FatalFormat(" Feeding path: {0}", (inPath != null) ? inPath.ToString() : "none");
|
|
log.FatalFormat(" Bench path: {0}", (benchPath != null) ? benchPath.ToString() : "none");
|
|
log.FatalFormat(" Output path: {0}", (outPath != null) ? outPath.ToString() : "none");
|
|
if (inPath.Pump is IPump) log.FatalFormat(" Pump power: {0}%", (inPath.Pump as IPump).Power);
|
|
else if (inPath.Pump is IValve) log.FatalFormat(" Feeding valve: {0}", (inPath.Pump as IValve).State ? "open" : "close");
|
|
if (outPath.RegulValve is IRegulValve) log.FatalFormat(" Regulation valve position: {0}%", outPath.RegulValve.Position);
|
|
log.FatalFormat(" Flow: {0}", RefFlow);
|
|
log.FatalFormat(" Mass: {0}", Mass);
|
|
log.FatalFormat(" Start mass: {0}", StartMass);
|
|
log.FatalFormat(" Liter/ref.pulse: {0}", LtrPerRefPulse);
|
|
log.FatalFormat(" Reference pulses: {0}", RefPulses);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|