tbf/TBF/Rig/Sequences/MainSeqUtils.cs

872 lines
42 KiB
C#
Raw Normal View History

///
/// Copyright (c) 2020-2023 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Common;
using Config.Entities;
2021-10-26 09:23:57 +00:00
using TBF.Rig.GenericDevices;
using TBF.Rig.Operations;
using TBF.Boxes;
using TBF.Resources;
using TBF.UiBridge;
using Results.Entities;
2021-10-26 09:23:57 +00:00
namespace TBF.Rig.Sequences
{
partial class MainSeq
{
/// <summary>
/// Wrapper
/// </summary>
IList<string> ServeCalendarEventsInvokeXY(Config.CalendarEvent.AutoAction selectedAction, int maxCount = 1)
{
return TBF.UI.Calendar.CalendarTabPageCtrl.ServeCalendarEventsInvokeXY(selectedAction, maxCount);
}
/// <summary>
/// Unconditionally wait for OK button
/// </summary>
void WaitForOkButton()
{
State.Create("MainSeq : Press OK to start the system")
2021-10-26 09:23:57 +00:00
.AddOperation(new Rig.Operations.MessageBoxOp(Strings.Start_the_test_bench, System.Drawing.Color.OliveDrab))
.EnterState();
while (!StateMachine.WaitRunDevsRunOps().Contains(Event.OK)) { }
}
/// <summary>
/// Unconditionally set valves to default position
/// </summary>
void SetValvesToDefaultState()
{
State.Create("MainSeq : Setting valves to default positions")
.AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose))
.EnterState();
while (StateMachine.WaitRunDevsRunOps().Contains(Event.ValvesBusy)) { }
}
/// <summary>
/// Test communication with all scales that support S/N read operation
/// </summary>
/// <param name="scaleName">Name of a scale that failed</param>
/// <param name="message">Message in case of a failure</param>
/// <returns>true = Test passed, all scales communicate OK</returns>
bool TestCommunicationWithScales(out string scaleName, out string message)
{
///
/// Read S/N-s from scales (cannot be stopped, but is limitted to Scales count x 3s (=timeout)
///
IScaleOrTank[] tanks = new IScaleOrTank[] { StateMachine.Tank1, StateMachine.Tank2, StateMachine.Tank3 };
foreach (var tank in tanks)
{
if (tank is IScale)
{
IScale scale = tank as IScale;
string sn = string.Empty;
IOperation getSNOp = scale.GetSerNumOp(ref sn);
if (getSNOp != null)
{
const int nrRetries = 3;
for (int i = 1; i <= nrRetries; i++)
{
IList<Event> e;
bool error = false;
bool timeout = false;
State.Create(string.Format("MainSeq : Reading S/N of scale {0} trial {1}", scale.Name, i))
.AddOperation(getSNOp)
.AddOperation(new Operations.TimerOp(2))
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error))
{
if (i == nrRetries)
{
///
/// All retries completed => the scale failed
///
scaleName = scale.Name;
message = Strings.Scale_communication_error;
return false;
}
else
{
/// The scale failed => try one more time
error = true;
break;
}
}
if (e.Contains(Event.Busy) && e.Contains(Event.TimerExpired))
{
if (i == nrRetries)
{
///
/// All retries completed, the scale failed
///
scaleName = scale.Name;
message = Strings.Scale_communication_timeout;
return false;
}
else
{
/// The scale failed => try one more time
timeout = true;
break;
}
}
}
while (e.Contains(Event.Busy));
if (!error && !timeout)
{
/// This scale communicates OK, break "for (int i = ... " loop
if (!string.IsNullOrEmpty(sn)) log.WarnFormat("Scale {0} : s/n = {1}", scale.Name, sn);
break; ///
}
/// Wait one state machine tick (1 second), kreep retrying, stay inside "for (int i = ... " loop
State.Create(string.Format("MainSeq : Reading S/N of scale {0}", scale.Name)).EnterState();
StateMachine.WaitRunDevsRunOps();
}
}
}
}
///
/// All scales communicate OK, test passed
///
scaleName = string.Empty;
message = string.Empty;
return true;
}
/// <summary>
///
/// </summary>
/// <returns>true = OK, false = error</returns>
bool DrainTanks()
{
IList<Event> e;
///
/// Enable stop draining buttons
///
Bridge.Bench2UI(((StateMachine.DrainValve1 != null) ? ButtonsEtc.DrainTankBtn1Hi : 0) |
((StateMachine.DrainValve2 != null) ? ButtonsEtc.DrainTankBtn2Hi : 0) |
((StateMachine.DrainValve3 != null) ? ButtonsEtc.DrainTankBtn3Hi : 0));
///
/// Determine lists of drain valves and drain times (max. of all tank drain times)
///
IList<IValve> fullDrainValves = new List<IValve>();
IList<IValve> secondHalfDrainValves = new List<IValve>();
IList<IValve> allDrainValves = new List<IValve>();
int totalDrainTime = 0;
int maxDrainTimeFor2VlvTanks = 0;
bool areTwoDrainPhases = false;
foreach (IScaleOrTank tank in new IScaleOrTank[] { StateMachine.Tank1, StateMachine.Tank2, StateMachine.Tank3 })
{
if (tank != null && tank.DrainValve != null)
{
if (tank.EmptyTimeSec > totalDrainTime) totalDrainTime = tank.EmptyTimeSec;
if (tank.DrainValve2 != null)
{
areTwoDrainPhases = true;
if (tank.EmptyTimeSec > maxDrainTimeFor2VlvTanks) maxDrainTimeFor2VlvTanks = tank.EmptyTimeSec;
if (!secondHalfDrainValves.Contains(tank.DrainValve)) secondHalfDrainValves.Add(tank.DrainValve);
if (!fullDrainValves.Contains(tank.DrainValve2)) fullDrainValves.Add(tank.DrainValve2);
if (!allDrainValves.Contains(tank.DrainValve)) allDrainValves.Add(tank.DrainValve);
if (!allDrainValves.Contains(tank.DrainValve2)) allDrainValves.Add(tank.DrainValve2);
}
else
{
if (!fullDrainValves.Contains(tank.DrainValve)) fullDrainValves.Add(tank.DrainValve);
if (!allDrainValves.Contains(tank.DrainValve)) allDrainValves.Add(tank.DrainValve);
}
}
}
///
/// Drain the tanks, two phases if necessary
///
if (totalDrainTime > 0)
{
IntBox timerTime = new IntBox(); /// Contains remaining time in each phase
int firstPhaseTime = maxDrainTimeFor2VlvTanks / 2;
State.Create(areTwoDrainPhases ? "MainSeq : Drain tanks - phase 1" : "MainSeq : Drain tanks")
.AddOperation(checkUiOp)
.AddOperation(new TimerOp(areTwoDrainPhases ? firstPhaseTime : totalDrainTime, timerTime))
.AddOperation(StateMachine.ControlBoard.SetValvesOp(fullDrainValves, null))
.EnterState();
do
{
int remTime = areTwoDrainPhases ? (timerTime.Val + totalDrainTime - firstPhaseTime) : timerTime.Val;
Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remTime / 60, "min", remTime % 60, Strings.sec));
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) return false;
bool stopDrainingCmd = e.Contains(Event.UiCmdStopDrainingTank1) || e.Contains(Event.UiCmdStopDrainingTank2) || e.Contains(Event.UiCmdStopDrainingTank3);
if (stopDrainingCmd && !e.Contains(Event.ValvesBusy) && !e.Contains(Event.CameraBusy)) break;
}
while (e.Contains(Event.TimerBusy) || e.Contains(Event.CameraBusy) || e.Contains(Event.ValvesBusy));
if (areTwoDrainPhases)
{
State.Create("MainSeq : Drain tanks - phase 2")
.AddOperation(checkUiOp)
.AddOperation(new TimerOp(totalDrainTime - firstPhaseTime, timerTime))
.AddOperation(StateMachine.ControlBoard.SetValvesOp(secondHalfDrainValves, null))
.EnterState();
do
{
int remTime = timerTime.Val;
Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remTime / 60, "min", remTime % 60, Strings.sec));
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) return false;
bool stopDrainingCmd = e.Contains(Event.UiCmdStopDrainingTank1) || e.Contains(Event.UiCmdStopDrainingTank2) || e.Contains(Event.UiCmdStopDrainingTank3);
if (stopDrainingCmd && !e.Contains(Event.ValvesBusy) && !e.Contains(Event.CameraBusy)) break;
}
while (e.Contains(Event.TimerBusy) || e.Contains(Event.CameraBusy) || e.Contains(Event.ValvesBusy));
}
Bridge.OnActivity(this, Strings.Emptying_tank);
State stopDraining = State.Create("MainSeq : Stop draining water tanks")
.AddOperation(checkUiOp)
.AddOperation(StateMachine.ControlBoard.SetValvesOp(null, allDrainValves))
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) return false;
}
while (e.Contains(Event.ValvesBusy));
}
return true; /// OK
}
/// <summary>
/// This function is called after a procedure was selected and all components procedure parameters of components were loaded
/// </summary>
void ClearSessionData()
{
///
/// Clear iperlhead data (including PCB Number, avoid double use)
///
foreach (var cmpnt in StateMachine.Components)
{
if (cmpnt is ISessionDataMngmnt) (cmpnt as ISessionDataMngmnt).StartSession();
}
DataEntry.DEItem.ClearSummaryColumns();
IsQ2PreCorrectionCalculated = false;
CalculatedQ2PreCorrectionLR = 0;
CalculatedQ2PreCorrectionRL = 0;
}
/// <summary>
/// Idle loop to make a procedure or test selection.
/// Handles tank emptying, camera test.
/// </summary>
/// <param name="context">Context where MakeSelection() is called</param>
/// <returns>
/// Selection.PurgeBegin, PurgeEnd, Break, Cycle, Test, Q1, Q2, Q3 or SaveResults
/// </returns>
Selection MakeSelection(MKSelContext context)
{
log.WarnFormat("MakeSelection({0})", context);
bool restoreIntrptdSessionEnabled = (context == MKSelContext.ProcedureNotSelected) && File.Exists(ProcessData.PDataFileName);
/// Tank emptying valves states
bool draining1 = false;
bool draining2 = false;
bool draining3 = false;
/// Measured masses to control emptying
DoubleBox mass1 = new DoubleBox();
DoubleBox mass2 = new DoubleBox();
DoubleBox mass3 = new DoubleBox();
IList<Event> e;
while (true)
{
bool draining = draining1 || draining2 || draining3;
///
/// Activity message
///
Bridge.OnActivity(this, draining ? Strings.Emptying_tank
: ((context == MKSelContext.ProcedureNotSelected) ? Strings.Please_select_a_procedure
: Strings.Please_select_a_cycle_a_test_or_empty));
bool saveResultsActive = (context == MKSelContext.InsideProcedure)
&& (StateMachine.Procedure != null)
&& (!StateMachine.Procedure.MustBeComplete || BatchRslts.AllTestsDone());
/// Enable appropriate UI controls and buttons
Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) |
ButtonsEtc.TestCmbBoxEn |
((context == MKSelContext.InsideProcedure) ? ButtonsEtc.Break : 0) |
(restoreIntrptdSessionEnabled ? ButtonsEtc.RestoreSession : 0) |
(saveResultsActive ? ButtonsEtc.AcceptResultsBtnEn : 0) |
(draining ? 0 : ButtonsEtc.StartCycleBtnEn) |
(draining ? 0 : ButtonsEtc.StartTestBtnsEn) |
(draining ? 0 : ButtonsEtc.PurgeBeginBtnEn) |
(draining ? 0 : ((context == MKSelContext.InsideProcedure) ? ButtonsEtc.PurgeEndBtnEn : 0)) |
((StateMachine.DrainValve1 == null) ? 0 : (draining1 ? ButtonsEtc.DrainTankBtn1Hi : ButtonsEtc.DrainTankBtn1En)) |
((StateMachine.DrainValve2 == null) ? 0 : (draining2 ? ButtonsEtc.DrainTankBtn2Hi : ButtonsEtc.DrainTankBtn2En)) |
((StateMachine.DrainValve3 == null) ? 0 : (draining3 ? ButtonsEtc.DrainTankBtn3Hi : ButtonsEtc.DrainTankBtn3En)));
State.Create("MainSeq : Select an activity")
.AddOperation(checkUiOp)
.AddOperation(StateMachine.BenchWaitingOp)
.AddOperation((StateMachine.Tank1 is IScale) ? (StateMachine.Tank1 as IScale).ReadMassOp(ref mass1) : null)
.AddOperation((StateMachine.Tank2 is IScale) ? (StateMachine.Tank2 as IScale).ReadMassOp(ref mass2) : null)
.AddOperation((StateMachine.Tank3 is IScale) ? (StateMachine.Tank3 as IScale).ReadMassOp(ref mass3) : null)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
/// Handled inside MakeSelection() inside the selection loop
if (e.Contains(Event.Error)) break;
if (!draining1 && e.Contains(Event.UiCmdDrainTank1)) break;
if (!draining2 && e.Contains(Event.UiCmdDrainTank2)) break;
if (!draining3 && e.Contains(Event.UiCmdDrainTank3)) break;
if (draining1 && e.Contains(Event.UiCmdStopDrainingTank1)) break;
if (draining2 && e.Contains(Event.UiCmdStopDrainingTank2)) break;
if (draining3 && e.Contains(Event.UiCmdStopDrainingTank3)) break;
if (draining1 && StateMachine.Tank1.IsEmpty()) break;
if (draining2 && StateMachine.Tank2.IsEmpty()) break;
if (draining3 && StateMachine.Tank3.IsEmpty()) break;
/// Quit the selection loop and leave MakeSelection()
if (e.Contains(Event.UiCmdShutdown)) return Selection.Shutdown;
if (context == MKSelContext.InsideProcedure
&& e.Contains(Event.UiCmdBreak)) return Selection.Break;
if (e.Contains(Event.UiCmdPurgeBegin)) return Selection.PurgeBegin;
if (e.Contains(Event.UiCmdPurgeEnd)) return Selection.PurgeEnd;
if (e.Contains(Event.UiCmdStartCycle)) return Selection.Cycle;
if (e.Contains(Event.UiCmdStartTest)) return Selection.Test;
if (e.Contains(Event.UiCmdStartQ1)) return Selection.Q1;
if (e.Contains(Event.UiCmdStartQ2)) return Selection.Q2;
if (e.Contains(Event.UiCmdStartQ3)) return Selection.Q3;
if (e.Contains(Event.UiCmdAcceptResults)) return Selection.SaveResults;
if (e.Contains(Event.UiCmdReloadBatch)) return Selection.RestoreBatch;
if (e.Contains(Event.UiCmdReloadAndFixBatch)) return Selection.RestoreAndFixBatch;
if (restoreIntrptdSessionEnabled
&& e.Contains(Event.UiCmdRestoreSession)) return Selection.RestoreInterruptedSession;
}
while (true);
if (e.Contains(Event.Error))
{
///------------------------------------
Bridge.OnActivity(this, Strings.Error);
///------------------------------------
State.Create("MainSeq : ERROR state")
.AddOperation(checkUiOp)
.AddOperation(StateMachine.BenchErrorOp)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
}
while (!e.Contains(Event.UiCmdShutdown));
return Selection.Shutdown;
}
else
{
string stateText = "MainSeq : ";
IList<IValve> openValves = new List<IValve>();
IList<IValve> closeValves = new List<IValve>();
if (draining1 && (StateMachine.Tank1.IsEmpty() || e.Contains(Event.UiCmdStopDrainingTank1)))
{
draining1 = false;
closeValves.Add(StateMachine.DrainValve1);
stateText = stateText + "close tank 1, ";
}
else if (draining2 && (StateMachine.Tank2.IsEmpty() || e.Contains(Event.UiCmdStopDrainingTank2)))
{
draining2 = false;
closeValves.Add(StateMachine.DrainValve2);
stateText = stateText + "close tank 2, ";
}
else if (draining3 && (StateMachine.Tank3.IsEmpty() || e.Contains(Event.UiCmdStopDrainingTank3)))
{
draining3 = false;
closeValves.Add(StateMachine.DrainValve3);
stateText = stateText + "close tank 3, ";
}
else if (!draining1 && e.Contains(Event.UiCmdDrainTank1))
{
draining1 = true;
openValves.Add(StateMachine.DrainValve1);
stateText = stateText + "open tank 1, ";
}
else if (!draining2 && e.Contains(Event.UiCmdDrainTank2))
{
draining2 = true;
openValves.Add(StateMachine.DrainValve2);
stateText = stateText + "open tank 2, ";
}
else if (!draining3 && e.Contains(Event.UiCmdDrainTank3))
{
draining3 = true;
openValves.Add(StateMachine.DrainValve3);
stateText = stateText + "open tank 3, ";
}
draining = draining1 || draining2 || draining3;
if (draining) Bridge.OnActivity(this, Strings.Emptying_tank);
Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) |
((StateMachine.DrainValve1 == null) ? 0 : (draining1 ? ButtonsEtc.DrainTankBtn1Hi : ButtonsEtc.DrainTankBtn1En)) |
((StateMachine.DrainValve2 == null) ? 0 : (draining2 ? ButtonsEtc.DrainTankBtn2Hi : ButtonsEtc.DrainTankBtn2En)) |
((StateMachine.DrainValve3 == null) ? 0 : (draining3 ? ButtonsEtc.DrainTankBtn3Hi : ButtonsEtc.DrainTankBtn3En)));
State.Create(stateText)
.AddOperation(StateMachine.ControlBoard.SetValvesOp(openValves, closeValves))
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
}
while (e.Contains(Event.ValvesBusy));
}
}
}
void Shutdown(bool skipTankDraining = false)
{
log.WarnFormat(string.Format("Shutdown(skipTankDraining={0})", skipTankDraining));
StateMachine.MachineState = MachineState.ShuttingDown; /// TBF shut down cannot be aborted from now on
Bridge.Bench2UI(0); /// All buttons off
if (!skipTankDraining)
{
/// Drain time
int maxDrainTime = 0;
if ((StateMachine.Tank1 != null) && (StateMachine.Tank1.EmptyTimeSec > maxDrainTime)) maxDrainTime = StateMachine.Tank1.EmptyTimeSec;
if ((StateMachine.Tank2 != null) && (StateMachine.Tank2.EmptyTimeSec > maxDrainTime)) maxDrainTime = StateMachine.Tank2.EmptyTimeSec;
if ((StateMachine.Tank3 != null) && (StateMachine.Tank3.EmptyTimeSec > maxDrainTime)) maxDrainTime = StateMachine.Tank3.EmptyTimeSec;
/// Drain valves
IList<IValve> drainValves = new List<IValve>();
if (StateMachine.DrainValve1 != null) drainValves.Add(StateMachine.DrainValve1);
if (StateMachine.DrainValve2 != null) drainValves.Add(StateMachine.DrainValve2);
if (StateMachine.DrainValve3 != null) drainValves.Add(StateMachine.DrainValve3);
/// Open all drain valves
if (drainValves.Count > 0)
{
Bridge.OnActivity(this, Strings.Emptying_tank); /// Activity message
State.Create("Open all drain valves")
.AddOperation(StateMachine.ControlBoard.SetValvesOp(drainValves, null))
.EnterState();
while (StateMachine.WaitRunDevsRunOps().Contains(Event.ValvesBusy)) { }
}
/// Tank emptying valves states
bool draining1 = (StateMachine.DrainValve1 != null && StateMachine.Tank1 != null);
bool draining2 = (StateMachine.DrainValve2 != null && StateMachine.Tank2 != null);
bool draining3 = (StateMachine.DrainValve3 != null && StateMachine.Tank3 != null);
int drainingStartTime = StateMachine.Time;
/// Quit the following loop when time expires or all tanks are empty
while ((StateMachine.Time < drainingStartTime + maxDrainTime) && (draining1 || draining2 || draining3))
{
int remTime = drainingStartTime + maxDrainTime - StateMachine.Time;
Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remTime / 60, "min", remTime % 60, Strings.sec));
DoubleBox mass1 = new DoubleBox();
DoubleBox mass2 = new DoubleBox();
DoubleBox mass3 = new DoubleBox();
///
State.Create("MainSeq : Reading mass")
.AddOperation(checkUiOp)
.AddOperation((StateMachine.Tank1 is IScale) ? (StateMachine.Tank1 as IScale).ReadMassOp(ref mass1) : null)
.AddOperation((StateMachine.Tank2 is IScale) ? (StateMachine.Tank2 as IScale).ReadMassOp(ref mass2) : null)
.AddOperation((StateMachine.Tank3 is IScale) ? (StateMachine.Tank3 as IScale).ReadMassOp(ref mass3) : null)
.EnterState();
while (StateMachine.WaitRunDevsRunOps().Contains(Event.Busy)) { }
if (draining1 && StateMachine.Tank1 != null && StateMachine.Tank1.IsEmpty()) draining1 = false;
if (draining2 && StateMachine.Tank2 != null && StateMachine.Tank2.IsEmpty()) draining2 = false;
if (draining3 && StateMachine.Tank3 != null && StateMachine.Tank3.IsEmpty()) draining3 = false;
}
/// Close all drain valves
if (drainValves.Count > 0)
{
State.Create("Close all drain valves")
.AddOperation(StateMachine.ControlBoard.SetValvesOp(null, drainValves))
.EnterState();
while (StateMachine.WaitRunDevsRunOps().Contains(Event.ValvesBusy)) { }
}
}
///
/// Shut down the state machine
///
Bridge.OnActivity(this, Strings.Shutting_down_devices); /// Activity message
State.Create("No operations").EnterState(); /// Stop all operations
StateMachine.WaitRunDevsRunOps(true);
2021-10-26 09:23:57 +00:00
Rig.StateMachine.StopDevices(); /// Stop all devices - phase 1
Thread.Sleep(100);
2021-10-26 09:23:57 +00:00
Rig.StateMachine.StopDevices2(); /// Stop all devices - phase 2
}
/// <summary>
/// Create a new empty batch results from the procedure
/// </summary>
/// <param name="newBatchNr">New batch number</param>
/// <param name="procedure">Selected procedure</param>
/// <returns>Created BatchResults</returns>
Results.BatchResults CreateNewBatchResults(int newBatchNr, Procedure procedure)
{
///
/// Prepare new water meters
///
foreach (var wm in WaterMeters) wm.ClearData(); /// Clean water meter data
bool compound = (StateMachine.Procedure.MetersKind == MetersKind.Combined);
bool heatMeters = (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter);
int waterMetersCount = Math.Min(WaterMeters.Count, heatMeters ? TBF.Data.HeatMetersCount : (compound ? TBF.Data.CompoundWMsCount : TBF.Data.WMsCount));
///
Results.Entities.WaterMeterData[] waterMeterData = new Results.Entities.WaterMeterData[waterMetersCount];
///
int[] waterMeterParts = new int[waterMetersCount];
for (int wmNr = 0; wmNr < waterMetersCount; wmNr++)
{
int ix = compound ? (2 * wmNr) : wmNr;
if (WaterMeters.Count > ix)
{
waterMeterParts[wmNr] = Utils.PartNr(wmNr + 1, compound);
waterMeterData[wmNr] = new Results.Entities.WaterMeterData()
{
ProductName = WaterMeters[ix].ProductName,
Producer = WaterMeters[ix].Producer,
L = WaterMeters[ix].L,
DN = WaterMeters[ix].DN,
Mounting = WaterMeters[ix].Mounting,
Qnames = (sbyte)WaterMeters[ix].Qnames,
Q4_Qmax = WaterMeters[ix].Q4_Qmax,
Q3_Qn = WaterMeters[ix].Q3_Qn,
Q2_Qt = WaterMeters[ix].Q2_Qt,
Q1_Qmin = WaterMeters[ix].Q1_Qmin,
ErrLimHiQ = WaterMeters[ix].ErrLimHiQ,
ErrLimLoQ = WaterMeters[ix].ErrLimLoQ,
MetrologicalClass = WaterMeters[ix].MetrologicalClass,
TemperatureClass = WaterMeters[ix].TemperatureClass,
PressureLossClass = WaterMeters[ix].PressureLossClass,
MaxAdmissiblePressure = WaterMeters[ix].MaxAdmissiblePressure,
FlowProfileSensitivityClass = WaterMeters[ix].FlowProfileSensitivityClass,
ApprovalInfo = WaterMeters[ix].ApprovalInfo,
Certificate = WaterMeters[ix].Certificate,
PulsesPerLtr = WaterMeters[ix].PulsesPerLtr,
Medium = WaterMeters[ix].Medium,
Text1 = WaterMeters[ix].Text1,
Text2 = WaterMeters[ix].Text2,
Text3 = WaterMeters[ix].Text3,
Text4 = WaterMeters[ix].Text4,
Text5 = WaterMeters[ix].Text5,
Compound = compound,
HeatMeter = heatMeters,
#if ORACLE_DB
WMTypeId = (ProcessData.OracleDB != null) ? ProcessData.OracleDB.WMTypeId : 0,
#endif
};
}
int auxIx = 2 * wmNr + 1;
if (compound && WaterMeters.Count > auxIx)
{
waterMeterData[wmNr].ProducerAux = WaterMeters[auxIx].Producer;
waterMeterData[wmNr].Q3_Qn_Aux = WaterMeters[auxIx].Q3_Qn;
waterMeterData[wmNr].MetrologicalClassAux = WaterMeters[auxIx].MetrologicalClass;
waterMeterData[wmNr].ApprovalInfoAux = WaterMeters[auxIx].ApprovalInfo;
}
}
/// Prepare empty results
return Results.BatchResults.NewFromProcedure(newBatchNr,
(BenchInfo != null) ? BenchInfo.TestBenchId : 1,
(BenchInfo != null) ? BenchInfo.TestBenchName : "testbench",
(BenchInfo != null) ? BenchInfo.Address1 : string.Empty,
(BenchInfo != null) ? BenchInfo.Address2 : string.Empty,
(BenchInfo != null) ? BenchInfo.Address3 : string.Empty,
(BenchInfo != null) ? BenchInfo.Address4 : string.Empty,
(BenchInfo != null) ? BenchInfo.Address5 : string.Empty,
#if BAHRAIN_50
(Users.CurrentUser.User() != null) ? Users.CurrentUser.User().ToEncodedStr() : "none",
#else
(Users.CurrentUser.User() != null) ? Users.CurrentUser.User().ToEncodedStr(legalizatorName) : "none",
#endif
Users.CurrentUser.Number(),
Program.Version,
StateMachine.Procedure,
waterMeterData,
waterMeterParts,
Config.Formulas.RealDensity(),
Config.Formulas.AtTemperature(),
Config.Formulas.Buoyancy());
}
/// <summary>
/// Reload batch results from Results database given the batch number
/// </summary>
/// <param name="oriBatchNr">Original batch number</param>
/// <param name="newBatchNr">New unique batch number</param>
/// <param name="procedure">Reloaded procedure</param>
/// <returns></returns>
void RestoreBatchResults(int oriBatchNr, ref Results.BatchResults batchResults)
{
Batch oriBatch = Results.DB.LoadBatch(oriBatchNr);
if (oriBatch == null) return;
batchResults.Batch.StartTime = oriBatch.StartTime.AddMinutes(1);
batchResults.Batch.TestBenchId = (BenchInfo != null) ? BenchInfo.TestBenchId : 1;
batchResults.Batch.TestBenchName = (BenchInfo != null) ? BenchInfo.TestBenchName : "testbench";
foreach (var testRslt in batchResults.Batch.TestRslts)
{
foreach (var oriTstRslt in oriBatch.TestRslts)
{
if (testRslt.Name() == oriTstRslt.Name() &&
testRslt.Part == oriTstRslt.Part &&
testRslt.RepetitionNr == oriTstRslt.RepetitionNr)
{
testRslt.CopyContentFrom(oriTstRslt);
break;
}
}
}
for (int i = 0; i < batchResults.Batch.WaterMeters.Count; i++)
{
WaterMeter wm = batchResults.Batch.WaterMeters[i];
wm.Disabled = true;
foreach (var wm2 in oriBatch.WaterMeters)
{
if (wm.WMPosition == wm2.WMPosition)
{
wm.CopyContentFrom(wm2);
wm.Disabled = false;
#if ORACLE_DB
wm.WaterMeterData.WMTypeId = wm2.WaterMeterData.WMTypeId;
#endif
break;
}
}
}
}
void CollectSimultSteps()
{
///
/// Collect steps (e.g. iPerl communication) to be done simultaneously with purging
///
simultWithPurgingCount = 0;
simultWithPurging = null;
simultWithPurgingProcParams = null;
simultWithPurgingTests.Clear();
simultWithPurgingTestParams.Clear();
///
foreach (var ti in StateMachine.TestInstances)
{
Generic.IComponent testMethodComp = TbfComponents.FindComponent(ti.Test.Method);
if (testMethodComp == null) break;
testMethodComp.Cfg.LoadTestParamsFromDB(ti.Test);
ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod;
MetersPath sensPath = StateMachine.GetMetersPath(ti.Test);
if (simultTest == null || !simultTest.SimultWithPrevious || sensPath == null) break;
if (simultWithPurgingCount == 0)
{
simultWithPurging = simultTest;
simultWithPurgingProcParams = simultWithPurging.Cfg.GetRuntimeProcParamsProvider() as Generic.IProcedureParams;
}
else if (simultTest != simultWithPurging)
{
break;
}
simultWithPurgingTests.Add(ti.Test);
if (testMethodComp.Cfg.GetRuntimeTestParamsProvider() != null)
{
simultWithPurgingTestParams.Add(testMethodComp.Cfg.GetRuntimeTestParamsProvider().Clone() as Generic.ITestParams);
}
else
{
simultWithPurgingTestParams.Add(null);
}
simultWithPurgingCount++;
}
///
/// Collect steps (e.g. iPerl communication) to be done simultaneously with evacuation
///
simultWithEvacuationCount = 0;
simultWithEvacuation = null;
simultWithEvacuationProcParams = null;
simultWithEvacuationTests.Clear();
simultWithEvacuationTestParams.Clear();
///
for (int i = StateMachine.TestInstances.Length - 1; i >= simultWithPurgingCount; i--)
{
var test = StateMachine.TestInstances[i].Test;
Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method);
if (testMethodComp == null) break;
testMethodComp.Cfg.LoadTestParamsFromDB(test);
ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod;
MetersPath sensPath = StateMachine.GetMetersPath(test);
if (simultTest == null || !simultTest.SimultWithNext || sensPath == null) break;
if (simultWithEvacuationCount == 0)
{
simultWithEvacuation = simultTest;
simultWithEvacuationProcParams = simultWithEvacuation.Cfg.GetRuntimeProcParamsProvider() as Generic.IProcedureParams;
}
else if (simultTest != simultWithEvacuation)
{
break;
}
simultWithEvacuationTests.Insert(0, test);
if (testMethodComp.Cfg.GetRuntimeTestParamsProvider() != null)
{
simultWithEvacuationTestParams.Insert(0, testMethodComp.Cfg.GetRuntimeTestParamsProvider().Clone() as Generic.ITestParams);
}
else
{
simultWithEvacuationTestParams.Insert(0, null);
}
simultWithEvacuationCount++;
}
}
/// <summary>
/// Executes steps of a evacuation sequence
/// </summary>
/// <returns>
/// Event.Done Transition sequence completed OK
/// Event.UiCmdStop Transition sequence interrupted by the STOP on-screen button
2022-01-04 17:15:49 +00:00
/// Event.Error Error (e.g. RegulValveTimeOut returned by Run() of SetRegValvePositionOp)
/// </returns>
Event DoEvacuation(TransitionSequence purgeEnd)
{
IList<Event> e;
if (simultWithEvacuationCount > 0)
{
/// Open iPerlCommunicationForm
ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithEvacuationTests[0]).RegisterReaders;
var firstRR = ProcessData.RegisterReaders.FirstOrDefault<IRegReader>(x => x != null);
2021-10-26 09:23:57 +00:00
if (firstRR is TBF.Rig.TestMethods.iPerlCommunication.iPerlHead.IperlHead)
{
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenIPerlCommForm),
new object[] { this, simultWithEvacuation, simultWithEvacuationProcParams, simultWithEvacuationTests, simultWithEvacuationTestParams });
}
2021-10-26 09:23:57 +00:00
else if (firstRR is TBF.Rig.RegisterReaders.S640Stream.S640Stream)
{
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenS640CommForm),
new object[] { this, simultWithEvacuation, simultWithEvacuationProcParams, simultWithEvacuationTests, simultWithEvacuationTestParams });
}
}
//--------------------------------------------------------
if (FillState != FillState.Empty)
{
switch (Transition(purgeEnd, TransitionContext.PurgeEnd))
{
case Event.Error:
if (simultWithEvacuationCount > 0) CloseCommunicationForm();
return Event.Error;
case Event.UiCmdStop:
if (simultWithEvacuationCount > 0) CloseCommunicationForm();
return Event.UiCmdStop;
default:
break;
}
}
if (simultWithEvacuationCount > 0)
{
///
/// Wait until iPerl communications are completed
///
bool completed = !(modelessDlg is IHasCompleted)
|| (modelessDlg as IHasCompleted).Completed;
if (!completed)
{
State.Create("MainSeq : Wait until the entry form is closed")
.AddOperation(checkUiOp)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.UiCmdStop))
{
CloseCommunicationForm();
return Event.UiCmdStop;
}
completed = (modelessDlg as IHasCompleted).Completed;
}
while (!completed);
}
modelessDlg = null;
}
Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty);
return Event.Done;
}
}
}