ProductionUiCordonel: - re-organized to support multiple production processes part 2
This commit is contained in:
@@ -21,6 +21,7 @@ using Xylem.Common.CommonCore.Consts;
|
||||
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EventArgs;
|
||||
using Xylem.Common.Utils.Logging;
|
||||
using Xylem.Common.Utils.UserAccessCtrl;
|
||||
@@ -53,7 +54,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel
|
||||
// maximum processing steps for calculation of progress bar
|
||||
private Int32 _maxOverallProcessSteps;
|
||||
private Int32 _maxSingleProcessSteps;
|
||||
private FinalProcessController _processCtrl;
|
||||
private BaseProcessController _processCtrl;
|
||||
private DateTimeOffset _startTime;
|
||||
private DispatcherTimer _timer;
|
||||
private String _lastLoggingTextToAvoidRepetition;
|
||||
@@ -177,7 +178,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel
|
||||
|
||||
try
|
||||
{
|
||||
_processCtrl = new FinalProcessController(Slot);
|
||||
_processCtrl = new EolProcessController(Slot);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ using Xylem.Common.CommonCore.Consts;
|
||||
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EventArgs;
|
||||
using Xylem.Common.Utils.Logging;
|
||||
using Xylem.Common.Utils.UserAccessCtrl;
|
||||
@@ -53,7 +54,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel
|
||||
// maximum processing steps for calculation of progress bar
|
||||
private Int32 _maxOverallProcessSteps;
|
||||
private Int32 _maxSingleProcessSteps;
|
||||
private FinalProcessController _processCtrl;
|
||||
private BaseProcessController _processCtrl;
|
||||
private DateTimeOffset _startTime;
|
||||
private DispatcherTimer _timer;
|
||||
private String _lastLoggingTextToAvoidRepetition;
|
||||
@@ -177,7 +178,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel
|
||||
|
||||
try
|
||||
{
|
||||
_processCtrl = new FinalProcessController(Slot);
|
||||
_processCtrl = new EolProcessController(Slot);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
+56
-300
@@ -8,27 +8,20 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd;
|
||||
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus;
|
||||
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EventArgs;
|
||||
using Timer = System.Threading.Timer;
|
||||
|
||||
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// Implementation for all methods needed to drive the state machine of the process controller
|
||||
/// </summary>
|
||||
public sealed class FinalProcessController
|
||||
public abstract class BaseProcessController : IProcessController
|
||||
{
|
||||
#region ------------------------------------------ Variables --------------------------------------------------
|
||||
// actual genesis meter
|
||||
private IGenesisMeter _genesisMeter;
|
||||
protected IGenesisMeter _genesisMeter;
|
||||
// Cordonel requirements for production
|
||||
private CordonelRequirements _cordonelRequirements;
|
||||
// EOL progress states for production
|
||||
@@ -38,19 +31,20 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
// batch just used for setup, as only one meter will be assigned
|
||||
private MeterBatch _meterBatch;
|
||||
// state of the state machine
|
||||
private ProcessState _stateMachineState;
|
||||
protected ProcessState _stateMachineState;
|
||||
// locker to avoid repeated state execution
|
||||
private ProcessState _lockedProcessState;
|
||||
protected ProcessState _lockedProcessState;
|
||||
// sender of state change event to evaluate in e.g. error process
|
||||
private IProductionProcess _stateChangeRequestProcess;
|
||||
protected IProductionProcess _stateChangeRequestProcess;
|
||||
// List of production processes
|
||||
public List<IProductionProcess> Processes
|
||||
{
|
||||
get; private set;
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
// Container for production process states
|
||||
private ProcessStateDef _processStateDef;
|
||||
protected EolProcessStates _processStateDef;
|
||||
|
||||
// Container for production status information, a list is used to keep the content over all classes of production
|
||||
// processes as a reference seems not to return their value (always reset to the initial value)
|
||||
@@ -69,24 +63,36 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
// reminder for slot
|
||||
private readonly Int32 _slot;
|
||||
|
||||
// processing retries
|
||||
private const Int32 MaxProcessRetries = 2;
|
||||
//private static Int32 _processRetryCtr;
|
||||
|
||||
//event for process list change or state of single process step change
|
||||
/// <summary>
|
||||
/// Change the overview table of the GUI to the state of the individual process
|
||||
/// </summary>
|
||||
public event EventHandler<SingleProcessStateArgs> OnSingleProcessStateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The overall process chain changed needed to signal to the GUI
|
||||
/// - Can be forced by the state machine to invoke,
|
||||
/// - Will be used via the OverallProcessStateChanged_Handler by the individual processes to return the next
|
||||
/// required sate after break, error or completion to change the state of the state machine.
|
||||
/// </summary>
|
||||
public event EventHandler<ProcessStateArgs> OnOverallProcessStateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Request for logging to GUI output and log-file
|
||||
/// </summary>
|
||||
public event EventHandler<ProcessLogArgs> OnProcessLogRequest;
|
||||
// progress bar and screen info of ongoing processes
|
||||
|
||||
/// <summary>
|
||||
/// Keep the progress bars of the GUI up to date
|
||||
/// </summary>
|
||||
public event EventHandler<ProcessProgressArgs> OnProcessProgressChanged;
|
||||
|
||||
// cancellation token
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private CancellationToken _cancellationToken;
|
||||
protected CancellationTokenSource _cancellationTokenSource;
|
||||
protected CancellationToken _cancellationToken;
|
||||
|
||||
// cyclic timer for state machine call
|
||||
private Timer _processCtrlTimer;
|
||||
private const Int32 ProcessTimerCycleMs = 250;
|
||||
protected const Int32 ProcessTimerCycleMs = 250;
|
||||
|
||||
// defines for state machine
|
||||
/// <summary>
|
||||
@@ -111,7 +117,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// - Always RegisterWatchService on,
|
||||
/// - Always MinMaxCHeck on.
|
||||
/// </remarks>
|
||||
public FinalProcessController(Int32 slot)
|
||||
protected BaseProcessController(Int32 slot)
|
||||
{
|
||||
_processCtrlTimer = new Timer(TmrProcessCtrlCycle_Elapsed, null, ProcessTimerCycleMs, ProcessTimerCycleMs);
|
||||
_slot = slot;
|
||||
@@ -248,6 +254,20 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
OnProcessLogRequest?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper to fire this event from a derived class
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <remarks date="2025-Apr-14" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
protected void OverallProcessStateChanged(Object sender, ProcessStateArgs e)
|
||||
{
|
||||
// signal state change to logger
|
||||
OnOverallProcessStateChanged?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler to set a new state for the state machine regarding the entire final-process
|
||||
/// </summary>
|
||||
@@ -282,272 +302,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
|
||||
#endregion --------------------------------------- Events -----------------------------------------------------
|
||||
#region ------------------------------------------ State Machine ----------------------------------------------
|
||||
/// <summary>
|
||||
/// 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 <see cref="ProcessStateDef.GetProcessOfState"/> 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 <see cref="ProcessStateDef.GetProcessOfState"/> with new
|
||||
/// _actualProcessState as input,
|
||||
/// - successExitState being set to <see cref="BaseProductionProcess.DoNotChangeStateAfterCompletion"/> (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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks date="2023-Jan-17" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
private 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
|
||||
OnOverallProcessStateChanged?.Invoke(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
|
||||
public abstract void StateMachine();
|
||||
|
||||
#endregion --------------------------------------- State Machine ----------------------------------------------
|
||||
#region ------------------------------------------ Tools ------------------------------------------------------
|
||||
@@ -588,7 +344,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2024-Jul-15" author="Thomas Wiedebusch">
|
||||
/// - Handle genesis meter is null as new meter.
|
||||
/// </remarks>
|
||||
private Boolean CheckForNewMeter()
|
||||
protected Boolean CheckForNewMeter()
|
||||
{
|
||||
if (_genesisMeter == null ||
|
||||
(!string.IsNullOrEmpty(_lastPcbId) &&
|
||||
@@ -626,7 +382,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2024-Oct-21" author="Thomas Wiedebusch">
|
||||
/// - Leave skipped processes as is.
|
||||
/// </remarks>
|
||||
private ProcessState RepeatFailedTests()
|
||||
protected ProcessState RepeatFailedTests()
|
||||
{
|
||||
var state = ProcessState.Idle;
|
||||
|
||||
@@ -668,7 +424,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2025-Jan-28" author="Thomas Wiedebusch">
|
||||
/// - Kick off exec parametrization if check after reboot failed.
|
||||
/// </remarks>
|
||||
private void ProcessErrorHandler(IProductionProcess process)
|
||||
protected void ProcessErrorHandler(IProductionProcess process)
|
||||
{
|
||||
if (process == null)
|
||||
return;
|
||||
@@ -693,7 +449,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <summary>
|
||||
/// Calculate the maximum of all processes expected to execute and signal to GUI.
|
||||
/// </summary>
|
||||
private void CalcAndPushMaxOverAllProcessSteps()
|
||||
protected void CalcAndPushMaxOverAllProcessSteps()
|
||||
{
|
||||
if (_processStateDef == null)
|
||||
return;
|
||||
@@ -707,7 +463,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <summary>
|
||||
/// Calculate all processes which are completed or skipped and signal to GUI.
|
||||
/// </summary>
|
||||
private void CalcAndPushOverAllProgress()
|
||||
protected void CalcAndPushOverAllProgress()
|
||||
{
|
||||
if (Processes == null)
|
||||
return;
|
||||
@@ -736,7 +492,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
if (Processes == null)
|
||||
Processes = new List<IProductionProcess>();
|
||||
if (_processStateDef == null)
|
||||
_processStateDef = new ProcessStateDef();
|
||||
_processStateDef = new EolProcessStates();
|
||||
|
||||
// get all processes relevant for EOL from table which has to be sorted
|
||||
var processes = _processStateDef.GetAllEolRelevantProcesses();
|
||||
@@ -791,7 +547,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2024-Sep-01" author="Thomas Wiedebusch">
|
||||
/// - Changed setup process to start process being able to create a process list in advance.
|
||||
/// </remarks>
|
||||
private void StartProcess(IProductionProcess process, ProcessState? successExitState,
|
||||
protected void StartProcess(IProductionProcess process, ProcessState? successExitState,
|
||||
ProcessState errorExitState = ProcessState.Error, ProcessState breakExitState = ProcessState.Stop,
|
||||
IProductionProcess waitForSingleProcess = DoNotWaitForSingleProcessCompletion,
|
||||
Boolean waitForAllProcesses = false, Boolean startAlways = false)
|
||||
@@ -956,7 +712,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2025-Apr-07" author="Thomas Wiedebusch">
|
||||
/// - Cancellation token source.
|
||||
/// </remarks>
|
||||
private void KillProcesses()
|
||||
protected void KillProcesses()
|
||||
{
|
||||
_cancellationTokenSource?.Cancel();
|
||||
Thread.Sleep(1000);
|
||||
@@ -978,7 +734,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2023-Jun-21" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
private void AbortProcesses()
|
||||
protected void AbortProcesses()
|
||||
{
|
||||
if (Processes == null || Processes.Count == 0)
|
||||
return;
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using Xylem.Common.CommonCore.Consts;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.Properties;
|
||||
|
||||
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses
|
||||
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
|
||||
{
|
||||
public class ConnectCordonel : BaseProductionProcess
|
||||
{
|
||||
+1
-1
@@ -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.EolProcesses
|
||||
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses
|
||||
{
|
||||
/// <summary>
|
||||
/// Request the serial number and radio address from DB.
|
||||
+1
@@ -15,6 +15,7 @@ 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.Properties;
|
||||
|
||||
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public sealed class EolProcessController : BaseProcessController, IProcessController
|
||||
{
|
||||
#region ------------------------------------------ Variables --------------------------------------------------
|
||||
//
|
||||
#endregion --------------------------------------- Variables --------------------------------------------------
|
||||
#region ------------------------------------------ Class ------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Ctor
|
||||
/// </summary>
|
||||
/// <param name="slot">physical slot for this meter</param>
|
||||
/// <remarks date="2025-Apr-14" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
public EolProcessController(Int32 slot) : base(slot)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion --------------------------------------- Class ------------------------------------------------------
|
||||
#region ------------------------------------------ Events -----------------------------------------------------
|
||||
//
|
||||
#endregion --------------------------------------- Events -----------------------------------------------------
|
||||
#region ------------------------------------------ State Machine ----------------------------------------------
|
||||
/// <summary>
|
||||
/// 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 <see cref="EolProcessStates.GetProcessOfState"/> 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 <see cref="EolProcessStates.GetProcessOfState"/> with new
|
||||
/// _actualProcessState as input,
|
||||
/// - successExitState being set to <see cref="BaseProductionProcess.DoNotChangeStateAfterCompletion"/> (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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks date="2023-Jan-17" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
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 ------------------------------------------------------
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -2,11 +2,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.CommonProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.Properties;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses;
|
||||
using Xylem.Common.Production.ProductionUiCordonel.Properties;
|
||||
|
||||
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses
|
||||
{
|
||||
/// <summary>
|
||||
/// Concatenation for all production process states:
|
||||
@@ -17,7 +16,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2023-Feb-14" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
public class ProcessStateDef
|
||||
public class EolProcessStates
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of state information
|
||||
@@ -31,7 +30,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// - Sort the active steps from first til last step as this is the order as those will be sorted in the
|
||||
/// process list UI.
|
||||
/// </summary>
|
||||
public ProcessStateDef()
|
||||
public EolProcessStates()
|
||||
{
|
||||
_stateContainer = new List<ProcessStateStruct>
|
||||
{
|
||||
+1
-1
@@ -66,7 +66,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
|
||||
/// <remarks date="2023-Jul-11" author="Thomas Wiedebusch">
|
||||
/// - Speed up to quick return if passwords are already set.
|
||||
///
|
||||
/// ATTENTION: This requires to remove those on new PcbId <see cref="FinalProcessController"/>
|
||||
/// ATTENTION: This requires to remove those on new PcbId <see cref="BaseProcessController"/>
|
||||
/// for CheckMeterChange!
|
||||
///
|
||||
/// </remarks>
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
|
||||
/// <remarks date="2023-Jul-11" author="Thomas Wiedebusch">
|
||||
/// - Speed up to quick return if programming parameters are already set.
|
||||
///
|
||||
/// ATTENTION: This requires to remove those on new PcbId <see cref="FinalProcessController"/>
|
||||
/// ATTENTION: This requires to remove those on new PcbId <see cref="BaseProcessController"/>
|
||||
/// for CheckMeterChange!
|
||||
/// </remarks>
|
||||
/// <remarks date="2023-Jul-19" author="Thomas Wiedebusch">
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
{
|
||||
public interface IProcessController
|
||||
{
|
||||
/// <summary>
|
||||
/// 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 <see cref="ProcessStates.GetProcessOfState"/> 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 <see cref="ProcessStates.GetProcessOfState"/> with new
|
||||
/// _actualProcessState as input,
|
||||
/// - successExitState being set to <see cref="BaseProductionProcess.DoNotChangeStateAfterCompletion"/> (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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks date="2023-Jan-17" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
void StateMachine();
|
||||
}
|
||||
}
|
||||
@@ -291,7 +291,7 @@
|
||||
<Compile Include="ProductionProcesses\EolProcesses\VisualInspection.cs" />
|
||||
<Compile Include="ProductionProcesses\CommonProcesses\ErrorHandler.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\ExecStoreConfiguration.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\GetSerialNumberAndRadioAddress.cs" />
|
||||
<Compile Include="ProductionProcesses\CommonProcesses\GetSerialNumberAndRadioAddress.cs" />
|
||||
<Compile Include="ProductionProcesses\CommonProcesses\DetectCordonel.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\ExecRebootCordonel.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\PrepareShipping.cs" />
|
||||
@@ -299,7 +299,9 @@
|
||||
<Compile Include="ProductionProcesses\Enum\ImgState.cs" />
|
||||
<Compile Include="ProductionProcesses\Enum\ProcessState.cs" />
|
||||
<Compile Include="ProductionProcesses\EventArgs\SingleProcessStateArgs.cs" />
|
||||
<Compile Include="ProductionProcesses\ProcessStateDef.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\EolProcessStates.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\EolProcessController.cs" />
|
||||
<Compile Include="ProductionProcesses\IProcessController.cs" />
|
||||
<Compile Include="ProductionProcesses\ProcessStateStruct.cs" />
|
||||
<Compile Include="Data\PickingResultData.cs" />
|
||||
<Compile Include="Data\PressureResultDataNotifyable.cs" />
|
||||
@@ -325,12 +327,12 @@
|
||||
<Compile Include="ProductionProcesses\EolProcesses\GetFinalParametrization.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\ExecFinalParametrization.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\CheckRadio.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\ConnectCordonel.cs" />
|
||||
<Compile Include="ProductionProcesses\CommonProcesses\ConnectCordonel.cs" />
|
||||
<Compile Include="ProductionProcesses\EolProcesses\ExecPasswordFile.cs" />
|
||||
<Compile Include="ProductionProcesses\BaseProductionProcess.cs" />
|
||||
<Compile Include="ProductionProcesses\Enum\SingleProcessState.cs" />
|
||||
<Compile Include="ProductionProcesses\IProductionProcess.cs" />
|
||||
<Compile Include="ProductionProcesses\FinalProcessController.cs" />
|
||||
<Compile Include="ProductionProcesses\BaseProcessController.cs" />
|
||||
<Compile Include="ProductionProcesses\EventArgs\ProcessStateArgs.cs" />
|
||||
<Compile Include="ProductionProcesses\EventArgs\ProcessLogArgs.cs" />
|
||||
<Compile Include="ProductionProcesses\EventArgs\ProcessProgressArgs.cs" />
|
||||
|
||||
Reference in New Issue
Block a user