diff --git a/Common/Common.sln.DotSettings b/Common/Common.sln.DotSettings
index 25cd6bf6..bf277268 100644
--- a/Common/Common.sln.DotSettings
+++ b/Common/Common.sln.DotSettings
@@ -52,6 +52,7 @@
True
True
True
+ True
True
True
True
@@ -62,6 +63,7 @@
True
True
True
+ True
True
True
True
diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs
index 6f40126d..f7137e89 100644
--- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs
+++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs
@@ -184,11 +184,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
private Int32 _actualRegisterCtr;
- ///
- /// Stop register access
- ///
- public Boolean StopRegisterAccess;
-
///
/// Genesis meter object
///
@@ -575,6 +570,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
List recoveryRegistersDb, out String errorMsg)
{
errorMsg = "";
+ if (string.IsNullOrEmpty(pcbId))
+ return StatusReturn.Failed;
try
{
var url = $"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetProgrammingParameters?PcbID={pcbId}";
@@ -622,14 +619,18 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// list of registers to update from database without special sequence
///
+ ///
/// true if setup succeeded
///
/// - Initial.
///
- public StatusReturn EolProgrammingRegisters(List recoveryRegistersDb)
+ ///
+ /// - CancellationToken.
+ ///
+ public StatusReturn EolProgrammingRegisters(List recoveryRegistersDb, CancellationToken cancellationToken)
{
// mark EOL as true to force accu reset
- return WriteRegisters(recoveryRegistersDb, true);
+ return WriteRegisters(recoveryRegistersDb, cancellationToken, true);
}
///
@@ -670,6 +671,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// list of registers to update from database without special sequence
///
+ ///
/// EOL (end of line) programming with accu reset
/// true if restoring succeeded
///
@@ -724,7 +726,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// - Exported write routines to .
///
- public StatusReturn WriteRegisters(List recoveryRegistersDb, Boolean eolProgramming = false)
+ ///
+ /// - CancellationToken.
+ ///
+ public StatusReturn WriteRegisters(List recoveryRegistersDb, CancellationToken cancellationToken,
+ Boolean eolProgramming = false)
{
if (_currentGenesis == null ||
string.IsNullOrEmpty(_currentGenesis.PcbId) ||
@@ -742,7 +748,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
RecoveryRegisters = recoveryRegistersDb;
}
- StopRegisterAccess = false;
_actualRegisterCtr = 0;
// Build string list for debug
@@ -789,7 +794,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(Resources.StrRegisterRecoveryPreparation,
actualProcessMessage: Resources.StrRegisterRecoveryPreparation));
- if (StatusReturn.Failed == WriteRegisterParameterSet(_prepareProgramming, recRegistersCount, meterRegisters))
+ if (StatusReturn.Failed == WriteRegisterParameterSet(_prepareProgramming, recRegistersCount, meterRegisters,
+ cancellationToken))
{
// the logout will force the radio app to activate the settings
_currentGenesis?.Logout();
@@ -800,7 +806,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(Resources.StrRegisterRecoveryExec,
actualProcessMessage: Resources.StrRegisterRecoveryExec));
- if (StatusReturn.Failed == WriteRegisterParameterSet(recoveryRegistersDb, recRegistersCount, meterRegisters))
+ if (StatusReturn.Failed == WriteRegisterParameterSet(recoveryRegistersDb, recRegistersCount, meterRegisters,
+ cancellationToken))
{
// the logout will force the radio app to activate the settings
_currentGenesis?.Logout();
@@ -811,7 +818,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(Resources.StrRegisterRecoveryFinalization,
actualProcessMessage: Resources.StrRegisterRecoveryFinalization));
- if (StatusReturn.Failed == WriteRegisterParameterSet(finalizeProgrammingAll, recRegistersCount, meterRegisters))
+ if (StatusReturn.Failed == WriteRegisterParameterSet(finalizeProgrammingAll, recRegistersCount, meterRegisters,
+ cancellationToken))
{
// the logout will force the radio app to activate the settings
_currentGenesis?.Logout();
@@ -837,12 +845,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
///
///
+ ///
///
///
/// - Initial imported from .
///
+ ///
+ /// - CancellationToken.
+ ///
private StatusReturn WriteRegisterParameterSet(List recoveryRegistersDb, Int32 recRegistersCount,
- MeterRegisters meterRegisters)
+ MeterRegisters meterRegisters, CancellationToken cancellationToken)
{
foreach (var recReg in recoveryRegistersDb)
{
@@ -915,7 +927,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
overallProcessCtrPercent, actualProcessMsg));
}
- if (StopRegisterAccess)
+ if (cancellationToken.IsCancellationRequested)
break;
}
@@ -928,6 +940,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// - The _restoreRegisters has to be filled with all registers being able to restore (RW),
/// - The _finalReadRegisters has to be filled.
///
+ ///
/// true if equal
///
/// - Initial.
@@ -965,13 +978,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// - Hash password and encryption key with SHA256.
///
- public Boolean CompareRegisters()
+ ///
+ /// - CancellationToken.
+ ///
+ public Boolean CompareRegisters(CancellationToken cancellationToken)
{
if (_pcbIdFinalRegisterRead != _pcbIdWriteRegisters ||
RecoveryRegisters == null)
return false;
- StopRegisterAccess = false;
_actualRegisterCtr = 0;
var retVal = true;
@@ -1132,7 +1147,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
}
}
- if (StopRegisterAccess)
+ if (cancellationToken.IsCancellationRequested)
break;
}
catch (Exception ex)
@@ -1147,6 +1162,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// Read the registers after the update for comparision. Build the post update registers here,
/// because an update may have changed the registers (new or removed registers).
///
+ ///
/// true if registers could be read
///
/// - Initial.
@@ -1176,7 +1192,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// - Check readBack value for null.
///
- public Boolean FinalReadRegisters()
+ ///
+ /// - CancellationToken.
+ ///
+ public Boolean FinalReadRegisters(CancellationToken cancellationToken)
{
if (_currentGenesis == null)
return false;
@@ -1199,7 +1218,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
_finalRegisterList.Sort();
// executes login read logout
- retVal = ReadRegistersSet(ref _finalRegisters);
+ retVal = ReadRegistersSet(ref _finalRegisters, cancellationToken);
// backup read data to RecoveryRegisters
if (RecoveryRegisters != null && _finalRegisters != null)
@@ -1241,6 +1260,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// The defined registers are based on the "configuration.json" and the installed application with
/// a specific version.
///
+ ///
/// true if registers could be read
///
/// - Initial.
@@ -1265,7 +1285,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// - Register list changed from RegisterDefinition to RecoveryRegisterItem list.
///
- public Boolean InitialReadRegisters()
+ ///
+ /// - CancellationToken.
+ ///
+ public Boolean InitialReadRegisters(CancellationToken cancellationToken)
{
if (_currentGenesis == null)
return false;
@@ -1291,7 +1314,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
_initialRegisterList = _initialRegisters.Select(register => register.RegisterIdent).ToList();
_initialRegisterList.Sort();
- return ReadRegistersSet(ref _initialRegisters);
+ return ReadRegistersSet(ref _initialRegisters, cancellationToken);
}
///
@@ -1346,6 +1369,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// The defined registers are based on the "configuration.json" and the installed application with a specific
/// version.
///
+ ///
/// true if registers could be read
///
/// - Initial.
@@ -1353,7 +1377,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// - Register list changed from RegisterDefinition to RecoveryRegisterItem list.
///
- public Boolean ReadRegisters()
+ ///
+ /// - CancellationToken.
+ ///
+ public Boolean ReadRegisters(CancellationToken cancellationToken)
{
if (_currentGenesis == null)
return false;
@@ -1368,17 +1395,21 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($@"{Resources.StrReadRegister}", 0,
Resources.StrReadRegistersBeforeUpdate));
- return ReadRegistersSet(ref registers);
+ return ReadRegistersSet(ref registers, cancellationToken);
}
///
/// Read predefined registers from RecoveryRegisters.
///
+ ///
/// true if registers could be read
///
/// - Initial.
///
- public Boolean ReadPresetRegisters()
+ ///
+ /// - CancellationToken.
+ ///
+ public Boolean ReadPresetRegisters(CancellationToken cancellationToken)
{
if (_currentGenesis == null || RecoveryRegisters == null || RecoveryRegisters.Count == 0)
return false;
@@ -1389,7 +1420,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
_pcbIdWriteRegisters = _currentGenesis.PcbId;
_pcbIdFinalRegisterRead = _currentGenesis.PcbId;
- return ReadRegistersSet(ref RecoveryRegisters);
+ return ReadRegistersSet(ref RecoveryRegisters, cancellationToken);
}
///
@@ -1401,6 +1432,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// Executes login, read cycle and logout.
///
/// registers to read
+ ///
/// true if registers could be read
///
/// - Initial.
@@ -1430,11 +1462,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
///
/// - Register list changed from RegisterDefinition to RecoveryRegisterItem list.
///
- private Boolean ReadRegistersSet(ref List registers)
+ ///
+ /// - CancellationToken.
+ ///
+ private Boolean ReadRegistersSet(ref List registers, CancellationToken cancellationToken)
{
if (_currentGenesis == null)
return false;
- StopRegisterAccess = false;
_actualRegisterCtr = 0;
// read values from Genesis
@@ -1503,7 +1537,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
overallProcessCtrPercent, actualProcessMsg));
}
- if (StopRegisterAccess)
+ if (cancellationToken.IsCancellationRequested)
break;
}
catch (Exception ex)
diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj b/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj
index aefdb732..4502e737 100644
--- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj
+++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj
@@ -211,6 +211,7 @@
PublicResXFileCodeGenerator
Resources.de.Designer.cs
+ Designer
PublicResXFileCodeGenerator
diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs
index 3597e876..2a29ebca 100644
--- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs
+++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs
@@ -259,6 +259,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
///
/// Update meter lookup table
///
+ ///
///
///
/// - Initial
@@ -269,7 +270,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
///
/// - Check reboot counter to verify reboot being done.
///
- public Boolean MeterResetPsuExecute()
+ ///
+ /// - CancellationToken.
+ ///
+ public Boolean MeterResetPsuExecute(CancellationToken cancellationToken = default(CancellationToken))
{
var statusReturn = _genesisMeter.RebootGenesis();
// Status return "Unknown" is from the real Genesis
@@ -291,6 +295,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
_genesisMeter.ReadRegister(registerName));
while (_meterResetPsuState != MeterResetPsuState.Idle && !StopUpdateProcess)
{
+ if (cancellationToken.IsCancellationRequested)
+ StopUpdateProcess = true;
MeterResetPsuStateMachine();
}
var rebootCountAfterReboot = RegisterConverter.ByteArrayToValue(
diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/Properties/Resources.de.resx b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Properties/Resources.de.resx
index bea1a4f8..fbdf1424 100644
--- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/Properties/Resources.de.resx
+++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Properties/Resources.de.resx
@@ -130,7 +130,7 @@
Sende Aktualisierungsdateien
- Sende Initialisierungsdatei für Aktualisierung
+ Sende Neustartkonfigurationsdatei
Lösche Aktualisierungsdatei
diff --git a/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs b/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs
index d896dffe..6edb24f2 100644
--- a/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs
+++ b/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Threading;
using FluentAssertions;
using LaaPackages.Features.Cordonel.Models;
using Logic.ProductionToProductMapper.Files.Fw;
@@ -524,7 +525,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
var meterSizeForParams = "?";
var unmodifiedParamsUsableAsReferenceForNextTest = false;
var intermediateRecoveryRegisters = new List();
-
+
foreach (var testCase in _testCases)
{
// Prepare one test result for an entire sequence to test
@@ -622,8 +623,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
testPp = new ExecFinalParametrization("UnitTestExecFinalParametrization");
testPp.RegisterRestorer = testCase.RegisterRestorer;
- CommonCallClassCheck(testPp, testCase,
- ref testResult);
+ CommonCallClassCheck(testPp, testCase, ref testResult);
break;
case "ExecStoreConfiguration":
@@ -632,8 +632,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
testCase.RequiredEOLProgress.StoreConfigurationDoneChecked = EOLStatus.OK;
testPp = new ExecStoreConfiguration("UnitTestExecStoreConfiguration");
- CommonCallClassCheck(testPp, testCase,
- ref testResult);
+ CommonCallClassCheck(testPp, testCase, ref testResult);
}
else
{
@@ -679,10 +678,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
testCase.RequiredEOLProgress.ParametrizationCompareChecked =
paramsCheckWillSucceed ? EOLStatus.OK : EOLStatus.FAIL;
- testPp = new CheckFinalParametrization(
- "UnitTestCheckFinalParametrization");
- CommonCallClassCheck(testPp, testCase,
- ref testResult);
+ testPp = new CheckFinalParametrization("UnitTestCheckFinalParametrization");
+ CommonCallClassCheck(testPp, testCase, ref testResult);
break;
}
}
diff --git a/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs b/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs
index 1eae9842..ed4519f2 100644
--- a/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs
+++ b/Common/Production/ProductionUiCordonel/FinalTest.xaml.cs
@@ -393,7 +393,16 @@ namespace Xylem.Common.Production.ProductionUiCordonel
// Stop all procedures
if (e.State == ProcessState.Stop)
{
- BtnStop_Click(this, null);
+ _timer?.Stop();
+ UiElmEnable(btnStart, true);
+ UiElmEnable(btnStop, false);
+ // update progress bars
+ ProcessProgress_Handler(this, new ProcessProgressArgs(0,
+ ProcessProgressArgs.ProcessProgressType.OverallProcessesSteps));
+ ProcessProgress_Handler(this, new ProcessProgressArgs(0,
+ ProcessProgressArgs.ProcessProgressType.ActualProcessSteps));
+ // remove user control
+ SetNewUserControl(null);
}
// Repeat failed tests
if (e.State == ProcessState.RepeatFailedTests)
@@ -849,18 +858,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel
///
private void BtnStop_Click(Object sender, RoutedEventArgs e)
{
- _timer?.Stop();
- UiElmEnable(btnStart, true);
- UiElmEnable(btnStop, false);
//set the process state to the state machine
_processCtrl?.SetProcessState(ProcessState.Stop);
- // update progress bars
- ProcessProgress_Handler(this, new ProcessProgressArgs(0,
- ProcessProgressArgs.ProcessProgressType.OverallProcessesSteps));
- ProcessProgress_Handler(this, new ProcessProgressArgs(0,
- ProcessProgressArgs.ProcessProgressType.ActualProcessSteps));
- // remove user control
- SetNewUserControl(null);
}
///
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs
index b8b74ff5..09391fba 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/BaseProductionProcess.cs
@@ -154,6 +154,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
// assembly version information
private static readonly Version _version = Assembly.GetExecutingAssembly().GetName().Version;
+ ///
+ public CancellationToken CancellationToken { set; get; }
+
///
public event EventHandler OnSingleProcessStateChanged;
@@ -248,6 +251,18 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
return retVal;
}
+ ///
+ /// Action for cancellation token to abort process
+ ///
+ ///
+ /// - Initial
+ ///
+ protected StatusReturn CancellationProcedure()
+ {
+ AbortProcess();
+ return StatusReturn.Failed;
+ }
+
///
/// Set new single process state and fire event from base class:
/// - First set new SingleProcessState,
@@ -298,7 +313,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
var processExec = new ProcessExec();
processExec.NewProcess(InitProcess, PreExecuteProcess, ExecuteProcess, FinalizeProcess,
- _cultureInfo, exitProcessStateObjects);
+ _cultureInfo, exitProcessStateObjects, CancellationToken);
}
///
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs
index 0b4a9e2d..e3a08504 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs
@@ -46,6 +46,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
///
/// - Moved setting of time and reset counters from here to .
///
+ ///
+ /// - CancellationToken.
+ ///
public override StatusReturn ExecuteProcess()
{
// Uncheck executed process to leave the result open needed for retries
@@ -76,38 +79,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
}
}
- //// Get the time in UTC to program the time for the Cordonel in seconds since 01. Jan 2000
- //// to set the new UTC after reboot
- //var teaTime = new TimeT();
- //// Build byte array
- //var rawSeconds = RegisterConverter.ValueToByteArray(teaTime.UtcNowToSecondsSince2000);
- //var timerSetup = new ProgrammingParameters("SYSTEM_CalendarSeconds", rawSeconds,
- // ProgrammingSource.ProgramInternal);
- //// This is the manufacturing date of the Cordonel
- //var irdaMfgDate = new ProgrammingParameters("IRDA_MfgDate", rawSeconds,
- // ProgrammingSource.ProgramInternal);
- //// Reset reboot counter
- //var nullRebootCtr = new ProgrammingParameters("CUSTOMER_RebootCount", new Byte[] { 0x00 },
- // ProgrammingSource.ProgramInternal);
- //var retValBol = WriteRegisterLogAndProcessCtr(timerSetup);
- //retValBol &= WriteRegisterLogAndProcessCtr(irdaMfgDate);
- //retValBol &= WriteRegisterLogAndProcessCtr(nullRebootCtr);
- //if (Meter.RadioFrequencyMhz != null)
- //{
- // // Reset periodic log reset counter
- // var periodicLogResetCtr = new ProgrammingParameters("PERIODICLOG_ResetCounter", new Byte[] { 0x00 },
- // ProgrammingSource.ProgramInternal);
- // retValBol &= WriteRegisterLogAndProcessCtr(periodicLogResetCtr);
- // // Reset sensus radio reset counter
- // var sensusRadioResetCtr = new ProgrammingParameters("SENSUSRADIO_ResetCounter", new Byte[] { 0x00 },
- // ProgrammingSource.ProgramInternal);
- // retValBol &= WriteRegisterLogAndProcessCtr(sensusRadioResetCtr);
- //}
-
// Execute final read after reboot
RegisterRestorer.OnProcessUpdate += ProcessUpdate_Handler;
- var retValBol = RegisterRestorer.FinalReadRegisters();
- retValBol &= RegisterRestorer.CompareRegisters();
+ var retValBol = RegisterRestorer.FinalReadRegisters(CancellationToken);
+
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
+ retValBol &= RegisterRestorer.CompareRegisters(CancellationToken);
RegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler;
if (retValBol)
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs
index a526bfaa..d7979e17 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs
@@ -76,6 +76,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
///
/// - Extracted from for better testability.
///
+ ///
+ /// - CancellationToken.
+ ///
public override StatusReturn PreExecuteProcess()
{
if (Meter == null || string.IsNullOrEmpty(Meter.PcbId) || Meter.PcbId.Length < GenesisMeter.MinPcbIdLength)
@@ -95,6 +98,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
// Get the requirement (Standard or special)
@@ -106,6 +113,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
// Get clustered FileId of firmware package for production or on special requirement release candidates
@@ -123,6 +134,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
// Get the real content of the FW package including all binaries of each app and the application description file
@@ -135,6 +150,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
// Read out the Cordonel and calculate remaining lifetime and fill the ProductionStatus
@@ -145,6 +164,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
// Check if requirement will force skipping of calibration
@@ -159,6 +182,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
// Get the pre- and final flow test state.
@@ -171,6 +198,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
// Fill the results to calibration check register restorer which will be used to read the actual
@@ -200,10 +231,14 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
return StatusReturn.Failed;
}
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
// Activate logging to output
CalibCheckRegisterRestorer.OnProcessUpdate += ProcessUpdate_Handler;
// Read out all parameters from meter and compare it
- if (!CalibCheckRegisterRestorer.ReadPresetRegisters())
+ if (!CalibCheckRegisterRestorer.ReadPresetRegisters(CancellationToken))
{
// Stop logging
CalibCheckRegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler;
@@ -1220,7 +1255,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
CalibCheckRegisterRestorer.OnProcessUpdate += ProcessUpdate_Handler;
// Compare the database value and the meter value (read in advance in the PreExecuteProcess)
- if (!CalibCheckRegisterRestorer.CompareRegisters())
+ if (!CalibCheckRegisterRestorer.CompareRegisters(CancellationToken))
{
// Stop logging
CalibCheckRegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler;
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs
index 3d9f68fe..09ebe34b 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs
@@ -173,6 +173,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
///
/// - Separate TestInit and SirtInit (only if test shouldn't be skipped).
///
+ ///
+ /// - CancellationToken.
+ ///
public override StatusReturn ExecuteProcess()
{
// This will force to reset all values, Sentinel and Prepare shipping will fail based on EOL Progress
@@ -278,12 +281,20 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
ClearRssiMeasurement();
// kick off RSSI test
StartRssiMeasurement();
+
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ CancellationProcedure();
var exitTime = DateTime.Now + TimeSpan.FromSeconds(Timeout_s);
var actualTime = DateTime.Now;
// wait on result or timeout or stop request from main window
while (!_testFinished && exitTime > actualTime && SingleProcessState != SingleProcessState.Idle)
{
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ CancellationProcedure();
+
Thread.Sleep(TimeoutLoop_ms);
actualTime = DateTime.Now;
ActualProcessProgress++;
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs
index f5ee63d0..b17d558d 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs
@@ -97,7 +97,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
}
RegisterRestorer.OnProcessUpdate += ProcessUpdate_Handler;
- var retVal = RegisterRestorer.EolProgrammingRegisters(RegisterRestorer.RecoveryRegisters);
+ var retVal = RegisterRestorer.EolProgrammingRegisters(RegisterRestorer.RecoveryRegisters,
+ CancellationToken);
+
RegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler;
EolProgress.ParametrizationDoneChecked = retVal == StatusReturn.Okay ? EOLStatus.OK : EOLStatus.FAIL;
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs
index e46b0fa8..e91e74fb 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs
@@ -83,6 +83,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
///
/// - EOL progress signaled.
///
+ ///
+ /// - CancellationToken.
+ ///
public override StatusReturn ExecuteProcess()
{
// Uncheck executed process to leave the result open needed for retries
@@ -131,6 +134,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
retValBol = MeterPwdHandlerDb.RequestPwdFileFromDb(Meter.PcbId, out var pwdContainer);
ActualProcessProgress++;
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
if (!retValBol)
{
ucPwd.UpdateImage(ucPwd.imgRequestPassword, ImgState.Error);
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs
index 538c5d2f..2b071f93 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs
@@ -76,7 +76,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
};
_meterResetPsu.OnProcessUpdate += ProcessUpdate_Handler;
- var rebootSucceeded = _meterResetPsu.MeterResetPsuExecute();
+ var rebootSucceeded = _meterResetPsu.MeterResetPsuExecute(CancellationToken);
_meterResetPsu.OnProcessUpdate -= ProcessUpdate_Handler;
if (!rebootSucceeded)
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs
index 59d8bd64..51f82cd0 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs
@@ -57,6 +57,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
///
/// - Output error message from register restorer..
///
+ ///
+ /// - CancellationToken.
+ ///
public override StatusReturn ExecuteProcess()
{
SignalRunningState();
@@ -99,6 +102,11 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
if (!retVal)
return StatusReturn.Failed;
}
+
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
RegisterRestorer.RecoveryRegisters = new List();
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetSerialNumberAndRadioAddress.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetSerialNumberAndRadioAddress.cs
index 5c6b9768..efe7c97d 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetSerialNumberAndRadioAddress.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetSerialNumberAndRadioAddress.cs
@@ -38,6 +38,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
///
/// - Get customer serial number for display.
///
+ ///
+ /// - CancellationToken.
+ ///
public override StatusReturn ExecuteProcess()
{
if (Meter == null)
@@ -82,6 +85,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
if (!retVal) return StatusReturn.Failed;
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
retVal &= OrderDetailsDb.GetCordonelOrderDetails(Meter.OrderNumber, out var orderDetails);
if (!retVal)
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/PrepareShipping.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/PrepareShipping.cs
index 92364db8..cac3474e 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/PrepareShipping.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/PrepareShipping.cs
@@ -53,6 +53,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
///
/// - Redesigned.
///
+ ///
+ /// - CancellationToken.
+ ///
public override StatusReturn ExecuteProcess()
{
try
@@ -98,12 +101,17 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
{
eolTriggerReturn = EOLHandler.TriggerSentinel(Meter.PcbId, out feedback, out error);
dataBaseCallIsFinished = true;
- });
+ }, CancellationToken);
// Keep progress bar alive
while (!dataBaseCallIsFinished)
{
Thread.Sleep(TimeoutLoop_ms);
+
+ // Exit if meanwhile cancellation is required
+ if (CancellationToken.IsCancellationRequested)
+ return CancellationProcedure();
+
ActualProcessProgress++;
}
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/FinalProcessController.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/FinalProcessController.cs
index 4e9203b9..11d6a882 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/FinalProcessController.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/FinalProcessController.cs
@@ -80,7 +80,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
// progress bar and screen info of ongoing processes
public event EventHandler OnProcessProgressChanged;
- private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource();
+ // cancellation token
+ private CancellationTokenSource _cancellationTokenSource;
+ private CancellationToken _cancellationToken;
// cyclic timer for state machine call
private Timer _processCtrlTimer;
@@ -113,6 +115,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
{
_processCtrlTimer = new Timer(TmrProcessCtrlCycle_Elapsed, null, ProcessTimerCycleMs, ProcessTimerCycleMs);
_slot = slot;
+ _cancellationTokenSource = new CancellationTokenSource();
+ _cancellationToken = _cancellationTokenSource.Token;
InitNewMeter();
InitProcesses();
// program start with idle process
@@ -355,10 +359,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
switch (_stateMachineState)
{
case ProcessState.Idle:
- // This state need an external state change like user input
+ // This state needs an external state change like user input to go ahead
break;
case ProcessState.DetectCordonel:
+ // 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();
@@ -522,9 +531,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
break;
}//
}
- catch (ThreadAbortException)
+ catch (ThreadAbortException ex)
{
- throw;
+ _genesisMeter?.WriteLog(ex.Message);
+ _stateMachineState = ProcessState.Idle;
}
catch (Exception ex)
{
@@ -835,6 +845,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
process.ProductionStatus = _productionStatus;
process.ProductionRequirements = _cordonelRequirements;
process.EolProgress = _cordonelEolProgress;
+ process.CancellationToken = _cancellationToken;
// kick off process execution, the breakExitState will not be used
process.StartProcess(successExitState, errorExitState, breakExitState);
@@ -935,6 +946,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
///
private void KillProcesses()
{
+ _cancellationTokenSource?.Cancel();
+ Thread.Sleep(1000);
+
if (Processes == null || Processes.Count == 0)
return;
@@ -942,8 +956,6 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
foreach (var pp in Processes)
{
pp.IdleProcess();
- if (_registerRestorer != null)
- _registerRestorer.StopRegisterAccess = true;
}
}
diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/IProductionProcess.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/IProductionProcess.cs
index 08fd6e4c..cf8c9e31 100644
--- a/Common/Production/ProductionUiCordonel/ProductionProcesses/IProductionProcess.cs
+++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/IProductionProcess.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading;
using System.Windows.Controls;
using LaaPackages.Features.Cordonel.Models;
using Xylem.Common.CommonCore.Consts;
@@ -13,6 +14,11 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
{
public interface IProductionProcess
{
+ ///
+ /// Cancellation token to stop operation
+ ///
+ CancellationToken CancellationToken { set; get; }
+
///
/// Event for process list change or state of single process step change from wait to execute to done or error
///
diff --git a/Common/Utils/ProcessExec/ProcessExec.cs b/Common/Utils/ProcessExec/ProcessExec.cs
index 82e67300..70bff0ea 100644
--- a/Common/Utils/ProcessExec/ProcessExec.cs
+++ b/Common/Utils/ProcessExec/ProcessExec.cs
@@ -48,16 +48,20 @@ namespace Xylem.Common.Utils.ProcessExec
/// finalizing function
/// language selection passing
/// exit objects
+ ///
///
/// - Initial.
///
- ///
+ ///
/// - Function for pre-execution before the main execution starts being executed in the new
/// thread.
///
+ ///
+ /// - CancellationToken.
+ ///
public void NewProcess(VoidCallbackFunction initFn, StatusReturnCallbackFunction preExecFn,
StatusReturnCallbackFunction execFn, ExitStateCallbackFunction finalFn,
- CultureInfo cultureInfo, Object[] exitObjects)
+ CultureInfo cultureInfo, Object[] exitObjects, CancellationToken cancellationToken)
{
_exitObjects = new Object[exitObjects.Length];
_exitObjects = exitObjects;
@@ -72,15 +76,17 @@ namespace Xylem.Common.Utils.ProcessExec
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = cultureInfo;
- if (preExecFn != null)
+ if (preExecFn != null && !cancellationToken.IsCancellationRequested)
success = (StatusReturn)preExecFn.DynamicInvoke();
- if (execFn == null || success != StatusReturn.Okay)
+ if (execFn == null || success != StatusReturn.Okay || cancellationToken.IsCancellationRequested)
return;
success = (StatusReturn)execFn.DynamicInvoke();
- }).ContinueWith(delegate { finalFn?.Invoke(success, _exitObjects); });
+ }, cancellationToken)
+ .ContinueWith(delegate { finalFn?.Invoke(success, _exitObjects); },
+ TaskContinuationOptions.NotOnCanceled);
}
}
}