diff --git a/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs b/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs
index 4e1fae51..6fecf460 100644
--- a/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs
+++ b/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs
@@ -178,7 +178,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel
try
{
- _processCtrl = new EolProcessController(Slot);
+ _processCtrl = new EolStateMachine(Slot);
}
catch (Exception ex)
{
diff --git a/Common/Production/ProductionUiCordonel/Picking.xaml.cs b/Common/Production/ProductionUiCordonel/Picking.xaml.cs
index 72e42923..7ec51aff 100644
--- a/Common/Production/ProductionUiCordonel/Picking.xaml.cs
+++ b/Common/Production/ProductionUiCordonel/Picking.xaml.cs
@@ -178,7 +178,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel
try
{
- _processCtrl = new EolProcessController(Slot);
+ _processCtrl = new EolStateMachine(Slot);
}
catch (Exception ex)
{
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProcessController.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProcessController.cs
index 8ddac59b..c3783ef1 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProcessController.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProcessController.cs
@@ -297,13 +297,200 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
///
private void TmrProcessCtrlCycle_Elapsed(Object state)
{
- StateMachine();
+ GenericStateMachine();
}
#endregion --------------------------------------- Events -----------------------------------------------------
#region ------------------------------------------ State Machine ----------------------------------------------
- public abstract void StateMachine();
+ ///
+ public abstract void IndividualStateMachine(IProductionProcess process);
+
+ ///
+ /// State machine of ProcessController which serves as template for all production processes.
+ ///
+ ///
+ /// INSTRUCTION FOR NORMAL USAGE:
+ /// -----------------------------
+ /// Call the SetupProcess() with the
+ /// - new process automatically collected from with new
+ /// _actualProcessState as input,
+ /// - successExitState set to the next required state after successfully execution.
+ /// That's it! The normal state change has always only one production process active and waits for completion
+ /// before changing to a new state and therefore a new production process.
+ ///
+ /// If a special state is needed on errorExitState or breakExitState these can be assigned. Otherwise, the
+ /// errorExitState is linked to the error state, the breakExitState to the stop state.
+ ///
+ ///
+ /// INSTRUCTION FOR NON-BLOCKING MULTIPLE PROCESSES SIMULTANEOUSLY ACTIVITIES:
+ /// --------------------------------------------------------------------------
+ /// Sometimes production processes may be able to be executed simultaneously as they are independent of each
+ /// other. One example is a database access for data collection from different tables.
+ ///
+ /// Call the SetupProcess with the
+ /// - new process automatically collected from with new
+ /// _actualProcessState as input,
+ /// - successExitState being set to (null).
+ /// This will lock the sate change after completion as multiple processes may be active and a state change after
+ /// completion may cause unpredictable operation, the state is already where it should be (manually changed),
+ /// - change the state after the SetupProcess() call manually.
+ ///
+ /// This is needed for non-blocking immediately new state change (not waiting for the successful execution of
+ /// the actual new assigned process):
+ /// E.g. all DB accesses need a certain time to get data, kicking off (fire and forget) the process without
+ /// waiting for the result, the exitSuccessState has to be set to null to avoid a state change on successfully
+ /// execution of the process. Instead, change the state here to go ahead with the next state. This forces a wait
+ /// on the state who needs the data from the "fire and forget" states, SEE next instruction how to proceed!
+ ///
+ ///
+ /// INSTRUCTION TO DELAY THE START OF A PROCESS:
+ /// --------------------------------------------
+ /// Each new process execution can be delayed as it may need the result of another process which is active.
+ ///
+ /// Wait for a single process to complete:
+ /// - set the "waitForSingleProcess" to the process to wait for.
+ /// Wait for all preceding processes to complete:
+ /// - set the "waitForAllProcesses" to true.
+ ///
+ ///
+ ///
+ /// - Initial
+ ///
+ private void GenericStateMachine()
+ {// avoid repeated execution of the state machine on unchanged state
+ if (_stateMachineState == _lockedProcessState)
+ {
+ Thread.Sleep(ProcessTimerCycleMs >> 1);
+ }
+ else
+ {
+ try
+ {
+ // remind backup state to avoid repeated execution and side effects
+ _lockedProcessState = _stateMachineState;
+
+ // signal overall process progress to GUI based on ready processes
+ CalcAndPushOverAllProgress();
+
+ // signal state change to logger
+ OverallProcessStateChanged(this, new ProcessStateArgs(_stateMachineState));
+
+ // get the actual required process from the state definition list
+ var process = _processStateDef?.GetProcessOfState(_stateMachineState);
+
+ switch (_stateMachineState)
+ {
+ case ProcessState.Idle:
+ // This state needs an external state change like user input to go ahead
+ break;
+
+ case ProcessState.DetectCordonel:
+ // Wait for cancellation
+ if (_cancellationToken.IsCancellationRequested)
+ {
+ Thread.Sleep(1000);
+ // Reset the cancellation request
+ _cancellationTokenSource?.Dispose();
+ _cancellationTokenSource = new CancellationTokenSource();
+ _cancellationToken = _cancellationTokenSource.Token;
+ }
+
+ // Set up the counter for maximum overall process progress bar in GUI
+ CalcAndPushMaxOverAllProcessSteps();
+
+ // Detection of Cordonel has to be completed before assigning next state, so leave to automatic
+ // to change the state after successfully execution. The detection is the base for all others.
+ StartProcess(process, ProcessState.CheckNewMeter);
+ break;
+
+ case ProcessState.CheckNewMeter:
+ // Detection of Cordonel has to be completed before assigning next state. It has to be checked if
+ // the meter changed to clear all collected contents of previous run. To UPDATE ALL INFORMATION after
+ // new meter assignment the "DetectCordonel" has to be repeated to return here "Old Meter" and then
+ // enter the "ConnectCordonel"!
+ _stateMachineState = CheckForNewMeter() ? ProcessState.DetectCordonel : ProcessState.ConnectCordonel;
+ break;
+
+ case ProcessState.ConnectCordonel:
+ // Precondition: - The detection process has to be completed as the PcbId is needed.
+ // AVOID to change the process state on completion as parallel process is active!
+ StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion);
+ // Do not wait on completion as new parallel process can be started by manually state change.
+ _stateMachineState = ProcessState.GetSerialNumberAndRadioAddress;
+ break;
+
+ case ProcessState.GetSerialNumberAndRadioAddress:
+ // Precondition: - The detection process has to be completed as the PcbId is needed.
+ // AVOID to change the process state on completion as parallel process is active!
+ StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion);
+ // Do not wait on completion as new parallel process can be started by manually state change.
+ _stateMachineState = ProcessState.GetProgrammingParameters;
+ break;
+
+ case ProcessState.CheckOrderNumber:
+ // This scans the order number, it has to be executed exclusively with automatic
+ StartProcess(process, ProcessState.CheckSerialNumber, waitForAllProcesses: true);
+ break;
+
+ case ProcessState.CheckSerialNumber:
+ // This scans the serial number, it has to be executed exclusively with automatic
+ StartProcess(process, ProcessState.CheckAttachments);
+ break;
+
+ case ProcessState.RepeatFailedTests:
+ _stateMachineState = RepeatFailedTests();
+ break;
+
+ case ProcessState.PrintReturnReport:
+ _stateMachineState = ProcessState.Idle;
+ break;
+
+ case ProcessState.PrintSuccessReport:
+ _stateMachineState = ProcessState.Idle;
+ break;
+
+ case ProcessState.AbortTest:
+ AbortProcesses();
+ _stateMachineState = ProcessState.Idle;
+ break;
+
+ case ProcessState.Stop:
+ KillProcesses();
+ _stateMachineState = ProcessState.Idle;
+ break;
+
+ case ProcessState.Error:
+ // Common error handling routine
+ ProcessErrorHandler(_stateChangeRequestProcess);
+ // Start the error handler with its user feedback request. It has to be started
+ // always even if the abortion of all processes is required! The error handler
+ // will change the exit state based on the user input.
+ StartProcess(process, ProcessState.Idle, startAlways: true);
+ break;
+
+ case ProcessState.StateListDelimiter:
+ _stateMachineState = ProcessState.Idle;
+ break;
+
+ default:
+ IndividualStateMachine(process);
+ break;
+ }
+ }
+ catch (ThreadAbortException ex)
+ {
+ _genesisMeter?.WriteLog(ex.Message);
+ _stateMachineState = ProcessState.Idle;
+ }
+ catch (Exception ex)
+ {
+ _genesisMeter?.WriteLog(ex.Message);
+ _stateMachineState = ProcessState.Error;
+ }
+ }
+ }// state locked against repeated execution
+
#endregion --------------------------------------- State Machine ----------------------------------------------
#region ------------------------------------------ Tools ------------------------------------------------------
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs
index 741e8986..79360a99 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs
@@ -292,7 +292,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
///
public void StartProcess(ProcessState? successExitState, ProcessState errorExitState = ProcessState.Error,
- ProcessState breakExitState = ProcessState.AbortFinalTest)
+ ProcessState breakExitState = ProcessState.AbortTest)
{
if (Meter == null)
{
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/ProcessState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/ProcessState.cs
index fd68e028..b15cb83e 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/ProcessState.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/ProcessState.cs
@@ -19,17 +19,17 @@
///
Error,
///
- /// Abort final test execution
+ /// Abort test execution
///
- AbortFinalTest,
+ AbortTest,
///
- /// Repeat the entire final test
+ /// Repeat the entire test
///
RepeatFailedTests,
///
/// Final test failed
///
- FinalTestFailed,
+ TestFailed,
///
/// User stopped process
///
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs
index 72993b35..bc596ccf 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs
@@ -15,8 +15,8 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
using Xylem.Common.Logic.ProductionOrderCore.TestResults;
using Xylem.Common.Production.ProductionUiCordonel.Model;
-using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses;
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
+using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessController.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessController.cs
deleted file mode 100644
index 58041c78..00000000
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessController.cs
+++ /dev/null
@@ -1,314 +0,0 @@
-using System;
-using System.Threading;
-using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
-using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EventArgs;
-
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses
-{
- ///
- /// Preparing the Cordonel for shipping:
- /// - Setup device with standard parameters covered by the VAKO or customer specific CSD,
- /// - If radio is installed: radio test,
- /// - Requiring radio key from LuDB,
- /// - Requiring 7 passwords for the Cordonel access levels,
- /// - Building the password file (Level 3 is the modified skeleton key),
- /// - Store all configurations,
- /// - Reboot the Cordonel to load all settings from FLASH to RAM,
- /// - Configuration check of all parameters defined by VAKO and CSD.
- ///
- public sealed class EolProcessController : BaseProcessController, IProcessController
- {
- #region ------------------------------------------ Variables --------------------------------------------------
- //
- #endregion --------------------------------------- Variables --------------------------------------------------
- #region ------------------------------------------ Class ------------------------------------------------------
-
- ///
- /// Ctor
- ///
- /// physical slot for this meter
- ///
- /// - Initial
- ///
- public EolProcessController(Int32 slot) : base(slot)
- {
- }
-
- #endregion --------------------------------------- Class ------------------------------------------------------
- #region ------------------------------------------ Events -----------------------------------------------------
- //
- #endregion --------------------------------------- Events -----------------------------------------------------
- #region ------------------------------------------ State Machine ----------------------------------------------
- ///
- /// State machine of FinalProcessController which serves as preparation for SHIPPING named EOL (End-Of-Line).
- ///
- ///
- /// INSTRUCTION FOR NORMAL USAGE:
- /// -----------------------------
- /// Call the SetupProcess() with the
- /// - new process automatically collected from with new
- /// _actualProcessState as input,
- /// - successExitState set to the next required state after successfully execution.
- /// That's it! The normal state change has always only one production process active and waits for completion
- /// before changing to a new state and therefore a new production process.
- ///
- /// If a special state is needed on errorExitState or breakExitState these can be assigned. Otherwise, the
- /// errorExitState is linked to the error state, the breakExitState to the stop state.
- ///
- ///
- /// INSTRUCTION FOR NON-BLOCKING MULTIPLE PROCESSES SIMULTANEOUSLY ACTIVITIES:
- /// --------------------------------------------------------------------------
- /// Sometimes production processes may be able to be executed simultaneously as they are independent of each
- /// other. One example is a database access for data collection from different tables.
- ///
- /// Call the SetupProcess with the
- /// - new process automatically collected from with new
- /// _actualProcessState as input,
- /// - successExitState being set to (null).
- /// This will lock the sate change after completion as multiple processes may be active and a state change after
- /// completion may cause unpredictable operation, the state is already where it should be (manually changed),
- /// - change the state after the SetupProcess() call manually.
- ///
- /// This is needed for non-blocking immediately new state change (not waiting for the successful execution of
- /// the actual new assigned process):
- /// E.g. all DB accesses need a certain time to get data, kicking off (fire and forget) the process without
- /// waiting for the result, the exitSuccessState has to be set to null to avoid a state change on successfully
- /// execution of the process. Instead, change the state here to go ahead with the next state. This forces a wait
- /// on the state who needs the data from the "fire and forget" states, SEE next instruction how to proceed!
- ///
- ///
- /// INSTRUCTION TO DELAY THE START OF A PROCESS:
- /// --------------------------------------------
- /// Each new process execution can be delayed as it may need the result of another process which is active.
- ///
- /// Wait for a single process to complete:
- /// - set the "waitForSingleProcess" to the process to wait for.
- /// Wait for all preceding processes to complete:
- /// - set the "waitForAllProcesses" to true.
- ///
- ///
- ///
- /// - Initial
- ///
- public override void StateMachine()
- {
- // avoid repeated execution of the state machine on unchanged state
- if (_stateMachineState == _lockedProcessState)
- {
- Thread.Sleep(ProcessTimerCycleMs >> 1);
- }
- else
- {
- try
- {
- // remind backup state to avoid repeated execution and side effects
- _lockedProcessState = _stateMachineState;
-
- // signal overall process progress to GUI based on ready processes
- CalcAndPushOverAllProgress();
-
- // signal state change to logger
- OverallProcessStateChanged(this, new ProcessStateArgs(_stateMachineState));
-
- // get the actual required process from the state definition list
- var process = _processStateDef?.GetProcessOfState(_stateMachineState);
-
- switch (_stateMachineState)
- {
- case ProcessState.Idle:
- // This state needs an external state change like user input to go ahead
- break;
-
- case ProcessState.DetectCordonel:
- // Wait for cancellation
- if (_cancellationToken.IsCancellationRequested)
- {
- Thread.Sleep(1000);
- // Reset the cancellation request
- _cancellationTokenSource?.Dispose();
- _cancellationTokenSource = new CancellationTokenSource();
- _cancellationToken = _cancellationTokenSource.Token;
- }
-
- // Set up the counter for maximum overall process progress bar in GUI
- CalcAndPushMaxOverAllProcessSteps();
-
- // Detection of Cordonel has to be completed before assigning next state, so leave to automatic
- // to change the state after successfully execution. The detection is the base for all others.
- StartProcess(process, ProcessState.CheckNewMeter);
- break;
-
- case ProcessState.CheckNewMeter:
- // Detection of Cordonel has to be completed before assigning next state. It has to be checked if
- // the meter changed to clear all collected contents of previous run. To UPDATE ALL INFORMATION after
- // new meter assignment the "DetectCordonel" has to be repeated to return here "Old Meter" and then
- // enter the "ConnectCordonel"!
- _stateMachineState = CheckForNewMeter() ? ProcessState.DetectCordonel : ProcessState.ConnectCordonel;
- break;
-
- case ProcessState.ConnectCordonel:
- // Precondition: - The detection process has to be completed as the PcbId is needed.
- // AVOID to change the process state on completion as parallel process is active!
- StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion);
- // Do not wait on completion as new parallel process can be started by manually state change.
- _stateMachineState = ProcessState.GetSerialNumberAndRadioAddress;
- break;
-
- case ProcessState.GetSerialNumberAndRadioAddress:
- // Precondition: - The detection process has to be completed as the PcbId is needed.
- // AVOID to change the process state on completion as parallel process is active!
- StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion);
- // Do not wait on completion as new parallel process can be started by manually state change.
- _stateMachineState = ProcessState.GetProgrammingParameters;
- break;
-
- case ProcessState.GetProgrammingParameters:
- // Precondition: - The connection process has to be completed as a readout of some register
- // values from the Cordonel are needed to check the update capability:
- // - Wait on completed connection process before starting this process.
- // AVOID to change the process state on completion as parallel process is active!
- StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion,
- waitForSingleProcess: _processStateDef?.GetProcessOfState(ProcessState.ConnectCordonel));
- // Do not wait on completion as new parallel process can be started by manually state change.
- _stateMachineState = ProcessState.CheckProductionState;
- break;
-
- case ProcessState.CheckProductionState:
- // Precondition: - The connection process has to be completed as a readout of some register
- // values from the Cordonel are needed to check the update capability:
- // - Wait on completed connection process before starting this process.
- // AVOID to change the process state on completion as parallel process is active!
- StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion,
- waitForSingleProcess: _processStateDef?.GetProcessOfState(ProcessState.ConnectCordonel));
- // Do not wait on completion as new parallel process can be started by manually state change.
- _stateMachineState = ProcessState.ProcessPasswordFile;
- break;
-
- case ProcessState.ProcessPasswordFile:
- // Precondition: - The connection process has to be completed as a password change in the DB
- // will take place: Skeleton to Password Level 8. Not waiting for completion may cause side
- // effects on login. Wait for all processes to complete.
- // Leave state switch to automatic to avoid side effects on incomplete updated DB for next
- // steps.
- StartProcess(process, ProcessState.ExecFinalParametrization, waitForAllProcesses: true);
- break;
-
- case ProcessState.ExecFinalParametrization:
- // This writes all setups to the device, it has to be executed exclusively with automatic
- StartProcess(process, ProcessState.ExecStoreConfiguration);
- break;
-
- case ProcessState.ExecStoreConfiguration:
- // Precondition: - The final parametrization has to be finished as this shall be stored
- // to non-volatile memory and checked if remaining valid after the reboot.
- // Store configuration has to be executed exclusively with automatic
- StartProcess(process, ProcessState.RebootCordonel);
- break;
-
- case ProcessState.RebootCordonel:
- // Precondition: - The store configuration has to be executed to safe all settings
- // to non-volatile memory and checked if remaining valid after the reboot.
- // Reboot has to be executed exclusively with automatic
- StartProcess(process, ProcessState.CheckFinalParametrization);
- break;
-
- case ProcessState.CheckFinalParametrization:
- // Precondition: - The reboot process including the store all configurations has to be
- // completed.
- // Check final configuration has to be executed exclusively with automatic
- StartProcess(process, ProcessState.CheckRadio);
- break;
-
- case ProcessState.CheckRadio:
- // Precondition: - The final parametrization, reboot process including the store all
- // configurations and the check of all setups survived the reboot have to be completed.
- // Radio signal level check, skipped on NA region or if skipping is required by special
- // approval
- StartProcess(process, ProcessState.CheckOrderNumber);
- break;
-
- case ProcessState.CheckOrderNumber:
- // This scans the order number, it has to be executed exclusively with automatic
- StartProcess(process, ProcessState.CheckSerialNumber, waitForAllProcesses: true);
- break;
-
- case ProcessState.CheckSerialNumber:
- // This scans the serial number, it has to be executed exclusively with automatic
- StartProcess(process, ProcessState.CheckAttachments);
- break;
-
- case ProcessState.CheckAttachments:
- // Precondition: - All checks have to be executed with positive result
- StartProcess(process, ProcessState.ExecVisualInspection);
- break;
-
- case ProcessState.ExecVisualInspection:
- // Precondition: - All checks have to be executed with positive result
- StartProcess(process, ProcessState.PrepareShippingMode);
- break;
-
- case ProcessState.PrepareShippingMode:
- // Precondition: - All checks have to be executed with positive result
- StartProcess(process, ProcessState.ReadyForShipping);
- break;
-
- case ProcessState.ReadyForShipping:
- _stateMachineState = ProcessState.Idle;
- break;
-
- case ProcessState.RepeatFailedTests:
- _stateMachineState = RepeatFailedTests();
- break;
-
- case ProcessState.PrintReturnReport:
- _stateMachineState = ProcessState.Idle;
- break;
-
- case ProcessState.PrintSuccessReport:
- _stateMachineState = ProcessState.Idle;
- break;
-
- case ProcessState.AbortFinalTest:
- AbortProcesses();
- _stateMachineState = ProcessState.Idle;
- break;
-
- case ProcessState.Stop:
- KillProcesses();
- _stateMachineState = ProcessState.Idle;
- break;
-
- case ProcessState.Error:
- // Common error handling routine
- ProcessErrorHandler(_stateChangeRequestProcess);
- // Start the error handler with its user feedback request. It has to be started
- // always even if the abortion of all processes is required! The error handler
- // will change the exit state based on the user input.
- StartProcess(process, ProcessState.Idle, startAlways: true);
- break;
-
- case ProcessState.StateListDelimiter:
- default:
- _stateMachineState = ProcessState.Idle;
- break;
- }//
- }
- catch (ThreadAbortException ex)
- {
- _genesisMeter?.WriteLog(ex.Message);
- _stateMachineState = ProcessState.Idle;
- }
- catch (Exception ex)
- {
- _genesisMeter?.WriteLog(ex.Message);
- _stateMachineState = ProcessState.Error;
- }
- }
- }// state locked against repeated execution
-
- #endregion --------------------------------------- State Machine ----------------------------------------------
- #region ------------------------------------------ Tools ------------------------------------------------------
- //
- #endregion --------------------------------------- Tools ------------------------------------------------------
- }
-}
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStates.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStates.cs
index b7c8b4c9..5652ecf7 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStates.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStates.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses;
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
+using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses
@@ -60,7 +60,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
new ProcessStateStruct(
null,
- ProcessState.AbortFinalTest,
+ ProcessState.AbortTest,
Resources.StrStateSkipping,
false),
@@ -72,7 +72,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
new ProcessStateStruct(
null,
- ProcessState.FinalTestFailed,
+ ProcessState.TestFailed,
Resources.StrStateFinalTestFailed,
false),
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolStateMachine.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolStateMachine.cs
new file mode 100644
index 00000000..62c3fcd1
--- /dev/null
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolStateMachine.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Threading;
+using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
+using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EventArgs;
+
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses
+{
+ ///
+ /// Preparing the Cordonel for shipping:
+ /// - Setup device with standard parameters covered by the VAKO or customer specific CSD,
+ /// - If radio is installed: radio test,
+ /// - Requiring radio key from LuDB,
+ /// - Requiring 7 passwords for the Cordonel access levels,
+ /// - Building the password file (Level 3 is the modified skeleton key),
+ /// - Store all configurations,
+ /// - Reboot the Cordonel to load all settings from FLASH to RAM,
+ /// - Configuration check of all parameters defined by VAKO and CSD.
+ ///
+ public sealed class EolStateMachine : BaseProcessController, IProcessController
+ {
+ #region ------------------------------------------ Variables --------------------------------------------------
+ //
+ #endregion --------------------------------------- Variables --------------------------------------------------
+ #region ------------------------------------------ Class ------------------------------------------------------
+
+ ///
+ /// Ctor
+ ///
+ /// physical slot for this meter
+ ///
+ /// - Initial
+ ///
+ public EolStateMachine(Int32 slot) : base(slot)
+ {
+ }
+
+ #endregion --------------------------------------- Class ------------------------------------------------------
+ #region ------------------------------------------ Events -----------------------------------------------------
+ //
+ #endregion --------------------------------------- Events -----------------------------------------------------
+ #region ------------------------------------------ State Machine ----------------------------------------------
+ ///
+ ///
+ /// State machine of FinalProcessController which serves as preparation for SHIPPING named EOL (End-Of-Line).
+ ///
+ ///
+ /// - Initial
+ ///
+ public override void IndividualStateMachine(IProductionProcess process)
+ {
+ switch (_stateMachineState)
+ {
+ case ProcessState.GetProgrammingParameters:
+ // Precondition: - The connection process has to be completed as a readout of some register
+ // values from the Cordonel are needed to check the update capability:
+ // - Wait on completed connection process before starting this process.
+ // AVOID to change the process state on completion as parallel process is active!
+ StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion,
+ waitForSingleProcess: _processStateDef?.GetProcessOfState(ProcessState.ConnectCordonel));
+ // Do not wait on completion as new parallel process can be started by manually state change.
+ _stateMachineState = ProcessState.CheckProductionState;
+ break;
+
+ case ProcessState.CheckProductionState:
+ // Precondition: - The connection process has to be completed as a readout of some register
+ // values from the Cordonel are needed to check the update capability:
+ // - Wait on completed connection process before starting this process.
+ // AVOID to change the process state on completion as parallel process is active!
+ StartProcess(process, BaseProductionProcess.DoNotChangeStateAfterCompletion,
+ waitForSingleProcess: _processStateDef?.GetProcessOfState(ProcessState.ConnectCordonel));
+ // Do not wait on completion as new parallel process can be started by manually state change.
+ _stateMachineState = ProcessState.ProcessPasswordFile;
+ break;
+
+ case ProcessState.ProcessPasswordFile:
+ // Precondition: - The connection process has to be completed as a password change in the DB
+ // will take place: Skeleton to Password Level 8. Not waiting for completion may cause side
+ // effects on login. Wait for all processes to complete.
+ // Leave state switch to automatic to avoid side effects on incomplete updated DB for next
+ // steps.
+ StartProcess(process, ProcessState.ExecFinalParametrization, waitForAllProcesses: true);
+ break;
+
+ case ProcessState.ExecFinalParametrization:
+ // This writes all setups to the device, it has to be executed exclusively with automatic
+ StartProcess(process, ProcessState.ExecStoreConfiguration);
+ break;
+
+ case ProcessState.ExecStoreConfiguration:
+ // Precondition: - The final parametrization has to be finished as this shall be stored
+ // to non-volatile memory and checked if remaining valid after the reboot.
+ // Store configuration has to be executed exclusively with automatic
+ StartProcess(process, ProcessState.RebootCordonel);
+ break;
+
+ case ProcessState.RebootCordonel:
+ // Precondition: - The store configuration has to be executed to safe all settings
+ // to non-volatile memory and checked if remaining valid after the reboot.
+ // Reboot has to be executed exclusively with automatic
+ StartProcess(process, ProcessState.CheckFinalParametrization);
+ break;
+
+ case ProcessState.CheckFinalParametrization:
+ // Precondition: - The reboot process including the store all configurations has to be
+ // completed.
+ // Check final configuration has to be executed exclusively with automatic
+ StartProcess(process, ProcessState.CheckRadio);
+ break;
+
+ case ProcessState.CheckRadio:
+ // Precondition: - The final parametrization, reboot process including the store all
+ // configurations and the check of all setups survived the reboot have to be completed.
+ // Radio signal level check, skipped on NA region or if skipping is required by special
+ // approval
+ StartProcess(process, ProcessState.CheckOrderNumber);
+ break;
+
+ case ProcessState.CheckAttachments:
+ // Precondition: - All checks have to be executed with positive result
+ StartProcess(process, ProcessState.ExecVisualInspection);
+ break;
+
+ case ProcessState.ExecVisualInspection:
+ // Precondition: - All checks have to be executed with positive result
+ StartProcess(process, ProcessState.PrepareShippingMode);
+ break;
+
+ case ProcessState.PrepareShippingMode:
+ // Precondition: - All checks have to be executed with positive result
+ StartProcess(process, ProcessState.ReadyForShipping);
+ break;
+
+ case ProcessState.ReadyForShipping:
+ _stateMachineState = ProcessState.Idle;
+ break;
+
+ default:
+ _stateMachineState = ProcessState.Idle;
+ break;
+ }
+ }
+
+ #endregion --------------------------------------- State Machine ----------------------------------------------
+ #region ------------------------------------------ Tools ------------------------------------------------------
+ //
+ #endregion --------------------------------------- Tools ------------------------------------------------------
+ }
+}
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs
index 2a322f9a..aa67ea14 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs
@@ -7,7 +7,7 @@ using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Logic.SoftwareAccessHelper;
-using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses;
+using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/CheckOrderNumber.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckOrderNumber.cs
similarity index 99%
rename from Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/CheckOrderNumber.cs
rename to Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckOrderNumber.cs
index 6eb900f3..3b4a7056 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/CheckOrderNumber.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckOrderNumber.cs
@@ -4,7 +4,7 @@ using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
using Xylem.Common.Production.ProductionUiCordonel.UserControls;
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses
{
public class CheckOrderNumber : BaseProductionProcess
{
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/CheckSerialNumber.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckSerialNumber.cs
similarity index 99%
rename from Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/CheckSerialNumber.cs
rename to Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckSerialNumber.cs
index 586e1f5b..ba488770 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/CheckSerialNumber.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckSerialNumber.cs
@@ -4,7 +4,7 @@ using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
using Xylem.Common.Production.ProductionUiCordonel.UserControls;
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses
{
public class CheckSerialNumber : BaseProductionProcess
{
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/ConnectCordonel.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/ConnectCordonel.cs
similarity index 98%
rename from Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/ConnectCordonel.cs
rename to Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/ConnectCordonel.cs
index a0fac18a..da46434a 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/ConnectCordonel.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/ConnectCordonel.cs
@@ -3,7 +3,7 @@ using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses
{
public class ConnectCordonel : BaseProductionProcess
{
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/DetectCordonel.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/DetectCordonel.cs
similarity index 98%
rename from Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/DetectCordonel.cs
rename to Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/DetectCordonel.cs
index fef61032..0c2d9993 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/DetectCordonel.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/DetectCordonel.cs
@@ -3,7 +3,7 @@ using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses
{
///
/// Production process detects the serial number of the Cordonel.
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/ErrorHandler.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/ErrorHandler.cs
similarity index 99%
rename from Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/ErrorHandler.cs
rename to Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/ErrorHandler.cs
index e333b9bd..78f5a3eb 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/ErrorHandler.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/ErrorHandler.cs
@@ -5,7 +5,7 @@ using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
using Xylem.Common.Production.ProductionUiCordonel.UserControls;
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses
{
public class ErrorHandler : BaseProductionProcess
{
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/GetSerialNumberAndRadioAddress.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/GetSerialNumberAndRadioAddress.cs
similarity index 99%
rename from Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/GetSerialNumberAndRadioAddress.cs
rename to Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/GetSerialNumberAndRadioAddress.cs
index 562d993e..a912e5a7 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/CommonProcesses/GetSerialNumberAndRadioAddress.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/GetSerialNumberAndRadioAddress.cs
@@ -8,7 +8,7 @@ using Xylem.Common.Logic.SoftwareAccessHelper;
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
using Xylem.Common.Production.ProductionUiCordonel.Properties;
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses
{
///
/// Request the serial number and radio address from DB.
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/IProcessController.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/IProcessController.cs
index 26615686..5a88c1ae 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/IProcessController.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/IProcessController.cs
@@ -1,58 +1,12 @@
-namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
+using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
+namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
{
public interface IProcessController
{
///
- /// State machine of ProcessController which serves as template for all production processes.
- ///
- ///
- /// INSTRUCTION FOR NORMAL USAGE:
- /// -----------------------------
- /// Call the SetupProcess() with the
- /// - new process automatically collected from with new
- /// _actualProcessState as input,
- /// - successExitState set to the next required state after successfully execution.
- /// That's it! The normal state change has always only one production process active and waits for completion
- /// before changing to a new state and therefore a new production process.
- ///
- /// If a special state is needed on errorExitState or breakExitState these can be assigned. Otherwise, the
- /// errorExitState is linked to the error state, the breakExitState to the stop state.
- ///
- ///
- /// INSTRUCTION FOR NON-BLOCKING MULTIPLE PROCESSES SIMULTANEOUSLY ACTIVITIES:
- /// --------------------------------------------------------------------------
- /// Sometimes production processes may be able to be executed simultaneously as they are independent of each
- /// other. One example is a database access for data collection from different tables.
- ///
- /// Call the SetupProcess with the
- /// - new process automatically collected from with new
- /// _actualProcessState as input,
- /// - successExitState being set to (null).
- /// This will lock the sate change after completion as multiple processes may be active and a state change after
- /// completion may cause unpredictable operation, the state is already where it should be (manually changed),
- /// - change the state after the SetupProcess() call manually.
- ///
- /// This is needed for non-blocking immediately new state change (not waiting for the successful execution of
- /// the actual new assigned process):
- /// E.g. all DB accesses need a certain time to get data, kicking off (fire and forget) the process without
- /// waiting for the result, the exitSuccessState has to be set to null to avoid a state change on successfully
- /// execution of the process. Instead, change the state here to go ahead with the next state. This forces a wait
- /// on the state who needs the data from the "fire and forget" states, SEE next instruction how to proceed!
- ///
- ///
- /// INSTRUCTION TO DELAY THE START OF A PROCESS:
- /// --------------------------------------------
- /// Each new process execution can be delayed as it may need the result of another process which is active.
- ///
- /// Wait for a single process to complete:
- /// - set the "waitForSingleProcess" to the process to wait for.
- /// Wait for all preceding processes to complete:
- /// - set the "waitForAllProcesses" to true.
- ///
+ /// Individual states to fill the state machine.
+ /// ATTENTION: All states have to be part of the
///
- ///
- /// - Initial
- ///
- void StateMachine();
+ void IndividualStateMachine(IProductionProcess process);
}
}
diff --git a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj
index 767a4554..945346a8 100644
--- a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj
+++ b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj
@@ -289,10 +289,10 @@
-
+
-
-
+
+
@@ -300,7 +300,7 @@
-
+
@@ -319,15 +319,15 @@
MultiModeChild.xaml
-
-
+
+
-
+