A – Registration and execution - Register GenesisCommunication Factory in the component list. - Separate the Genesis form and sequence from iPerl communication. B – Communication activities - Restore initialization, connection, PCB reading, password and login. - Include grouped login, mode switching and disconnection. - Support processing up to 10 slots. C1 – Input calibration factors - Read three factors from Water meters / Text1–Text3. - Validate integer values in the range 1–65535. - Preserve the default of 15625 when all three fields are empty. D – Q3 calibration - Connect the Prepare Q3 → measurement → Write Q3 workflow. - Add channel processing to FlyingStart and FlyingStartMassCollection. - Reset previous measurement data and validate calculated factors. - Mark factors as stored only after StoreCalibration succeeds. E – Results and database - Store calibration factors separately for each meter and channel. - Add result entities, mappings and Q3 data. - Extend DB.cs / EnsureSchema to create and update the schema. - Preserve compatibility with the existing binary format. Validation: - Debug build and 18 tests passed. - Simulated communication runs follow the same activity sequence. - The complete Q3 workflow has not yet been verified on hardware. Known limitation: - An inherited mismatch in simulated responses and error propagation can produce an incorrect OK result; this change does not fix it.
1861 lines
86 KiB
C#
1861 lines
86 KiB
C#
///
|
|
/// Copyright (c) 2013-2023 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using log4net;
|
|
using NHibernate;
|
|
using Common;
|
|
using Config.Entities;
|
|
using TBF.Rig.Operations;
|
|
using TBF.Rig.GenericDevices;
|
|
using TBF.Resources;
|
|
using TBF.Rig.Generic;
|
|
using TBF.Rig.Network.RestAPI;
|
|
using TBF.Rig.Network.RestAPI.facade;
|
|
using TBF.Rig.Output.Printers.GroupPrinting.Single;
|
|
using TBF.UiBridge;
|
|
using SharedComponents;
|
|
using System.Text;
|
|
using TBF.Rig.RegisterReaders.CommonRR.IPerl;
|
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
|
|
|
namespace TBF.Rig.Sequences
|
|
{
|
|
public partial class MainSeq : SequenceBase
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(MainSeq));
|
|
|
|
public override string ToString() { return "Sequences.MainSeq"; }
|
|
|
|
bool isApprovedByLegalizator = false;
|
|
string legalizatorName = string.Empty;
|
|
DateTime lastApprovalByLegalizatorTime;
|
|
|
|
int simultWithPurgingCount;
|
|
Generic.IComponentCfg simultWithPurgingCfg;
|
|
Generic.IComponent simultWithPurging;
|
|
Generic.IProcedureParams simultWithPurgingProcParams;
|
|
IList<Config.Entities.Test> simultWithPurgingTests;
|
|
IList<Generic.ITestParams> simultWithPurgingTestParams;
|
|
|
|
int simultWithEvacuationCount;
|
|
Generic.IComponentCfg simultWithEvacuationCfg;
|
|
Generic.IProcedureParams simultWithEvacuationProcParams;
|
|
IList<Config.Entities.Test> simultWithEvacuationTests;
|
|
IList<Generic.ITestParams> simultWithEvacuationTestParams;
|
|
|
|
System.Windows.Forms.Form modelessDlg;
|
|
///
|
|
delegate void CommunicationFormDlgt(MainSeq myRef, Generic.IComponent testMethod, Generic.IComponentCfg cfg, Generic.IProcedureParams procParams, IList<Test> tests, IList<Generic.ITestParams> multiTestParams);
|
|
///
|
|
void OpenIPerlCommForm(MainSeq myRef, Generic.IComponent testMethod, Generic.IComponentCfg cfg, Generic.IProcedureParams procParams, IList<Test> tests, IList<Generic.ITestParams> multiTestParams)
|
|
{
|
|
try
|
|
{
|
|
// /// 1nd argument
|
|
// ITestMethodCfg testMethodCfg = cfg as ITestMethodCfg;
|
|
// if (testMethodCfg == null)
|
|
// {
|
|
//
|
|
// }
|
|
//
|
|
// /// 2rd argument: as is
|
|
//
|
|
// /// 3th argument
|
|
// IList<ITestParams> iPerlCommParams = new List<ITestParams>();
|
|
// foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as TestMethods.iPerlCommunication.iPerlCommunicationParams);
|
|
//
|
|
// /*myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(iPerlCfg, tests, iPerlCommParams);
|
|
// myRef.modelessDlg.Show();*/
|
|
//
|
|
// myRef.modelessDlg = new SmartCommunicationForm( testMethod , tests, iPerlCommParams);
|
|
// myRef.modelessDlg.Show();
|
|
|
|
if (testMethod is TestMethods.GenesisCommunication.TestMethod genesisMethod)
|
|
{
|
|
var parameters = multiTestParams.Cast<TestMethods.GenesisCommunication.iPerlCommunicationParams>().ToList();
|
|
myRef.modelessDlg = new TestMethods.GenesisCommunication.GenesisCommunicationForm(genesisMethod, tests, parameters);
|
|
myRef.modelessDlg.Show();
|
|
return;
|
|
}
|
|
|
|
/// 1nd argument
|
|
TestMethods.iPerlCommunication.TestMethodCfg iPerlCfg = cfg as TestMethods.iPerlCommunication.TestMethodCfg;
|
|
|
|
/// 2rd argument: as is
|
|
|
|
/// 3th argument
|
|
IList<TestMethods.iPerlCommunication.iPerlCommunicationParams> iPerlCommParams = new List<TestMethods.iPerlCommunication.iPerlCommunicationParams>();
|
|
foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as TestMethods.iPerlCommunication.iPerlCommunicationParams);
|
|
|
|
/*myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(iPerlCfg, tests, iPerlCommParams);
|
|
myRef.modelessDlg.Show();*/
|
|
|
|
myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(
|
|
testMethod as TestMethods.iPerlCommunication.TestMethod, tests, iPerlCommParams);
|
|
myRef.modelessDlg.Show();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
log.FatalFormat("---------------( MainSeq : OpenIperlCommForm crashed !!! )---------------");
|
|
log.FatalFormat("Message : {0}", e.Message);
|
|
if (e.InnerException != null)
|
|
{
|
|
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
|
|
}
|
|
log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace);
|
|
log.Fatal("--------------------------------------");
|
|
}
|
|
}
|
|
///
|
|
void OpenS640CommForm(MainSeq myRef, Generic.IComponent testMethod, Generic.IComponentCfg cfg, Generic.IProcedureParams procParams, IList<Test> tests, IList<Generic.ITestParams> multiTestParams)
|
|
{
|
|
try
|
|
{
|
|
TestMethods.S640Communication.S640Activity activity; /// 1st argument
|
|
TBF.Rig.TestMethods.S640Communication.I640Cfg config; /// 2nd argument
|
|
if (cfg is TestMethods.S640Communication.S640StartCfg)
|
|
{
|
|
activity = TestMethods.S640Communication.S640Activity.Start;
|
|
config = (cfg as TestMethods.S640Communication.S640StartCfg);
|
|
}
|
|
else if (cfg is TestMethods.S640Communication.S640EndCfg)
|
|
{
|
|
activity = TestMethods.S640Communication.S640Activity.End;
|
|
config = (cfg as TestMethods.S640Communication.S640EndCfg);
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
/// 1st argument
|
|
IList<TestMethods.S640Communication.S640Activity> activities = new List<TestMethods.S640Communication.S640Activity>();
|
|
foreach (var t in tests)
|
|
{
|
|
activities.Add(activity);
|
|
}
|
|
/// 2nd argument: as is
|
|
/// 3rd argument: as is
|
|
|
|
myRef.modelessDlg = new TestMethods.S640Communication.S640CommForm(activities, config, procParams, tests,
|
|
ProcessData.BatchRslts.Batch.WaterMeters);
|
|
myRef.modelessDlg.Show();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
log.FatalFormat("---------------( MainSeq : OpenIperlCommForm crashed !!! )---------------");
|
|
log.FatalFormat("Message : {0}", e.Message);
|
|
if (e.InnerException != null)
|
|
{
|
|
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
|
|
}
|
|
log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace);
|
|
log.Fatal("--------------------------------------");
|
|
}
|
|
}
|
|
///
|
|
void CloseCommunicationForm()
|
|
{
|
|
Bridge.OnCloseModelessForm(this, null);
|
|
modelessDlg = null;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public MainSeq()
|
|
{
|
|
FillState = FillState.Unknown;
|
|
|
|
simultWithPurgingCount = 0;
|
|
simultWithPurgingCfg = null;
|
|
simultWithPurgingProcParams = null;
|
|
simultWithPurgingTests = new List<Config.Entities.Test>();
|
|
simultWithPurgingTestParams = new List<Generic.ITestParams>();
|
|
|
|
simultWithEvacuationCount = 0;
|
|
simultWithEvacuationCfg = null;
|
|
simultWithEvacuationProcParams = null;
|
|
simultWithEvacuationTests = new List<Config.Entities.Test>();
|
|
simultWithEvacuationTestParams = new List<Generic.ITestParams>();
|
|
|
|
checkUiOp = new CheckUIOp(true); /// Running in almost all states
|
|
}
|
|
|
|
|
|
private string[] ImplementActiveGroupPrinters(string[] printers)
|
|
{
|
|
return GroupPrinterUtils.GetExpandedGroupPrinters(printers);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes the main sequence.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method is used to execute the main sequence.
|
|
/// </remarks>
|
|
public void Execute()
|
|
{
|
|
IList<Event> e = new List<Event>();
|
|
Selection selection;
|
|
string selectedTestName;
|
|
|
|
Bridge.OnActivity(this, Strings.Starting_system);
|
|
WaitForOkButton();
|
|
SetValvesToDefaultState();
|
|
|
|
|
|
string scaleName;
|
|
string message;
|
|
if (TestCommunicationWithScales(out scaleName, out message) == false)
|
|
{
|
|
log.ErrorFormat("Error state on scale:{0} : {1}", scaleName, message);
|
|
Bridge.OnError(this, string.Format("{0} : {1}", scaleName, message));
|
|
goto error;
|
|
}
|
|
|
|
|
|
if (!DrainTanks())
|
|
{
|
|
Bridge.OnError(this, "Error when draining tanks");
|
|
goto error;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
Bridge.OnActivity(this, Strings.Resetting_scales);
|
|
Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Resetting scales -> Enable STOP button
|
|
|
|
State.Create("MainSeq : Reset scales").AddOperation(checkUiOp)
|
|
.AddOperation((StateMachine.Tank1 is IScale) ? (StateMachine.Tank1 as IScale).ZeroOp() : null)
|
|
.AddOperation((StateMachine.Tank2 is IScale) ? (StateMachine.Tank2 as IScale).ZeroOp() : null)
|
|
.AddOperation((StateMachine.Tank3 is IScale) ? (StateMachine.Tank3 as IScale).ZeroOp() : null)
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) goto error;
|
|
if (e.Contains(Event.UiCmdStop)) goto stop;
|
|
}
|
|
while (e.Contains(Event.Busy));
|
|
|
|
select_procedure:
|
|
|
|
CloseBeginForm(); /// Make sure the CycleBeginForm is closed (after an abnormal end, etc.)
|
|
|
|
do
|
|
{
|
|
do
|
|
{
|
|
selection = MakeSelection(MKSelContext.ProcedureNotSelected);
|
|
if (selection == Selection.Shutdown)
|
|
{
|
|
Shutdown();
|
|
return;
|
|
}
|
|
}
|
|
while (selection == Selection.Shutdown);
|
|
|
|
ProcessData.SelectedProcedure = Program.MainWnd.SelectedProcedure;
|
|
///
|
|
if (ProcessData.SelectedProcedure != null && ProcessData.SelectedProcedure.OrderInfo is Output.DB.SensusOracle.OrderDetails)
|
|
{
|
|
ProcessData.OrderInfo = ProcessData.SelectedProcedure.OrderInfo;
|
|
}
|
|
else if (ProcessData.SelectedProcedure != null && ProcessData.SelectedProcedure.OrderInfo is SharedDatabase.Entities.OrderInfo &&
|
|
ProcessData.TracingDB != null)
|
|
{
|
|
try
|
|
{
|
|
using (var session = ProcessData.TracingDB.SessionFactory.OpenSession())
|
|
{
|
|
var list = session.QueryOver<SharedDatabase.Entities.OrderInfo>()
|
|
.Where(x => (x.POName == ProcessData.SelectedProcedure.OrderInfo.POName))
|
|
.List();
|
|
ProcessData.OrderInfo = (list.Count == 1) ? list[0] : null;
|
|
string workflow = (list.Count == 1) ? list[0].Workflow : null;
|
|
ProcessData.WorkflowSummary = SharedDatabase.WorkflowSummary.ReadFromDB(workflow, "test", session);
|
|
session.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.ErrorFormat("Unable to load order, workflow or workstep: {0}", ex);
|
|
ProcessData.OrderInfo = null;
|
|
ProcessData.WorkflowSummary = null;
|
|
}
|
|
}
|
|
|
|
selectedTestName = (selection == Selection.Q1) ? "Q1"
|
|
: ((selection == Selection.Q2) ? "Q2"
|
|
: ((selection == Selection.Q3) ? "Q3" : Program.MainWnd.BenchControlPanel.TestName));
|
|
|
|
///
|
|
/// Auto invocation actions
|
|
///
|
|
IList<string> procedureBefore = new List<string>();
|
|
IList<string> testsInside = new List<string>();
|
|
IList<string> procedureAfer = new List<string>();
|
|
|
|
///
|
|
/// Collect information about the interrupted procedure (if applicable)
|
|
///
|
|
bool restoreInterruptedSession = false;
|
|
bool processDataHeaderOK = false;
|
|
string interruptedProcedureName = string.Empty;
|
|
bool isRemoteIntProc = false;
|
|
///
|
|
if (selection == Selection.RestoreInterruptedSession)
|
|
{
|
|
int batchNr;
|
|
string version;
|
|
processDataHeaderOK = ProcessData.LoadProcessDataHeader(out batchNr, out version, out interruptedProcedureName, out isRemoteIntProc);
|
|
|
|
if (!processDataHeaderOK)
|
|
{
|
|
Bridge.OnError(this, "Invalid process data");
|
|
continue;
|
|
}
|
|
else if (version != Program.Version)
|
|
{
|
|
/// Program version does not match the one stored in process data
|
|
Bridge.OnError(this, Strings.Program_version_does_not_match);
|
|
continue;
|
|
}
|
|
else if (batchNr != Program.LocalSettings.BatchNr)
|
|
{
|
|
/// Program version does not match the one stored in process data
|
|
Bridge.OnError(this, Strings.Invalid_batch_number);
|
|
continue;
|
|
}
|
|
|
|
restoreInterruptedSession = true;
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
using (ISession localSession = TBF.DB.CreateSession(DBKind.Config))
|
|
{
|
|
StateMachine.LoadPathsAndTransitions(localSession);
|
|
}
|
|
|
|
///
|
|
/// Try to load all parameters of selected or restored procedure from the respective database
|
|
///
|
|
if (restoreInterruptedSession)
|
|
{
|
|
/// User has chosen to restore an interrupted session and necessary conditions are met
|
|
|
|
/// TODO: Repeate twice for DBKind.Config and DBKind.RemoteConfig
|
|
using (ISession remoteOrLocalSession = TBF.DB.CreateSession(isRemoteIntProc ?
|
|
DBKind.RemoteConfig :
|
|
DBKind.Config))
|
|
{
|
|
StateMachine.LoadProcedure(remoteOrLocalSession, interruptedProcedureName, isRemoteIntProc);
|
|
StateMachine.LoadProcedureParams(StateMachine.Procedure);
|
|
|
|
/// This is to load Procedure.Tests and test.MoreParams for each test
|
|
int a = 0;
|
|
foreach (var test in StateMachine.Procedure.Tests) a += test.MoreParams.Count;
|
|
}
|
|
}
|
|
else if (SelectedProcedure != null &&
|
|
SelectedProcedure.ResolvedSource != ProcedureSelection.None &&
|
|
!string.IsNullOrEmpty(SelectedProcedure.ResolvedName))
|
|
{
|
|
if (selection == Selection.Cycle)
|
|
{
|
|
/// This is a regular complete cycle => check AutoAction==InvokeXY calendar events
|
|
procedureBefore = ServeCalendarEventsInvokeXY(Config.CalendarEvent.AutoAction.InvokeBeforeCycle, 1);
|
|
|
|
if (procedureBefore.Count == 1)
|
|
{
|
|
/// TODO: Invoke procedure before a cycle
|
|
}
|
|
else
|
|
{
|
|
testsInside = ServeCalendarEventsInvokeXY(Config.CalendarEvent.AutoAction.InvokeInsideCycle);
|
|
}
|
|
}
|
|
|
|
/// TODO: Repeate twice for DBKind.Config and DBKind.RemoteConfig
|
|
using (ISession remoteOrLocalSession = TBF.DB.CreateSession((SelectedProcedure.ResolvedSource == ProcedureSelection.FromSharedDB) ?
|
|
DBKind.RemoteConfig :
|
|
DBKind.Config))
|
|
{
|
|
StateMachine.LoadProcedure(remoteOrLocalSession,
|
|
SelectedProcedure.ResolvedName,
|
|
(SelectedProcedure.ResolvedSource == ProcedureSelection.FromSharedDB),
|
|
testsInside);
|
|
StateMachine.LoadProcedureParams(StateMachine.Procedure);
|
|
|
|
/// This is to load Procedure.Tests and test.MoreParams for each test
|
|
int a = 0;
|
|
foreach (var test in StateMachine.Procedure.Tests) a += test.MoreParams.Count;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StateMachine.Procedure = null;
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
string msg = exc.Message;
|
|
StateMachine.Procedure = null;
|
|
}
|
|
}
|
|
while (StateMachine.Procedure == null); /// Make sure a valid procedure is selected
|
|
|
|
#if LANG_PL
|
|
///
|
|
/// Approval of a legalizator
|
|
///
|
|
if (!string.IsNullOrEmpty(StateMachine.Procedure.AltProcName) && !IsApprovedByLegalizator())
|
|
{
|
|
goto select_procedure; /// Loop back to procedure selection if not approved by a legalizator
|
|
}
|
|
#endif
|
|
|
|
Debug.WriteLine(string.Empty);
|
|
Debug.WriteLine(string.Format("TransitionSequences {0}", NHibernateUtil.IsInitialized(StateMachine.TransitionSequences) ? "initialized" : "NOT initialized"));
|
|
Debug.WriteLine(string.Format("TransitionSteps {0}", NHibernateUtil.IsInitialized(StateMachine.TransitionSteps) ? "initialized" : "NOT initialized"));
|
|
Debug.WriteLine(string.Format("Procedure {0}", NHibernateUtil.IsInitialized(StateMachine.Procedure) ? "initialized" : "NOT initialized"));
|
|
Debug.WriteLine(string.Format("Procedure.MoreParams {0}", NHibernateUtil.IsInitialized(StateMachine.Procedure.MoreParams) ? "initialized" : "NOT initialized"));
|
|
Debug.WriteLine(string.Format("Procedure.Tests {0}", NHibernateUtil.IsInitialized(StateMachine.Procedure.Tests) ? "initialized" : "NOT initialized"));
|
|
if (StateMachine.Procedure.Tests.Count > 0)
|
|
{
|
|
Debug.WriteLine(string.Format("Procedure.Tests[0].MoreParams {0}", NHibernateUtil.IsInitialized(StateMachine.Procedure.Tests[0].MoreParams) ? "initialized" : "NOT initialized"));
|
|
}
|
|
|
|
Bridge.OnError(this, string.Empty); /// Clear an error message (if any)
|
|
|
|
|
|
if (selection == Selection.RestoreInterruptedSession)
|
|
{
|
|
if (!LoadProcessData())
|
|
{
|
|
/// Restorig interrupted session failed
|
|
Bridge.OnError(this, "Restorig interrupted session failed");
|
|
goto stop;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/// Clear session data in case this is not an interrupted/restored session
|
|
ClearSessionData();
|
|
}
|
|
|
|
|
|
///
|
|
/// Procedure selected at this point, a new batch was started
|
|
///
|
|
int newBatchNr = Program.LocalSettings.BatchNr;
|
|
if (StateMachine.ControlBoardMain is ControlBoard.Uni.UniCB)
|
|
{
|
|
(StateMachine.ControlBoardMain as ControlBoard.Uni.UniCB).IsUIBlocked = StateMachine.Procedure.ManualCtrlDisabled;
|
|
}
|
|
Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// A new cycle started : Enable STOP button
|
|
log.FatalFormat("New measurement session started: batch = {0}, procedure = {1}", newBatchNr, StateMachine.Procedure.Name);
|
|
|
|
|
|
if (selection == Selection.RestoreBatch)
|
|
{
|
|
BatchRslts = CreateNewBatchResults(newBatchNr, StateMachine.Procedure);
|
|
RestoreBatchResults(Bridge.BatchNr, ref BatchRslts); /// pass the original batch number of the batch to be restored
|
|
}
|
|
else if (selection == Selection.RestoreAndFixBatch)
|
|
{
|
|
///
|
|
/// Restore and fix a batch - part 1 (fix "Previous workstep is missing" error)
|
|
///
|
|
BatchRslts = CreateNewBatchResults(newBatchNr, StateMachine.Procedure);
|
|
RestoreBatchResults(Bridge.BatchNr, ref BatchRslts); /// pass the original batch number of the batch to be restored
|
|
|
|
for (int i = 0; i < BatchRslts.Batch.WaterMeters.Count; i++)
|
|
{
|
|
var wm = BatchRslts.Batch.WaterMeters[i];
|
|
if (wm != null && !wm.Disabled)
|
|
{
|
|
if (wm.Passed)
|
|
{
|
|
/// Water meter passed and was already saved to Oracle, do not reload & fix it now
|
|
wm.Disabled = true;
|
|
}
|
|
else if ((wm.ErrorFlags & (int)ErrorFlagMask.E28) == 0)
|
|
{
|
|
/// Water meter failed but the failure is not an assembly error
|
|
wm.Disabled = true;
|
|
}
|
|
else if (!wm.Disabled && (CurrentUser.UserName() == "milan" ||
|
|
CurrentUser.UserName() == "augustin" ||
|
|
CurrentUser.UserName() == "michal" ||
|
|
CurrentUser.UserName() == "michal2"))
|
|
{
|
|
/// Water meter failed, is not disabled, there is an assembly error and user is one of above
|
|
/// ... => reset flag E28
|
|
wm.ErrorFlags = wm.ErrorFlags & (~(int)ErrorFlagMask.E28);
|
|
foreach (var mtr in wm.MeterTestRslts)
|
|
{
|
|
if (mtr.TestData().Evaluate && (mtr.TestData().Name == "Kontrola montaze") && (mtr.TestData().Method == "iPerlCommunication"))
|
|
{
|
|
mtr.TestDone = true;
|
|
mtr.Passed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (selection != Selection.RestoreInterruptedSession)
|
|
{
|
|
/// This is a regular session => initialize BatchRslts
|
|
string vaco = (SelectedProcedure != null) ? SelectedProcedure.Variant : string.Empty;
|
|
string order = (SelectedProcedure != null && SelectedProcedure.OrderInfo != null) ? SelectedProcedure.OrderInfo.POName : string.Empty;
|
|
string wflow = (SelectedProcedure != null) ? SelectedProcedure.Workflow : string.Empty;
|
|
string laser = (SelectedProcedure != null) ? SelectedProcedure.LaserMarking : string.Empty;
|
|
///
|
|
BatchRslts = CreateNewBatchResults(newBatchNr, StateMachine.Procedure, vaco, order, wflow, laser);
|
|
}
|
|
|
|
|
|
BatchRslts.Batch.IsRemoteProcedure = StateMachine.IsRemoteProcedure;
|
|
StateMachine.CycleStartTimeStamp = BatchRslts.Batch.StartTime;
|
|
Bridge.OnProcedureSelected(this, new ProcedureSelectedEventArgs(StateMachine.Procedure)); /// Select procedure in case of interrupted session
|
|
|
|
|
|
if (selection != Selection.RestoreBatch && selection != Selection.RestoreAndFixBatch && selection != Selection.RestoreInterruptedSession)
|
|
{
|
|
///
|
|
/// This is a normal batch (not a restored one) => Display 'Cycle Begin Form'
|
|
///
|
|
/// Open iPerlCommunicationForm
|
|
if (simultWithPurgingTests.Count > 0)
|
|
{
|
|
ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithPurgingTests[0]).RegisterReaders;
|
|
}
|
|
|
|
// Some procedures do not have a communication test simultaneous with purging.
|
|
// Resolve their first usable meter path before opening the cycle-begin dialog.
|
|
if (ProcessData.RegisterReaders == null ||
|
|
!ProcessData.RegisterReaders.Any(reader => reader != null))
|
|
{
|
|
foreach (Test procedureTest in StateMachine.Procedure.Tests)
|
|
{
|
|
MetersPath metersPath = StateMachine.GetMetersPath(procedureTest);
|
|
if (metersPath == null || metersPath.RegisterReaders == null ||
|
|
!metersPath.RegisterReaders.Any(reader => reader != null))
|
|
continue;
|
|
|
|
ProcessData.RegisterReaders = metersPath.RegisterReaders;
|
|
log.DebugFormat(
|
|
"DATA_ENTRY_BEGIN_READERS_RESOLVED Test={0}, Slots={1}, Readers={2}, Positions=[{3}]",
|
|
procedureTest.Name,
|
|
ProcessData.RegisterReaders.Length,
|
|
ProcessData.RegisterReaders.Count(reader => reader != null),
|
|
string.Join(",", ProcessData.RegisterReaders
|
|
.Where(reader => reader != null)
|
|
.Select(reader => reader.Position)));
|
|
break;
|
|
}
|
|
|
|
if (ProcessData.RegisterReaders == null ||
|
|
!ProcessData.RegisterReaders.Any(reader => reader != null))
|
|
{
|
|
log.Warn(
|
|
"DATA_ENTRY_BEGIN_READERS_NOT_RESOLVED No procedure test contains an active register reader");
|
|
}
|
|
}
|
|
|
|
if (!OpenCycleBeginForm(ProcessData.RegisterReaders))
|
|
{
|
|
goto stop;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Prepare operations for reading start info @ cycle start
|
|
///
|
|
IList<IOperation> startInfoReadOps = new List<IOperation>();
|
|
string[] resultWriters = StateMachine.Procedure.ResultsWriter.Split(new char[] { '~' });
|
|
foreach (var writerName in resultWriters)
|
|
{
|
|
IStartInfoReader infoReader = TbfComponents.FindComponent(writerName) as IStartInfoReader;
|
|
if (infoReader != null)
|
|
{
|
|
try
|
|
{
|
|
IOperation op = infoReader.ReadStartInfoOp(ProcessData.BatchRslts.Batch.WaterMeters);
|
|
if (op != null) startInfoReadOps.Add(op);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Bridge.OnError(this, string.Format(Strings.Component_0_crashed_Results_not_saved, writerName));
|
|
log.FatalFormat("StartInfoReader {0} crashed: {1}", writerName, exc.Message);
|
|
}
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Find purge suquences
|
|
///
|
|
TransitionSequence purgeBegin = null;
|
|
TransitionSequence purgeEnd = null;
|
|
foreach (var transition in StateMachine.TransitionSequences)
|
|
{
|
|
if (transition.Name == StateMachine.Procedure.TransitionStart) purgeBegin = transition;
|
|
if (transition.Name == StateMachine.Procedure.TransitionEnd) purgeEnd = transition;
|
|
}
|
|
|
|
|
|
if (selection == Selection.Q1 ||
|
|
selection == Selection.Q2 ||
|
|
selection == Selection.Q3 ||
|
|
selection == Selection.Test ||
|
|
selection == Selection.RestoreInterruptedSession)
|
|
{
|
|
goto assume_bench_filled;
|
|
}
|
|
else if ((selection == Selection.Cycle && FillState == FillState.Full) ||
|
|
(selection == Selection.RestoreBatch) ||
|
|
(selection == Selection.RestoreAndFixBatch) ||
|
|
(selection == Selection.RestoreInterruptedSession))
|
|
{
|
|
///
|
|
/// Always ask a question in case of a restored batch
|
|
///
|
|
State.Create("MainSeq : Answer a question")
|
|
.AddOperation(new Operations.AskYesNoOp(Strings.Fill_with_water))
|
|
.AddOperation(checkUiOp)
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.No)) goto assume_bench_filled;
|
|
if (e.Contains(Event.UiCmdStop)) goto select_procedure;
|
|
}
|
|
while (!e.Contains(Event.Yes));
|
|
}
|
|
|
|
fill_the_bench:
|
|
|
|
CollectSimultSteps();
|
|
///
|
|
if (simultWithPurgingCount > 0)
|
|
{
|
|
/// Make sure the entry form is closed
|
|
if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop;
|
|
|
|
/// Open iPerlCommunicationForm
|
|
ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithPurgingTests[0]).RegisterReaders;
|
|
var firstRR = ProcessData.RegisterReaders.FirstOrDefault<IRegReader>(x => x != null);
|
|
if (firstRR is TBF.Rig.TestMethods.iPerlCommunication.iPerlHead.IperlHead)
|
|
{
|
|
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingProcParams, simultWithPurgingTests, simultWithPurgingTestParams });
|
|
}
|
|
else if (firstRR is TBF.Rig.RegisterReaders.S640Stream.S640Stream)
|
|
{
|
|
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenS640CommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingProcParams, simultWithPurgingTests, simultWithPurgingTestParams });
|
|
}
|
|
else if (firstRR is TBF.Rig.RegisterReaders.PoseidonCmdStartStop.PoseidonReader)
|
|
{
|
|
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenS640CommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingProcParams, simultWithPurgingTests, simultWithPurgingTestParams });
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Purging @ cycle start
|
|
///
|
|
Event evt = Transition(purgeBegin, TransitionContext.PurgeBegin);
|
|
switch (evt)
|
|
{
|
|
case Event.Error:
|
|
if (simultWithPurgingCount > 0) CloseCommunicationForm();
|
|
goto error;
|
|
case Event.UiCmdStop:
|
|
if (simultWithPurgingCount > 0) CloseCommunicationForm();
|
|
goto stop;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
///
|
|
/// Wait until iPerl communications or S/N data entry are completed
|
|
///
|
|
if ((simultWithPurgingCount > 0) || (startInfoReadOps.Count > 0))
|
|
{
|
|
/// Get 'bool completed'
|
|
bool completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.IHasCompleted).Completed;
|
|
if (lastDataEntryCmpnt != null) completed = completed && lastDataEntryCmpnt.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();
|
|
goto stop;
|
|
}
|
|
|
|
/// Update 'bool completed'
|
|
completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.IHasCompleted).Completed;
|
|
if (lastDataEntryCmpnt != null) completed = completed && lastDataEntryCmpnt.Completed;
|
|
}
|
|
while (!completed);
|
|
}
|
|
|
|
modelessDlg = null;
|
|
}
|
|
|
|
assume_bench_filled:
|
|
|
|
FillState = FillState.Full;
|
|
Bridge.Bench2UI(ButtonsEtc.ShowBenchFilled);
|
|
|
|
if ((selection == Selection.Cycle) || (selection == Selection.RestoreBatch) || (selection == Selection.RestoreAndFixBatch))
|
|
{
|
|
///
|
|
/// Read start info from the DB @ cycle start
|
|
///
|
|
if (startInfoReadOps.Count > 0)
|
|
{
|
|
State.Create("MainSeq : Reading start info from DB")
|
|
.AddOperations(startInfoReadOps)
|
|
.AddOperation(checkUiOp).EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) goto error;
|
|
if (e.Contains(Event.UiCmdStop)) goto stop;
|
|
}
|
|
while (e.Contains(Event.Busy));
|
|
|
|
if (e.Contains(Event.InfoNotRead))
|
|
{
|
|
log.ErrorFormat("StartInfoReader failed to read data from the database");
|
|
/// TODO: Message for an operator? Error?
|
|
}
|
|
else if ((selection == Selection.RestoreAndFixBatch) && (CurrentUser.UserName() != "milan"))
|
|
{
|
|
/// Restore and fix a batch - part 2
|
|
for (int i = 0; i < BatchRslts.Batch.WaterMeters.Count; i++)
|
|
{
|
|
var wm = BatchRslts.Batch.WaterMeters[i];
|
|
if (wm != null && !wm.Disabled)
|
|
{
|
|
/// Water meter did not pass
|
|
foreach (var mtr in wm.MeterTestRslts)
|
|
{
|
|
/// Find test entitled 'Kontrola montaze'
|
|
if (mtr.TestData().Evaluate && (mtr.TestData().Name == "Kontrola montaze") && (mtr.TestData().Method == "iPerlCommunication"))
|
|
{
|
|
/// This meter test result (mtr) is 'Kontrola montaze'
|
|
if (wm.LastRecordIsNok)
|
|
{
|
|
/// There is still a production tracing error, last record is missing
|
|
wm.ErrorFlags |= (int)ErrorFlagMask.E28; /// Set E28
|
|
}
|
|
else
|
|
{
|
|
/// No production tracing error, last record is OK
|
|
wm.ErrorFlags &= ~(int)ErrorFlagMask.E28; /// Clear E28
|
|
}
|
|
|
|
if ((wm.ErrorFlags & (int)ErrorFlagMask.E28) != 0)
|
|
{
|
|
/// Previous workstep missing or NOK (production tracing error)
|
|
mtr.ErrorIndicators |= (int)ErrorFlagMask.E28;
|
|
mtr.Passed = false;
|
|
}
|
|
else
|
|
{
|
|
/// Previous step is OK
|
|
mtr.Passed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Redraw on-screen results
|
|
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(string.Empty, null));
|
|
}
|
|
}
|
|
|
|
if (selection == Selection.Cycle || selection == Selection.RestOfCycle ||
|
|
selection == Selection.Test || selection == Selection.Q1 || selection == Selection.Q2 || selection == Selection.Q3)
|
|
{
|
|
goto cycle_or_test_selected;
|
|
}
|
|
else if (selection == Selection.RestoreInterruptedSession)
|
|
{
|
|
/// Make progress bars of completed test green
|
|
foreach (var testRslt in BatchRslts.Batch.TestRslts)
|
|
{
|
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(testRslt));
|
|
}
|
|
|
|
/// TODO: Try to find out where the cycle stopped
|
|
}
|
|
else
|
|
{
|
|
/// Do nothing
|
|
}
|
|
|
|
select_cycle_or_test:
|
|
|
|
//----------------------------------------------------------
|
|
selection = MakeSelection(MKSelContext.InsideProcedure);
|
|
if (selection == Selection.Shutdown)
|
|
{
|
|
Shutdown();
|
|
return;
|
|
}
|
|
switch (selection)
|
|
{
|
|
case Selection.Q1: selectedTestName = "Q1"; break;
|
|
case Selection.Q2: selectedTestName = "Q2"; break;
|
|
case Selection.Q3: selectedTestName = "Q3"; break;
|
|
default:
|
|
selectedTestName = Program.MainWnd.BenchControlPanel.TestName;
|
|
break;
|
|
}
|
|
///
|
|
Bridge.OnError(this, string.Empty); /// Clear an error message (if any)
|
|
///
|
|
if (selection == Selection.PurgeBegin) goto fill_the_bench;
|
|
if (selection == Selection.PurgeEnd)
|
|
{
|
|
FillState = FillState.Unknown; /// Enfoce evacuation
|
|
switch (DoEvacuation(purgeEnd))
|
|
{
|
|
case Event.Error: goto error;
|
|
case Event.UiCmdStop: goto stop;
|
|
default: goto select_cycle_or_test;
|
|
}
|
|
}
|
|
if (selection == Selection.Break)
|
|
{
|
|
if (StateMachine.ControlBoardMain is ControlBoard.Uni.UniCB)
|
|
{
|
|
(StateMachine.ControlBoardMain as ControlBoard.Uni.UniCB).IsUIBlocked = false;
|
|
}
|
|
Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty);
|
|
Bridge.OnProcedureCompleted(this, new ProcedureCompletedEventArgs(StateMachine.Procedure));
|
|
goto select_procedure;
|
|
}
|
|
if (selection == Selection.SaveResults) goto save_results;
|
|
|
|
cycle_or_test_selected:
|
|
|
|
Bridge.OnError(this, string.Empty); /// Clear an error message (if any)
|
|
|
|
if (UIFlowControl.Stop == WaitBeginFormClosed())
|
|
{
|
|
goto stop_within_cycle; /// Make sure the entry form is closed
|
|
}
|
|
|
|
Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Hide buttons
|
|
|
|
if (selection != Selection.Cycle)
|
|
{
|
|
//--------------------------------
|
|
State.Create("MainSeq : Continue in the cycle?")
|
|
.AddOperation(new Operations.AskYesNoOp(Strings.Continue_in_the_cycle))
|
|
.AddOperation(checkUiOp)
|
|
.EnterState();
|
|
while (true)
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Yes))
|
|
{
|
|
selection = Selection.RestOfCycle;
|
|
break;
|
|
}
|
|
if (e.Contains(Event.No)) break;
|
|
if (e.Contains(Event.UiCmdStop)) goto select_procedure;
|
|
}
|
|
}
|
|
|
|
///------------------------------------------------------------------------------------------------------------
|
|
if (selection == Selection.Cycle || selection == Selection.RestOfCycle)
|
|
{
|
|
/// A sequence of tests will be executed
|
|
|
|
IList<DeferredTestEvaluationData> deferredData = new List<DeferredTestEvaluationData>();
|
|
bool veryFirstTestInTheRestOfCycle = true;
|
|
|
|
int selsctedTestIx = -1; ///= undefined
|
|
///
|
|
if (selection == Selection.RestOfCycle) /// ... otherwise
|
|
{
|
|
log.InfoFormat(
|
|
"RestOfCycle requested from selectedTestName={0}",
|
|
selectedTestName);
|
|
|
|
for (int i = 0; i < StateMachine.TestInstances.Length; i++)
|
|
{
|
|
if (selectedTestName == StateMachine.TestInstances[i].Name)
|
|
{
|
|
selsctedTestIx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((selsctedTestIx < simultWithPurgingCount) ||
|
|
(selsctedTestIx >= StateMachine.TestInstances.Length - simultWithEvacuationCount))
|
|
{
|
|
/// Invalid test selection
|
|
Bridge.OnError(this, string.Format("No test specified"));
|
|
goto select_cycle_or_test;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
selsctedTestIx = simultWithPurgingCount; /// Applies when selection == Selection.Cycle
|
|
}
|
|
|
|
|
|
double TimeEstimateTotal = 0; /// Time estimate of the selected cycle or test
|
|
|
|
for (int i = selsctedTestIx; i < StateMachine.TestInstances.Length - simultWithEvacuationCount; i++)
|
|
{
|
|
Test test = StateMachine.TestInstances[i].Test;
|
|
|
|
TimeEstimateTotal += (test.TestTime + 10.0);
|
|
|
|
/// Try to fetch all test paths and transitions
|
|
/// to detect configuration errors as early as possible.
|
|
TBF.Rig.Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method);
|
|
string errorMsg;
|
|
if (!(testMethodComp is TBF.Rig.TestMethods.OuterLoop.Start.Component) &&
|
|
!(testMethodComp is TBF.Rig.TestMethods.OuterLoop.End.Component) &&
|
|
!StateMachine.GetPaths(test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter),
|
|
out inPath, out benchPath, out outPath, out sensPath,
|
|
out heatMetersPath,
|
|
out transitionBefore, out transitionBetween, out transitionAfter,
|
|
out errorMsg))
|
|
{
|
|
Bridge.OnError(this, errorMsg);
|
|
goto select_cycle_or_test;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Data Collector AFTER ? if exist, then check collector and test
|
|
*/
|
|
bool collectDataAfterTests = false;
|
|
TBF.Rig.Generic.IComponent collector = TbfComponents.FindFirstSequenceComponentImpl<IProcedureCameraCollect>();
|
|
|
|
int currentTestIx = selsctedTestIx;
|
|
while (currentTestIx < StateMachine.TestInstances.Length - simultWithEvacuationCount)
|
|
{
|
|
TestInstance nextTest = (currentTestIx + 1 < StateMachine.TestInstances.Length - simultWithEvacuationCount)
|
|
? StateMachine.TestInstances[currentTestIx + 1]
|
|
: null;
|
|
|
|
Test nextHydroTest = null;
|
|
for (int i = currentTestIx + 1; i < StateMachine.TestInstances.Length - simultWithEvacuationCount; i++)
|
|
{
|
|
Test tst = StateMachine.TestInstances[i].Test;
|
|
if (tst != null)
|
|
{
|
|
ITestMethod tm = TbfComponents.FindComponent(tst.Method) as ITestMethod;
|
|
if (tm != null && tm.DoTransitions())
|
|
{
|
|
nextHydroTest = tst;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nextHydroTest != null)
|
|
{
|
|
/// Fetch paths and 'transition before' of the next test
|
|
TBF.Rig.Generic.IComponent nextTestMethodComp = TbfComponents.FindComponent(nextHydroTest.Method);
|
|
TransitionSequence dummy2, dummy3;
|
|
string errorMsg2;
|
|
if (!(nextTestMethodComp is TBF.Rig.TestMethods.OuterLoop.Start.Component) &&
|
|
!(nextTestMethodComp is TBF.Rig.TestMethods.OuterLoop.End.Component) &&
|
|
!StateMachine.GetPaths(nextHydroTest, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter),
|
|
out nextInPath, out nextBenchPath, out nextOutPath, out nextSensPath,
|
|
out nextHeatMetersPath,
|
|
out nextTransitionBefore, out dummy2, out dummy3,
|
|
out errorMsg2))
|
|
{
|
|
Bridge.OnError(this, errorMsg2);
|
|
goto select_cycle_or_test;
|
|
}
|
|
|
|
nextQfrom = nextHydroTest.QfromM3ph();
|
|
nextQto = nextHydroTest.QtoM3ph();
|
|
nextPumpPower = nextHydroTest.PumpPower;
|
|
nextShortPulses = nextHydroTest.ShortPulses;
|
|
nextPidCoef = (nextOutPath != null) ? nextOutPath.PidCoef : 1.0F;
|
|
}
|
|
else
|
|
{
|
|
/// Clear paths and 'transition before' of the next test it does not exist
|
|
nextInPath = null;
|
|
nextBenchPath = null;
|
|
nextOutPath = null;
|
|
nextSensPath = null;
|
|
nextHeatMetersPath = null;
|
|
nextTransitionBefore = null;
|
|
}
|
|
|
|
/// Fetch paths and transitions of this test
|
|
TestInstance testInst = StateMachine.TestInstances[currentTestIx];
|
|
|
|
/// Remember the current test so that "Continue in the cycle"
|
|
/// can restart from the interrupted test.
|
|
selectedTestName = testInst.Name;
|
|
log.InfoFormat(
|
|
"Cycle current test: index={0}, name={1}, selectedTestName updated",
|
|
currentTestIx,
|
|
selectedTestName);
|
|
|
|
TBF.Rig.Generic.IComponent testMethodComp =
|
|
TbfComponents.FindComponent(testInst.Test.Method);
|
|
|
|
string errorMsg;
|
|
if (!StateMachine.GetPaths(testInst.Test,
|
|
(StateMachine.Procedure.MetersKind == MetersKind.HeatMeter),
|
|
out inPath,
|
|
out benchPath,
|
|
out outPath,
|
|
out sensPath,
|
|
out heatMetersPath,
|
|
out transitionBefore,
|
|
out transitionBetween,
|
|
out transitionAfter,
|
|
out errorMsg))
|
|
{
|
|
Bridge.OnError(this, errorMsg);
|
|
goto select_cycle_or_test;
|
|
}
|
|
|
|
/// Update format for the water mass
|
|
if (outPath != null && outPath.Scale != null && !string.IsNullOrEmpty(outPath.Scale.Format))
|
|
{
|
|
StartMass.Format = outPath.Scale.Format;
|
|
EndMass.Format = outPath.Scale.Format;
|
|
}
|
|
|
|
|
|
ITestMethod testMethod = testMethodComp as ITestMethod;
|
|
if (testMethod != null && testMethod.CanTest(StateMachine.Procedure.MetersKind))
|
|
{
|
|
StateMachine.LoadTestParams(testInst.Test);
|
|
|
|
string errMsg;
|
|
if (!testMethod.CheckDeviceCaps(testInst.Test, outPath, out errMsg))
|
|
{
|
|
Bridge.OnError(this, errMsg);
|
|
goto select_cycle_or_test;
|
|
}
|
|
StateMachine.ControlBoardMain.Devices = outPath;
|
|
ProcessData.RegisterReaders = (sensPath != null && sensPath.RegisterReaders != null) ? sensPath.RegisterReaders : null;
|
|
|
|
/// Set temperature control setpoint
|
|
ITempControl tControl = TbfComponents.FindComponent(testInst.Test.TempControl) as ITempControl;
|
|
if (tControl != null) tControl.SetTemperatureSetpoint((testInst.Test.TempLimLo + testInst.Test.TempLimHi) / 2.0);
|
|
|
|
///
|
|
/// Execute one test (single repetition of a repeated test)
|
|
/// Previously:
|
|
/// e = testMethod.Execute(test, outerLoopMode, (outerLoopMode ? outerLoopCounter: repetNr));
|
|
///
|
|
Event rsltTransBefore = Event.Done;
|
|
Event rsltTransBetween = Event.Done;
|
|
Event rsltTransAfter = Event.Done;
|
|
{
|
|
int timeEstTransBefore = testMethod.DoTransitions() ? GetTransitionTimeEst(transitionBefore) : 1;
|
|
int timeEstTransBetween = testMethod.DoTransitions() ? GetTransitionTimeEst(transitionBetween) : 1;
|
|
int timeEstTransAfter = testMethod.DoTransitions() ? GetTransitionTimeEst(transitionAfter) : 1;
|
|
|
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 1, timeEstTransBefore, 1, 30, 0, Convert.ToInt32(testInst.Test.TestTime) + 15, timeEstTransAfter, 0 });
|
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(testInst.Test, testInst.Repetition, Progress.JustStarted));
|
|
|
|
bool currentTestFinished = true;
|
|
bool doOneMoreRepetition = false;
|
|
|
|
bool doExecuteTransitionBefore = (currentTestIx == simultWithPurgingCount) || (testInst.Test != StateMachine.TestInstances[currentTestIx - 1].Test) || veryFirstTestInTheRestOfCycle;
|
|
bool isLastRepetition = (currentTestIx == StateMachine.TestInstances.Length - simultWithEvacuationCount - 1) || (testInst.Test != StateMachine.TestInstances[currentTestIx + 1].Test);
|
|
veryFirstTestInTheRestOfCycle = false;
|
|
if (testMethod.DoTransitions())
|
|
{
|
|
/// Make a transition before a test and before each test repetition
|
|
rsltTransBefore = Transition(doExecuteTransitionBefore ? transitionBefore : null, TransitionContext.BeforeTest); /// Transition or SetRoute - start of test
|
|
log.InfoFormat("Test {0}: Transition({1}, BeforeTest) returned {2}", testInst.Name, (transitionBefore == null ? "null" : transitionBefore.Name), rsltTransBefore);
|
|
}
|
|
if (rsltTransBefore != Event.Done) break;
|
|
|
|
log.InfoFormat("Test {0}: Execute(., {1}, {2})", testInst.Name, testInst.Repetition, isLastRepetition);
|
|
e = testMethod.Execute(testInst.Test, testInst.Repetition, isLastRepetition);
|
|
|
|
if (testMethod is IProcedureCameraShowAfter)
|
|
{
|
|
collectDataAfterTests = collectDataAfterTests ? true : (testMethod as IProcedureCameraShowAfter).IsSupportedCollector(collector);
|
|
log.InfoFormat("Set After test method done! Name: {0}, Do collect: {1}", testMethod.Name,collectDataAfterTests);
|
|
}
|
|
|
|
if (e.Contains(Event.MakeSecondPass) && testMethod is ITestMethodWith2ndPass)
|
|
{
|
|
deferredData.Add(new DeferredTestEvaluationData(testInst.Test, testInst.Repetition, (testMethod as ITestMethodWith2ndPass).IntermediateData));
|
|
}
|
|
|
|
currentTestFinished = (rsltTransBefore == Event.Done && !e.Contains(Event.Error)
|
|
&& !e.Contains(Event.ConfigurationError)
|
|
&& !e.Contains(Event.OpArgumentError)
|
|
&& !e.Contains(Event.UiCmdStop));
|
|
|
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(testInst.Test, testInst.Repetition, currentTestFinished ? Progress.Completed
|
|
: Progress.Aborted));
|
|
|
|
if (testMethod.DoTransitions() && !e.Contains(Event.RecoverableError))
|
|
{
|
|
if (currentTestFinished && !isLastRepetition && !e.Contains(Event.ErrorFlagsStop))
|
|
{
|
|
/// Make a transition between two test repetitions
|
|
rsltTransBetween = Transition(transitionBetween, TransitionContext.BetweenTests); /// Transition or SetRoute - start of test
|
|
log.InfoFormat("Test {0}: Transition({1}, BetweenTests) returned {2}", testInst.Name, (transitionBetween == null ? "null" : transitionBetween.Name), rsltTransBetween);
|
|
}
|
|
else
|
|
{
|
|
/// Make a transition after the last test repetition
|
|
TransitionContext endContext =
|
|
!currentTestFinished ? TransitionContext.Stop
|
|
: ((nextTransitionBefore != null) && (nextTransitionBefore.Name.ToLower().Contains("fastflow"))) ? TransitionContext.AfterTestWithOverlap
|
|
: TransitionContext.AfterTest;
|
|
rsltTransAfter = Transition(transitionAfter, endContext); /// Transition or SetRoute - end of test
|
|
log.InfoFormat("Test {0}: Transition({1}, {2}) returned {3}", testInst.Name, (transitionAfter == null ? "null" : transitionAfter.Name), endContext, rsltTransAfter);
|
|
}
|
|
}
|
|
|
|
if (currentTestIx == StateMachine.TestInstances.Length - simultWithEvacuationCount - 1 &&
|
|
e.Contains(Event.EndSession))
|
|
{
|
|
goto save_results;
|
|
}
|
|
}
|
|
|
|
if (rsltTransBefore == Event.Error || rsltTransBetween == Event.Error|| e.Contains(Event.Error))
|
|
{
|
|
goto error;
|
|
}
|
|
else if (e.Contains(Event.ConfigurationError))
|
|
{
|
|
goto select_cycle_or_test; /// OR goto config_error; ???
|
|
}
|
|
else if (e.Contains(Event.OpArgumentError))
|
|
{
|
|
goto config_error;
|
|
}
|
|
else if (rsltTransBefore == Event.UiCmdStop || e.Contains(Event.UiCmdStop) || e.Contains(Event.RecoverableError) || e.Contains(Event.ErrorFlagsStop))
|
|
{
|
|
goto stop_within_cycle;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Bridge.OnError(this, string.Format(Strings.Method_0_cannot_be_used, testInst.Test.Method));
|
|
goto select_cycle_or_test;
|
|
}
|
|
|
|
currentTestIx++;
|
|
}
|
|
|
|
///
|
|
/// Execute deferred evaluations of tests that returned 'Event.MakeSecondPass' here
|
|
///
|
|
foreach (var dfrrdData in deferredData)
|
|
{
|
|
string errorMsg;
|
|
StateMachine.GetPaths(dfrrdData.Test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter),
|
|
out inPath, out benchPath, out outPath, out sensPath,
|
|
out heatMetersPath,
|
|
out transitionBefore, out transitionBetween, out transitionAfter,
|
|
out errorMsg);
|
|
|
|
ITestMethodWith2ndPass testMethod = TbfComponents.FindComponent(dfrrdData.Test.Method) as ITestMethodWith2ndPass;
|
|
|
|
if (testMethod != null && testMethod.CanTest(StateMachine.Procedure.MetersKind))
|
|
{
|
|
StateMachine.LoadTestParams(dfrrdData.Test);
|
|
|
|
StateMachine.ControlBoardMain.Devices = outPath;
|
|
ProcessData.RegisterReaders = (sensPath != null && sensPath.RegisterReaders != null) ? sensPath.RegisterReaders : null;
|
|
|
|
e = testMethod.Execute2ndPass(dfrrdData.Test, dfrrdData.RepetNr, dfrrdData.IntermediateData);
|
|
|
|
if (e.Contains(Event.Error)) goto error;
|
|
else if (e.Contains(Event.OpArgumentError)) goto config_error;
|
|
else if (e.Contains(Event.UiCmdStop)) goto stop_within_cycle;
|
|
}
|
|
}
|
|
|
|
deferredData.Clear();
|
|
|
|
//ON THE END run collector process if is actual
|
|
if (collector != null && collectDataAfterTests)
|
|
{
|
|
IProcedureCameraCollect collectorParent = collector as IProcedureCameraCollect;
|
|
collectorParent.DefineParentProcess(StateMachine.Procedure);
|
|
|
|
for (int i = 0; i < StateMachine.TestInstances.Length - simultWithEvacuationCount; i++)
|
|
{
|
|
try
|
|
{
|
|
Test test = StateMachine.TestInstances[i].Test;
|
|
TestInstance testInst = StateMachine.TestInstances[i];
|
|
ITestMethod testMethod = collector as ITestMethod; //Found Process to run - data collection
|
|
log.InfoFormat("Test {0}: Execute(., {1}, {2})", testInst.Name, testInst.Repetition, true);
|
|
e = testMethod.Execute(testInst.Test, testInst.Repetition, true);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
log.ErrorFormat("Read ",exception);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
///------------------------------------------------------------------------------------------------------------
|
|
else
|
|
{
|
|
/// selection == Selection.Test or Selection.Q1 or Selection.Q2 or Selection.Q3
|
|
/// Single test will be executed
|
|
|
|
int testIx = -1; ///= undefined
|
|
///
|
|
for (int i = 0; i < StateMachine.TestInstances.Length; i++)
|
|
{
|
|
if (selectedTestName == StateMachine.TestInstances[i].Name)
|
|
{
|
|
testIx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (testIx < 0)
|
|
{
|
|
/// Invalid test selection
|
|
Bridge.OnError(this, string.Format("No test specified"));
|
|
goto select_cycle_or_test;
|
|
}
|
|
|
|
Test test = StateMachine.TestInstances[testIx].Test;
|
|
int repetNr = StateMachine.TestInstances[testIx].Repetition;
|
|
|
|
/// Fetch the test paths and transitions
|
|
string errorMsg;
|
|
TBF.Rig.Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method);
|
|
if (!(testMethodComp is TBF.Rig.TestMethods.OuterLoop.Start.Component) &&
|
|
!(testMethodComp is TBF.Rig.TestMethods.OuterLoop.End.Component) &&
|
|
!StateMachine.GetPaths(test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter),
|
|
out inPath, out benchPath, out outPath, out sensPath,
|
|
out heatMetersPath,
|
|
out transitionBefore, out transitionBetween, out transitionAfter,
|
|
out errorMsg))
|
|
{
|
|
Bridge.OnError(this, errorMsg);
|
|
goto select_cycle_or_test;
|
|
}
|
|
|
|
/// Update format for the water mass
|
|
StartMass.Format = "F3";
|
|
EndMass.Format = "F3";
|
|
|
|
/*
|
|
* Data Collector AFTER ? if exist, then check collector and test
|
|
*/
|
|
bool collectDataAfterTests = false;
|
|
TBF.Rig.Generic.IComponent collector = TbfComponents.FindFirstSequenceComponentImpl<IProcedureCameraCollect>();
|
|
|
|
ITestMethod testMethod = TbfComponents.FindComponent(test.Method) as ITestMethod;
|
|
if (testMethod != null && testMethod.CanTest(StateMachine.Procedure.MetersKind))
|
|
{
|
|
StateMachine.LoadTestParams(test);
|
|
string errMsg;
|
|
if (!testMethod.CheckDeviceCaps(test, outPath, out errMsg))
|
|
{
|
|
Bridge.OnError(this, errMsg);
|
|
goto select_cycle_or_test;
|
|
}
|
|
StateMachine.ControlBoardMain.Devices = outPath;
|
|
ProcessData.RegisterReaders = (sensPath != null && sensPath.RegisterReaders != null) ? sensPath.RegisterReaders : null;
|
|
|
|
/// Set temperature control setpoint
|
|
ITempControl tControl = TbfComponents.FindComponent(test.TempControl) as ITempControl;
|
|
if (tControl != null) tControl.SetTemperatureSetpoint((test.TempLimLo + test.TempLimHi) / 2.0);
|
|
|
|
Event rsltTransBefore = Event.Done;
|
|
Event rsltTransAfter = Event.Done;
|
|
{
|
|
int timeEstTransBefore = testMethod.DoTransitions() ? GetTransitionTimeEst(transitionBefore) : 1;
|
|
int timeEstTransBetween = testMethod.DoTransitions() ? GetTransitionTimeEst(transitionBetween) : 1;
|
|
int timeEstTransAfter = testMethod.DoTransitions() ? GetTransitionTimeEst(transitionAfter) : 1;
|
|
|
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 1, timeEstTransBefore, 1, 30, 0, Convert.ToInt32(test.TestTime) + 15, timeEstTransAfter, 0 });
|
|
/// start, transition, flow detection, flow setting, aborted, test, transition, end
|
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetNr, Progress.JustStarted));
|
|
|
|
if (testMethod.DoTransitions())
|
|
{
|
|
rsltTransBefore = Transition(transitionBefore, TransitionContext.BeforeTest); /// Transition or SetRoute - start of test
|
|
}
|
|
|
|
if (rsltTransBefore == Event.Done)
|
|
{
|
|
e = testMethod.Execute(test, repetNr, true);
|
|
|
|
if (testMethod is IProcedureCameraShowAfter)
|
|
{
|
|
collectDataAfterTests = collectDataAfterTests ? true : (testMethod as IProcedureCameraShowAfter).IsSupportedCollector(collector);
|
|
log.InfoFormat("Set After test method done! Name: {0}, Do collect: {1}", testMethod.Name,collectDataAfterTests);
|
|
}
|
|
|
|
if (e.Contains(Event.MakeSecondPass) && testMethod is ITestMethodWith2ndPass)
|
|
{
|
|
ITestMethodWith2ndPass tm2 = testMethod as ITestMethodWith2ndPass;
|
|
e = tm2.Execute2ndPass(test, repetNr, tm2.IntermediateData);
|
|
}
|
|
}
|
|
|
|
bool testFinished = (rsltTransBefore == Event.Done && !e.Contains(Event.Error)
|
|
&& !e.Contains(Event.ConfigurationError)
|
|
&& !e.Contains(Event.OpArgumentError)
|
|
&& !e.Contains(Event.UiCmdStop));
|
|
|
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetNr, testFinished ? Progress.Completed
|
|
: Progress.Aborted));
|
|
|
|
//ON THE END run collector process if is actual (defined and actual process supports it)
|
|
if (testFinished && collector != null && collectDataAfterTests)
|
|
{
|
|
e = RunCollector(collector, test, repetNr);
|
|
}
|
|
|
|
if (testMethod.DoTransitions())
|
|
{
|
|
TransitionContext endContext = testFinished ? TransitionContext.AfterTest : TransitionContext.Stop;
|
|
rsltTransAfter = Transition(transitionAfter, endContext); /// Transition or SetRoute - end of test
|
|
}
|
|
|
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetNr, testFinished ? Progress.Completed
|
|
: Progress.Aborted));
|
|
}
|
|
|
|
if (rsltTransBefore == Event.Error || e.Contains(Event.Error)) goto error;
|
|
if (e.Contains(Event.ConfigurationError)) goto config_error;
|
|
if (e.Contains(Event.OpArgumentError)) goto config_error;
|
|
if (rsltTransBefore == Event.UiCmdStop || e.Contains(Event.UiCmdStop)) goto stop_within_cycle;
|
|
}
|
|
else
|
|
{
|
|
Bridge.OnError(this, string.Format("{0} cannot be used", test.Method));
|
|
goto select_cycle_or_test;
|
|
}
|
|
}
|
|
///------------------------------------------------------------------------------------------------------------
|
|
|
|
goto select_cycle_or_test;
|
|
|
|
|
|
save_results:
|
|
|
|
Bridge.OnError(this, string.Empty); /// Clear an error message (if any)
|
|
Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Hide most of buttons
|
|
|
|
if (State.LastEvents.Contains(Event.ModelessFormIsOpen))
|
|
{
|
|
if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop;
|
|
}
|
|
else if (State.LastEvents.Contains(Event.ModelessFormClosed))
|
|
{
|
|
CloseBeginForm();
|
|
}
|
|
|
|
Bridge.OnActivity(this, Strings.Enter_protocol_data);
|
|
|
|
//--------------------------------
|
|
IDataEntry dataEntryCmpnt = TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as IDataEntry;
|
|
if (dataEntryCmpnt is IHasCycleEndForm)
|
|
{
|
|
IOperation showCycleEndFormOp =
|
|
(dataEntryCmpnt as IHasCycleEndForm).ShowCycleEndFormOp(BatchRslts.Batch.WaterMeters);
|
|
|
|
if (showCycleEndFormOp != null)
|
|
{
|
|
/// Open the modeless form for the end of the cycle
|
|
State.Create("MainSeq : Enter end data")
|
|
.AddOperation(showCycleEndFormOp)
|
|
.AddOperation(checkUiOp)
|
|
.EnterState();
|
|
do {
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.UiCmdStop)) goto stop;
|
|
}
|
|
while (!e.Contains(Event.ModelessFormClosed));
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Update batch results, determine whether watermeters passed all required tests
|
|
///
|
|
|
|
State.Create("MainSeq : Collector")
|
|
.AddOperation(checkUiOp)
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.UiCmdStop)) goto stop;
|
|
} while (false);
|
|
|
|
//--------------------------------
|
|
{
|
|
TBF.Rig.Generic.IComponent collector =
|
|
TbfComponents.FindFirstSequenceComponentImpl<IProcedureCameraCollect>();
|
|
//ON THE END run collector process if is actual (defined and actual process supports it)
|
|
if (collector != null)
|
|
{
|
|
for (int i = 0; i < StateMachine.TestInstances.Length; i++)
|
|
{
|
|
int testIx = i;
|
|
Test test = StateMachine.TestInstances[testIx].Test;
|
|
int repetNr = StateMachine.TestInstances[testIx].Repetition;
|
|
e = RunCollector(collector, test, repetNr);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// Determine the end of the last test and save it as the batch end time
|
|
DateTime lastTestEndTime = DateTime.MinValue;
|
|
if (BatchRslts.Batch.TestRslts != null)
|
|
{
|
|
foreach (var tr in BatchRslts.Batch.TestRslts)
|
|
{
|
|
if (tr.EndTime > lastTestEndTime) lastTestEndTime = tr.EndTime;
|
|
}
|
|
}
|
|
BatchRslts.Batch.EndTime = lastTestEndTime;
|
|
BatchRslts.Batch.SaveTime = DateTime.Now;
|
|
|
|
Results.Utils.GetCounterStates(BatchRslts.Batch, Program.LocalSettings.Counters); /// Update counters
|
|
/// Remove results of internal tests
|
|
for (int i = BatchRslts.Batch.TestRslts.Count - 1; i >= 0; i--)
|
|
{
|
|
foreach (var wm in BatchRslts.Batch.WaterMeters)
|
|
{
|
|
for (int j = wm.MeterTestRslts.Count - 1; j >= 0; j--)
|
|
{
|
|
var mtr = wm.MeterTestRslts[j];
|
|
if ((mtr.Publish() == Publish.Never || mtr.Publish() == Publish.Internal) && !mtr.Evaluate())
|
|
{
|
|
wm.MeterTestRslts.RemoveAt(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
var tr = BatchRslts.Batch.TestRslts[i];
|
|
if ((tr.Publish() == Publish.Never || tr.Publish() == Publish.Internal) && !tr.Evaluate())
|
|
{
|
|
BatchRslts.Batch.TestRslts.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
/// (1) Set boolean WaterMeter.Passed variable, (2) Remove disabled water meters
|
|
for (int wmNr0 = BatchRslts.Batch.WaterMeters.Count - 1; wmNr0 >= 0; wmNr0--)
|
|
{
|
|
var wm = BatchRslts.Batch.WaterMeters[wmNr0];
|
|
if (wm.Q3Channel == 0){
|
|
if (wm.Disabled)
|
|
{
|
|
/// Do not save disabled watermeters to DB, remove them from the list
|
|
BatchRslts.Batch.WaterMeters.RemoveAt(wmNr0);
|
|
}
|
|
else
|
|
{
|
|
/// Determine whether the watermeter passed all required tests
|
|
wm.Passed = wm.PassedFromTests();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!wm.Disabled)
|
|
{
|
|
wm.Passed = wm.PassedFromTests();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------
|
|
Bridge.OnActivity(this, Strings.Saving_and_printing_results);
|
|
//------------------------------------------------------
|
|
|
|
/// Save results to 'Results' MySQL DB with RsltsSent = 0 before saving and printing elswhere
|
|
BatchRslts.Batch.RsltsSent = false;
|
|
Results.DB.SaveNewBatch(BatchRslts.Batch);
|
|
|
|
string[] writers = (StateMachine.Procedure.ResultsWriter != null) ? StateMachine.Procedure.ResultsWriter.Split(new char[] { '~' }) : new string[0];
|
|
string[] printers = (StateMachine.Procedure.ResultsPrinter != null) ? StateMachine.Procedure.ResultsPrinter.Split(new char[] { '~' }) : new string[0];
|
|
string[] eventTriggers = (StateMachine.Procedure.EventTriggers != null) ? StateMachine.Procedure.EventTriggers.Split(new char[] { '~' }) : new string[0];
|
|
|
|
/// we have poassibility print GROUP printing - we just check if exist some like this
|
|
printers = ImplementActiveGroupPrinters(printers);
|
|
|
|
///
|
|
string[] rsltProcessors = new string[writers.Length + printers.Length + eventTriggers.Length];
|
|
writers.CopyTo(rsltProcessors, 0);
|
|
printers.CopyTo(rsltProcessors, writers.Length);
|
|
eventTriggers.CopyTo(rsltProcessors, writers.Length + printers.Length);
|
|
///
|
|
int rpix = 0; /// Component index in AddOperation() loop, afterwards rsltProcessors.Length
|
|
try
|
|
{
|
|
State st = State.Create("MainSeq : Saving and printing results");
|
|
for (rpix = 0; rpix < rsltProcessors.Length; rpix++ )
|
|
{
|
|
var rp = TbfComponents.FindComponent(rsltProcessors[rpix]) as IResultsProcessor;
|
|
if (rp != null) st.AddOperation(rp.ProcessResultsOp(ProcessData.BatchRslts.Batch));
|
|
}
|
|
st.EnterState();
|
|
do {
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) break;
|
|
}
|
|
while (e.Contains(Event.Busy));
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
string rpName = (rpix < rsltProcessors.Length) ? rsltProcessors[rpix] : "???";
|
|
Bridge.OnError(this, string.Format(Strings.Component_0_crashed_Results_not_saved, rpName));
|
|
log.FatalFormat("FileWriter {0} crashed: {1}", rpName, exc.Message);
|
|
goto error;
|
|
}
|
|
if (e.Contains(Event.Error)) goto error;
|
|
|
|
/// --- REST API via Operation
|
|
try
|
|
{
|
|
//send REST API via Operation
|
|
IRestAPIAdapter adapter = TbfComponents.FindFirstComponentImpl<IRestAPIAdapter>() as IRestAPIAdapter;
|
|
if (adapter != null)
|
|
{
|
|
State st = State.Create("MainSeq : Send data via REST API");
|
|
//ProcessData.BatchRslts.Batch
|
|
st.AddOperation(new ApiMessageOp(adapter, new ApiDataLoad(ProcessData.BatchRslts)));
|
|
st.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) break;
|
|
if (e.Contains(Event.Error)) break;
|
|
} while (e.Contains(Event.Busy) && e.Contains(Event.Starting));
|
|
}
|
|
}
|
|
catch (Exception x)
|
|
{
|
|
Bridge.OnError(this, string.Format(Strings.Component_0_crashed_Results_not_saved, "API REST"));
|
|
log.FatalFormat("API call crashed: {1}", x.Message);
|
|
e.Add(Event.ErrorProcessingResults); // operation unsuccessful
|
|
}
|
|
|
|
|
|
///
|
|
if (!e.Contains(Event.ErrorProcessingResults))
|
|
{
|
|
/// Results successfully saved and printed => update Batch record in Results DB in MySQL
|
|
try
|
|
{
|
|
var dbConn = new MySql.Data.MySqlClient.MySqlConnection(Results.DB.ConnectionString);
|
|
dbConn.Open();
|
|
var cmd = dbConn.CreateCommand();
|
|
cmd.CommandText = string.Format("UPDATE `batch` SET `RsltsSent` = '1' WHERE `batch`.`BatchNr` = {0};", ProcessData.BatchRslts.Batch.BatchNr);
|
|
int rowsUpdated = cmd.ExecuteNonQuery();
|
|
cmd.Dispose();
|
|
dbConn.Close();
|
|
if (rowsUpdated != 1)
|
|
{
|
|
string msg = string.Format("Unable to update Batch.RsltsSent in local MySQL DB, BatchNr = {0}",
|
|
ProcessData.BatchRslts.Batch.BatchNr);
|
|
Bridge.OnError(this, msg);
|
|
log.Fatal(msg);
|
|
goto error;
|
|
}
|
|
}
|
|
/*catch (Exception exc)
|
|
{
|
|
string msg = string.Format("Unable to update Batch.RsltsSent in local MySQL DB, BatchNr = {0}",
|
|
ProcessData.BatchRslts.Batch.BatchNr);
|
|
Bridge.OnError(this, msg);
|
|
log.FatalFormat("{0}: {1}", msg, exc.Message);
|
|
goto error;
|
|
}*/
|
|
catch (Exception exc)
|
|
{
|
|
var batch = ProcessData.BatchRslts.Batch;
|
|
|
|
// ⚠️ Skladanie detailného logu do jedného reťazca
|
|
var logBuilder = new StringBuilder();
|
|
logBuilder.AppendLine("----------------- Unable to update Batch.RsltsSent in local MySQL DB, BatchNr = {0} ------------------");
|
|
logBuilder.AppendLine("❌ Chyba pri UPDATE `batch` SET `RsltsSent` = '1'");
|
|
logBuilder.AppendLine($"BatchNr = {batch.BatchNr}");
|
|
logBuilder.AppendLine($"SQL príkaz: UPDATE `batch` SET `RsltsSent` = '1' WHERE `batch`.`BatchNr` = {batch.BatchNr};");
|
|
logBuilder.AppendLine();
|
|
logBuilder.AppendLine("💥 Výnimka:");
|
|
logBuilder.AppendLine($" - Message: {exc.Message}");
|
|
logBuilder.AppendLine($" - StackTrace: {exc.StackTrace}");
|
|
logBuilder.AppendLine($" - InnerException: {(exc.InnerException != null ? exc.InnerException.Message : "null")}");
|
|
logBuilder.AppendLine();
|
|
logBuilder.AppendLine("📦 Batch obsah:");
|
|
|
|
// 💡 Dynamický výpis vlastností objektu Batch
|
|
var props = batch.GetType().GetProperties();
|
|
foreach (var prop in props)
|
|
{
|
|
object value = prop.GetValue(batch, null);
|
|
logBuilder.AppendLine($" - {prop.Name}: {value}");
|
|
}
|
|
|
|
// ✍️ Uloženie do vlastného logu
|
|
LiveLogCache.Instance.AddLog(logBuilder.ToString());
|
|
|
|
Bridge.OnError(this, "Chyba pri aktualizácii výsledkov v MySQL.");
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Save results to 'summary results' logger
|
|
///
|
|
log.WarnFormat("Saving SummaryResults of batch {0}", ProcessData.BatchRslts.Batch.BatchNr);
|
|
foreach (var tr in ProcessData.BatchRslts.Batch.TestRslts)
|
|
{
|
|
summaryResults.Info(TestResult2CsvLine(tr));
|
|
}
|
|
|
|
///
|
|
/// Clear a file with interim test results
|
|
///
|
|
ClearProcessDataFile();
|
|
|
|
Program.LocalSettings.BatchNr++;
|
|
Program.LocalSettings.Save();
|
|
|
|
log.FatalFormat("Measurement session saved: batch = {0}, procedure = {1}, next batch nr. = {2}",
|
|
ProcessData.BatchRslts.Batch.BatchNr,
|
|
ProcessData.BatchRslts.Batch.ProcedureName,
|
|
Program.LocalSettings.BatchNr);
|
|
|
|
if (StateMachine.ControlBoardMain is ControlBoard.Uni.UniCB)
|
|
{
|
|
(StateMachine.ControlBoardMain as ControlBoard.Uni.UniCB).IsUIBlocked = false;
|
|
}
|
|
Event evacRetv = DoEvacuation(purgeEnd);
|
|
|
|
///
|
|
/// Process statistics (in each regular cycle after evacuation when ProcessData.StatisticsMonitoringComp is defined)
|
|
///
|
|
if (ProcessData.StatisticsMonitoringComp is IStatisticsMonitoring)
|
|
{
|
|
Bridge.OnActivity(this, Strings.Processing_statistics);
|
|
|
|
State.Create("MainSeq : Processing statistics")
|
|
.AddOperation((ProcessData.StatisticsMonitoringComp as IStatisticsMonitoring).ProcessStatisticsOp(ProcessData.BatchRslts.Batch.BatchNr))
|
|
.AddOperation(checkUiOp)
|
|
.EnterState();
|
|
do {
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.UiCmdStop)) goto stop;
|
|
}
|
|
while (e.Contains(Event.Busy));
|
|
}
|
|
|
|
///
|
|
/// Procedure completed, branch depending on the result of evacuation
|
|
///
|
|
Bridge.OnProcedureCompleted(this, new ProcedureCompletedEventArgs(StateMachine.Procedure));
|
|
switch (evacRetv)
|
|
{
|
|
case Event.Error: goto error;
|
|
case Event.UiCmdStop: goto stop;
|
|
default: goto select_procedure;
|
|
}
|
|
|
|
|
|
stop_within_cycle:
|
|
//--------------------------------
|
|
State.Create("MainSeq : Turning IDLE -> Closing the valves")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(StateMachine.ControlBoardMain.SetValvesOp(StateMachine.DefaultValvesOpen,
|
|
StateMachine.DefaultValvesClose))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) goto error;
|
|
}
|
|
while (!e.Contains(Event.ValvesSet));
|
|
|
|
goto select_cycle_or_test;
|
|
|
|
stop:
|
|
//--------------------------------
|
|
State.Create("MainSeq : Turning IDLE -> Closing the valves")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(StateMachine.ControlBoardMain.SetValvesOp(StateMachine.DefaultValvesOpen,
|
|
StateMachine.DefaultValvesClose))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
if (e.Contains(Event.Error)) goto error;
|
|
}
|
|
while (!e.Contains(Event.ValvesSet));
|
|
|
|
goto select_procedure;
|
|
|
|
config_error:
|
|
//--------------------------------
|
|
State.Create("MainSeq : Procedure configuration error")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(StateMachine.BenchErrorOp)
|
|
.AddOperation(new Operations.MessageBoxOp("Test configuration error"))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
}
|
|
while (!e.Contains(Event.OK));
|
|
|
|
goto select_cycle_or_test;
|
|
|
|
error:
|
|
log.Error("Error tag in MainSequence!");
|
|
//--------------------------------
|
|
State.Create("MainSeq : ERROR -> Closing the valves")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(StateMachine.BenchErrorOp)
|
|
.AddOperation(StateMachine.ControlBoardMain.SetValvesOp(StateMachine.DefaultValvesOpen,
|
|
StateMachine.DefaultValvesClose))
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
}
|
|
while (!e.Contains(Event.ValvesSet) && !e.Contains(Event.Error));
|
|
|
|
//--------------------------------
|
|
State.Create("MainSeq : ERROR state")
|
|
.AddOperation(checkUiOp)
|
|
.AddOperation(StateMachine.BenchErrorOp)
|
|
.EnterState();
|
|
do
|
|
{
|
|
e = StateMachine.WaitRunDevsRunOps();
|
|
}
|
|
while (!e.Contains(Event.UiCmdShutdown));
|
|
|
|
Shutdown(true);
|
|
return;
|
|
}
|
|
|
|
private static IList<Event> RunCollector(IComponent collector, Test test, int repetNr)
|
|
{
|
|
IProcedureCameraCollect collectorParent = collector as IProcedureCameraCollect;
|
|
collectorParent.DefineParentProcess(StateMachine.Procedure);
|
|
ITestMethod testMethodCollector = collector as ITestMethod;
|
|
|
|
IList<Event> e = null;
|
|
if (testMethodCollector != null &&
|
|
testMethodCollector.CanTest(StateMachine.Procedure.MetersKind))
|
|
{
|
|
try
|
|
{
|
|
log.InfoFormat("Test single {0}: Execute(., {1}, {2})", test.Name, repetNr,
|
|
true);
|
|
e = testMethodCollector.Execute(test, repetNr, true);
|
|
log.DebugFormat("Collector with name: {0} done with Events:{1} ", test.Name, e);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
log.ErrorFormat("Read ", exception);
|
|
}
|
|
}
|
|
|
|
return e;
|
|
}
|
|
|
|
|
|
bool IsApprovedByLegalizator()
|
|
{
|
|
if (isApprovedByLegalizator && DateTime.Now < lastApprovalByLegalizatorTime.Date.AddDays(1))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var loginDlg = new SharedDatabase.Forms.PlainLoginDlg(new GID[] { GID.CalibrationSpecialists }, "Approval by legalizator");
|
|
if (loginDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
|
{
|
|
isApprovedByLegalizator = true;
|
|
legalizatorName = loginDlg.FullName;
|
|
lastApprovalByLegalizatorTime = DateTime.Now;
|
|
return true;
|
|
}
|
|
|
|
legalizatorName = string.Empty;
|
|
return false;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// MakeSelection() call context
|
|
/// </summary>
|
|
enum MKSelContext
|
|
{
|
|
ProcedureNotSelected,
|
|
InsideProcedure,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return values of MakeSelection()
|
|
/// </summary>
|
|
public enum Selection
|
|
{
|
|
PurgeBegin,
|
|
PurgeEnd,
|
|
Break,
|
|
Cycle,
|
|
RestOfCycle,
|
|
Test,
|
|
Q1,
|
|
Q2,
|
|
Q3,
|
|
SaveResults,
|
|
RestoreBatch,
|
|
RestoreAndFixBatch,
|
|
Shutdown,
|
|
RestoreInterruptedSession,
|
|
}
|
|
}
|
|
}
|