laatzen/ZeroFlowTool/LogOn.cs
2021-10-01 11:12:07 +02:00

476 lines
25 KiB
C#

using System;
using System.Linq;
using System.Globalization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace GenesisZeroFlow
{
public static class LogOnSequences
{
public static Boolean[] Total(Boolean[] enable, CmdInterface[] commandInterface, String[] password, UInt16 numberOfTrials, out Boolean aborted, CultureInfo culture)
{
#region Definitions and initializations
Boolean[] SequenceFailed = new Boolean[Constants.NumberOfMeters];
Boolean[] TaskStarted = new Boolean[Constants.NumberOfMeters];
Boolean[] TaskCompleted = new Boolean[Constants.NumberOfMeters];
Int32 NextDelayTime = 0;
aborted = false;
for (UInt16 Meter = Constants.Meter1; Meter < Constants.NumberOfMeters; Meter++)
{
SequenceFailed[Meter] = false;
TaskStarted[Meter] = false;
TaskCompleted[Meter] = false;
}
#region CA1062
if ((enable == null) || (password == null) || (commandInterface == null))
return SequenceFailed;
#endregion
LogOn LogOn1 = new LogOn();
LogOn LogOn2 = new LogOn();
LogOn LogOn3 = new LogOn();
LogOn LogOn4 = new LogOn();
LogOn LogOn5 = new LogOn();
LogOn LogOn6 = new LogOn();
LogOn LogOn7 = new LogOn();
LogOn LogOn8 = new LogOn();
LogOn LogOn9 = new LogOn();
LogOn LogOn10 = new LogOn();
LogOn1.Initialize(commandInterface[Constants.Meter1], Constants.Meter, password[Constants.Meter1], Constants.Meter1, numberOfTrials, culture);
LogOn2.Initialize(commandInterface[Constants.Meter2], Constants.Meter, password[Constants.Meter2], Constants.Meter2, numberOfTrials, culture);
LogOn3.Initialize(commandInterface[Constants.Meter3], Constants.Meter, password[Constants.Meter3], Constants.Meter3, numberOfTrials, culture);
LogOn4.Initialize(commandInterface[Constants.Meter4], Constants.Meter, password[Constants.Meter4], Constants.Meter4, numberOfTrials, culture);
LogOn5.Initialize(commandInterface[Constants.Meter5], Constants.Meter, password[Constants.Meter5], Constants.Meter5, numberOfTrials, culture);
LogOn6.Initialize(commandInterface[Constants.Meter6], Constants.Meter, password[Constants.Meter6], Constants.Meter6, numberOfTrials, culture);
LogOn7.Initialize(commandInterface[Constants.Meter7], Constants.Meter, password[Constants.Meter7], Constants.Meter7, numberOfTrials, culture);
LogOn8.Initialize(commandInterface[Constants.Meter8], Constants.Meter, password[Constants.Meter8], Constants.Meter8, numberOfTrials, culture);
LogOn9.Initialize(commandInterface[Constants.Meter9], Constants.Meter, password[Constants.Meter9], Constants.Meter9, numberOfTrials, culture);
LogOn10.Initialize(commandInterface[Constants.Meter10], Constants.Meter, password[Constants.Meter10], Constants.Meter10, numberOfTrials, culture);
#endregion
#region Perform test
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
#region METER1
Task<Boolean> Task1 = new Task<Boolean>(() => { return true; });
LogOn1.Meter(enable[Constants.Meter1], ref Task1, ref TaskStarted[Constants.Meter1], ref SequenceFailed[Constants.Meter1], LogOn1, ref NextDelayTime, token);
#endregion
#region METER2
Task<Boolean> Task2 = new Task<Boolean>(() => { return true; });
LogOn2.Meter(enable[Constants.Meter2], ref Task2, ref TaskStarted[Constants.Meter2], ref SequenceFailed[Constants.Meter2], LogOn2, ref NextDelayTime, token);
#endregion
#region METER3
Task<Boolean> Task3 = new Task<Boolean>(() => { return true; });
LogOn3.Meter(enable[Constants.Meter3], ref Task3, ref TaskStarted[Constants.Meter3], ref SequenceFailed[Constants.Meter3], LogOn3, ref NextDelayTime, token);
#endregion
#region METER4
Task<Boolean> Task4 = new Task<Boolean>(() => { return true; });
LogOn4.Meter(enable[Constants.Meter4], ref Task4, ref TaskStarted[Constants.Meter4], ref SequenceFailed[Constants.Meter4], LogOn4, ref NextDelayTime, token);
#endregion
#region METER5
Task<Boolean> Task5 = new Task<Boolean>(() => { return true; });
LogOn5.Meter(enable[Constants.Meter5], ref Task5, ref TaskStarted[Constants.Meter5], ref SequenceFailed[Constants.Meter5], LogOn5, ref NextDelayTime, token);
#endregion
#region METER6
Task<Boolean> Task6 = new Task<Boolean>(() => { return true; });
LogOn6.Meter(enable[Constants.Meter6], ref Task6, ref TaskStarted[Constants.Meter6], ref SequenceFailed[Constants.Meter6], LogOn6, ref NextDelayTime, token);
#endregion
#region METER7
Task<Boolean> Task7 = new Task<Boolean>(() => { return true; });
LogOn7.Meter(enable[Constants.Meter7], ref Task7, ref TaskStarted[Constants.Meter7], ref SequenceFailed[Constants.Meter7], LogOn7, ref NextDelayTime, token);
#endregion
#region METER8
Task<Boolean> Task8 = new Task<Boolean>(() => { return true; });
LogOn8.Meter(enable[Constants.Meter8], ref Task8, ref TaskStarted[Constants.Meter8], ref SequenceFailed[Constants.Meter8], LogOn8, ref NextDelayTime, token);
#endregion
#region METER9
Task<Boolean> Task9 = new Task<Boolean>(() => { return true; });
LogOn9.Meter(enable[Constants.Meter9], ref Task9, ref TaskStarted[Constants.Meter9], ref SequenceFailed[Constants.Meter9], LogOn9, ref NextDelayTime, token);
#endregion
#region METER10
Task<Boolean> Task10 = new Task<Boolean>(() => { return true; });
LogOn10.Meter(enable[Constants.Meter10], ref Task10, ref TaskStarted[Constants.Meter10], ref SequenceFailed[Constants.Meter10], LogOn10, ref NextDelayTime, token);
#endregion
#endregion
#region Wait for tasks
Int32[] KeepAuthentifiedCounter = new Int32[Constants.NumberOfMeters];
Boolean[] SequenceOk = new Boolean[Constants.NumberOfMeters];
for (UInt16 Meter = Constants.Meter1; Meter < Constants.NumberOfMeters; Meter++)
{
KeepAuthentifiedCounter[Meter] = 0;
SequenceOk[Meter] = false;
}
while (!CheckArray(TaskCompleted))
{
if (GenesisZeroFlow._GenesisZeroFlow.AbortIndicator)
{
aborted = true;
cancellationTokenSource.Cancel();
}
TaskCompleted[Constants.Meter1] = TaskOperations.WaitFor(TaskStarted[Constants.Meter1], Task1);
TaskCompleted[Constants.Meter2] = TaskOperations.WaitFor(TaskStarted[Constants.Meter2], Task2);
TaskCompleted[Constants.Meter3] = TaskOperations.WaitFor(TaskStarted[Constants.Meter3], Task3);
TaskCompleted[Constants.Meter4] = TaskOperations.WaitFor(TaskStarted[Constants.Meter4], Task4);
TaskCompleted[Constants.Meter5] = TaskOperations.WaitFor(TaskStarted[Constants.Meter5], Task5);
TaskCompleted[Constants.Meter6] = TaskOperations.WaitFor(TaskStarted[Constants.Meter6], Task6);
TaskCompleted[Constants.Meter7] = TaskOperations.WaitFor(TaskStarted[Constants.Meter7], Task7);
TaskCompleted[Constants.Meter8] = TaskOperations.WaitFor(TaskStarted[Constants.Meter8], Task8);
TaskCompleted[Constants.Meter9] = TaskOperations.WaitFor(TaskStarted[Constants.Meter9], Task9);
TaskCompleted[Constants.Meter10] = TaskOperations.WaitFor(TaskStarted[Constants.Meter10], Task10);
LogOn1.KeepAuthentified(enable[Constants.Meter1], SequenceOk[Constants.Meter1], TaskCompleted[Constants.Meter1], ref KeepAuthentifiedCounter[Constants.Meter1]);
LogOn2.KeepAuthentified(enable[Constants.Meter2], SequenceOk[Constants.Meter2], TaskCompleted[Constants.Meter2], ref KeepAuthentifiedCounter[Constants.Meter2]);
LogOn3.KeepAuthentified(enable[Constants.Meter3], SequenceOk[Constants.Meter3], TaskCompleted[Constants.Meter3], ref KeepAuthentifiedCounter[Constants.Meter3]);
LogOn4.KeepAuthentified(enable[Constants.Meter4], SequenceOk[Constants.Meter4], TaskCompleted[Constants.Meter4], ref KeepAuthentifiedCounter[Constants.Meter4]);
LogOn5.KeepAuthentified(enable[Constants.Meter5], SequenceOk[Constants.Meter5], TaskCompleted[Constants.Meter5], ref KeepAuthentifiedCounter[Constants.Meter5]);
LogOn6.KeepAuthentified(enable[Constants.Meter6], SequenceOk[Constants.Meter6], TaskCompleted[Constants.Meter6], ref KeepAuthentifiedCounter[Constants.Meter6]);
LogOn7.KeepAuthentified(enable[Constants.Meter7], SequenceOk[Constants.Meter7], TaskCompleted[Constants.Meter7], ref KeepAuthentifiedCounter[Constants.Meter7]);
LogOn8.KeepAuthentified(enable[Constants.Meter8], SequenceOk[Constants.Meter8], TaskCompleted[Constants.Meter8], ref KeepAuthentifiedCounter[Constants.Meter8]);
LogOn9.KeepAuthentified(enable[Constants.Meter9], SequenceOk[Constants.Meter9], TaskCompleted[Constants.Meter9], ref KeepAuthentifiedCounter[Constants.Meter9]);
LogOn10.KeepAuthentified(enable[Constants.Meter10], SequenceOk[Constants.Meter10], TaskCompleted[Constants.Meter10], ref KeepAuthentifiedCounter[Constants.Meter10]);
Misc.WaitNSeconds(1);
SequenceFailed = TaskOperations.GetResultTotal(TaskStarted, Task1, Task2, Task3, Task4, Task5, Task6, Task7, Task8, Task9, Task10);
for (UInt16 Meter = Constants.Meter1; Meter < Constants.NumberOfMeters; Meter++)
SequenceOk[Meter] = !SequenceFailed[Meter];
GenesisZeroFlow.Display.MeterStatusGreenRed(SequenceOk, TaskStarted);
// GenesisZeroFlow.Display.ShowResultStatus("Login sequence OK (while loop) = ", SequenceOk);
}
#endregion
#region Destroy tasks
SequenceFailed = TaskOperations.GetResultTotal(TaskStarted, Task1, Task2, Task3, Task4, Task5, Task6, Task7, Task8, Task9, Task10);
for (UInt16 Meter = Constants.Meter1; Meter < Constants.NumberOfMeters; Meter++)
SequenceOk[Meter] = !SequenceFailed[Meter];
GenesisZeroFlow.Display.MeterStatusGreenRed(SequenceOk, TaskStarted);
// GenesisZeroFlow.Display.ShowResultStatus("Login sequence failed = ", SequenceFailed);
// GenesisZeroFlow.Display.ShowResultStatus("Task Completed = ", TaskCompleted);
TaskOperations.CheckAndDispose(ref Task1);
TaskOperations.CheckAndDispose(ref Task2);
TaskOperations.CheckAndDispose(ref Task3);
TaskOperations.CheckAndDispose(ref Task4);
TaskOperations.CheckAndDispose(ref Task5);
TaskOperations.CheckAndDispose(ref Task6);
TaskOperations.CheckAndDispose(ref Task7);
TaskOperations.CheckAndDispose(ref Task8);
TaskOperations.CheckAndDispose(ref Task9);
TaskOperations.CheckAndDispose(ref Task10);
#endregion
return SequenceFailed;
}
private static Boolean CheckArray(Boolean[] array)
{
Boolean Completed = true;
for (Int16 i = 0; i < array.Count(); i++)
{
if (Boolean.Equals(array[i], false))
return false;
}
return Completed;
}
public static Boolean CheckIfNoMeterSelected(Boolean[] meterSelected)
{
Boolean noMeterSelected = true;
#region CA1062
if (meterSelected == null)
return noMeterSelected;
#endregion
for (Int16 i = 0; i < meterSelected.Count(); i++)
{
if (meterSelected[i])
noMeterSelected = false;
}
return noMeterSelected;
}
public static Boolean CheckIfPortIndicatorsValid(Boolean[] meterSelected, Boolean[] serialPortOpenIndicator)
{
Boolean portIndicatorsValid = true;
#region CA1062
if ((meterSelected == null) || (serialPortOpenIndicator == null))
return portIndicatorsValid = false; ;
#endregion
for (Int16 i = 0; i < meterSelected.Count(); i++)
{
if (meterSelected[i] != (serialPortOpenIndicator[i] & serialPortOpenIndicator[Constants.NumberOfMeters + i]))
portIndicatorsValid = false;
}
return portIndicatorsValid;
}
}
public class LogOn
{
private String Password { get; set; }
private UInt16 MeterNumber { get; set; }
private String MeterIndex { get; set; }
private String MeterType { get; set; }
private UInt16 NumberOfTrials { get; set; }
private CultureInfo Culture { get; set; }
private SerialPort SerialPort { get; set; }
private CmdInterface CommandInterface { get; set; }
public void Initialize(CmdInterface commandInterface, String meterType, String password, UInt16 meterNumber, UInt16 numberOfTrials, CultureInfo culture)
{
this.Password = password;
this.MeterNumber = meterNumber;
this.NumberOfTrials = numberOfTrials;
this.CommandInterface = commandInterface;
this.Culture = culture;
this.MeterIndex = (meterNumber + 1).ToString(culture);
this.MeterType = meterType;
}
public Boolean PerformLogOn(CancellationToken token, out String debugMessage)
{
#region Definitions and initializations
Boolean reAuthentication = false;
Boolean Ok = false;
UInt16 Trials = 0;
Byte[] Password = new Byte[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
String DebugMessage = String.Empty;
#endregion
#region Get password
debugMessage = String.Empty;
if (this.Password.Count() != 12)
{
debugMessage = $"COMMAND CHANNEL:\t Password length wrong at {this.MeterType}{this.MeterIndex}\n";
return Ok;
}
Boolean OnlyHex = Misc.OnlyHexInString(this.Password);
if (!OnlyHex)
{
if (String.IsNullOrEmpty(this.Password))
debugMessage = $"COMMAND CHANNEL:\t Missing password at {this.MeterType}{this.MeterIndex}\n";
else
debugMessage = $"COMMAND CHANNEL:\t Password contains invalid characters at {this.MeterType}{MeterIndex}\n";
return Ok;
}
Password = Encoding.ASCII.GetBytes(this.Password);
#endregion
#region Send data to privilege register
Trials = 0;
Ok = false;
while ((Trials < this.NumberOfTrials) && (Boolean.Equals(Ok, false)) && (Boolean.Equals(reAuthentication, false)))
{
if (token.IsCancellationRequested)
return false;
GenesisZeroFlow.Display.DebugMessage($"COMMAND CHANNEL:\t Writing '8' to 'Privilege'-register at {this.MeterType}{this.MeterIndex}; Trial: {(Trials + 1).ToString(this.Culture)} of {this.NumberOfTrials}\n", this.Culture);
Ok = this.SetPrivilegeRegister(8, out DebugMessage);
if (Ok)
GenesisZeroFlow.Display.DebugMessage($"COMMAND CHANNEL:\t Writing '8' to 'Privilege'-register successful at {this.MeterType}{this.MeterIndex}\n", this.Culture);
else
{
GenesisZeroFlow.Display.DebugMessage($"COMMAND CHANNEL:\t Writing '8' to 'Privilege'-register failed at {this.MeterType}{this.MeterIndex}\n", this.Culture);
if ((Byte.Equals(this.CommandInterface.Subreason, GP30ConfigExErrors.AccessDenied)) || (Byte.Equals(this.CommandInterface.Subreason, GP30ConfigExErrors.LockedOut)))
reAuthentication = true;
}
Trials++;
}
if (Boolean.Equals(Ok, false))
return Ok;
#endregion
#region Send data to password register
Trials = 0;
Ok = false;
while ((Trials < this.NumberOfTrials) && (Boolean.Equals(Ok, false)) && (Boolean.Equals(reAuthentication, false)))
{
if (token.IsCancellationRequested)
return false;
GenesisZeroFlow.Display.DebugMessage($"COMMAND CHANNEL:\t Writing to 'Password'-register at {this.MeterType}{this.MeterIndex}; Trial: {(Trials + 1).ToString(this.Culture)} of {this.NumberOfTrials}\n", this.Culture);
Ok = this.SetPasswordRegister(Password, out DebugMessage);
if (Ok)
GenesisZeroFlow.Display.DebugMessage($"COMMAND CHANNEL:\t Writing to 'Password'-register successful at {this.MeterType}{this.MeterIndex}\n", this.Culture);
else
{
GenesisZeroFlow.Display.DebugMessage($"COMMAND CHANNEL:\t Writing to 'Password'-register failed at {this.MeterType}{this.MeterIndex}\n", this.Culture);
if ((Byte.Equals(this.CommandInterface.Subreason, GP30ConfigExErrors.AccessDenied)) || (Byte.Equals(this.CommandInterface.Subreason, GP30ConfigExErrors.LockedOut)))
reAuthentication = true;
}
Trials++;
}
if (Boolean.Equals(Ok, false))
return Ok;
#endregion
#region Command memory
this.CommandInterface.GP30LastCommand = GP30Commands.MultipleWritedata;
this.CommandInterface.SetGP30LastRegister(GP30Registers.Password());
#endregion
return Ok;
}
public void Meter(Boolean enable, ref Task<Boolean> task, ref Boolean taskStarted, ref Boolean sequenceFailed, LogOn logOn, ref Int32 nextDelayTime, CancellationToken token)
{
#region Definitions and initializations
Int32 DelayTime = 0;
const Int32 DeltaDelay = 5;
DialogResult AskForActions = DialogResult.None;
var _sequenceFailed = sequenceFailed;
var _logOn = logOn;
String DebugMessage = String.Empty;
Int32 temp = DelayTime;
Boolean Ok = false;
#endregion
#region Avoid CA1062
if (task == null)
return;
#endregion
#region Everything else
if ((enable) && (task.Status != TaskStatus.Running) && (!task.IsCompleted))
{
DelayTime = nextDelayTime;
nextDelayTime = nextDelayTime + DeltaDelay;
taskStarted = true;
Misc.WaitNSeconds(temp);
task = Task.Run(() =>
{
while ((DialogResult.Equals(AskForActions, DialogResult.Retry)) || (DialogResult.Equals(AskForActions, DialogResult.None)))
{
#region Login procedure
if (DialogResult.Equals(AskForActions, DialogResult.None))
GenesisZeroFlow.Display.DebugMessage($"APPLICATION:\t\t LOGIN started at {this.MeterType}{this.MeterIndex}\n", this.Culture);
Ok = _logOn.PerformLogOn(token, out DebugMessage);
if (token.IsCancellationRequested)
{
GenesisZeroFlow.Display.DebugMessage($"APPLICATION:\t\t LOGIN aborted at {this.MeterType}{this.MeterIndex}\n", this.Culture);
return true;
}
if (Ok)
{
GenesisZeroFlow.Display.DebugMessage($"APPLICATION:\t\t LOGIN successful at {this.MeterType}{this.MeterIndex}\n", this.Culture);
_sequenceFailed = false;
AskForActions = DialogResult.OK;
}
else
{
GenesisZeroFlow.Display.DebugMessage($"APPLICATION:\t\t LOGIN failed at {this.MeterType}{this.MeterIndex}\n", this.Culture);
_sequenceFailed = true;
AskForActions = AskHowToProceedSequence("LOGIN");
}
#endregion
}
return _sequenceFailed;
});
}
#endregion
}
private DialogResult AskHowToProceedSequence(String sequenceName)
{
DialogResult AskForActions;
GenesisZeroFlow.Display.AbortButtonEnabled(false);
AskForActions = MessageBox.Show($"{sequenceName} failed at {this.MeterType}{this.MeterIndex}", "Retry?", MessageBoxButtons.RetryCancel, MessageBoxIcon.Question);
switch (AskForActions)
{
case DialogResult.Retry:
GenesisZeroFlow.Display.DebugMessage($"APPLICATION:\t\t {sequenceName} restarted at {this.MeterType}{this.MeterIndex}\n", this.Culture);
break;
case DialogResult.Cancel:
GenesisZeroFlow.Display.DebugMessage($"APPLICATION:\t\t {sequenceName} canceled at {this.MeterType}{this.MeterIndex}\n", this.Culture);
GenesisZeroFlow.Display.DebugMessage(Debugmessages.Line, this.Culture);
break;
default: break;
}
GenesisZeroFlow.Display.AbortButtonEnabled(true);
return AskForActions;
}
public void KeepAuthentified(Boolean enable, Boolean sequenceOk, Boolean taskCompleted, ref Int32 counter)
{
const Int32 CounterValue = 30;
if (enable && taskCompleted && sequenceOk && (counter >= CounterValue))
{
GenesisZeroFlow.Display.DebugMessage($"COMMAND CHANNEL:\t Keep authentified at {this.MeterType}{this.MeterIndex}\n", this.Culture);
String DebugMessage = String.Empty;
this.GetLedModeRegister(out DebugMessage);
counter = 0;
}
else
counter++;
}
private Boolean SetPrivilegeRegister(Int32 value, out String debugMessage)
{
#region Definitions and initializations
Byte[] Payload = new Byte[4] { 0, 0, 0, 0 };
Boolean Ok = false;
Int32 ErrCode = GP30LowLevelErrors.NoError;
#endregion
#region Write register
Payload = BitConverter.GetBytes((Int32)value);
ErrCode = this.CommandInterface.WriteRegister(GP30Registers.Privilege(), Payload, true);
#endregion
#region Wait for answer
if (Int32.Equals(ErrCode, GP30LowLevelErrors.NoError))
ErrCode = this.CommandInterface.RXProcessor(GP30RequestType.WriteRegister);
#endregion
#region Debug message
debugMessage = this.CommandInterface.LowLevelMessages(ErrCode, out Ok);
#endregion
return Ok;
}
private Boolean SetPasswordRegister(Byte[] password, out String debugMessage)
{
#region Definitions and initializations
Boolean Ok = false;
Int32 ErrCode = GP30LowLevelErrors.NoError;
#endregion
#region Write register
ErrCode = this.CommandInterface.MultipleWriteRegister(GP30Registers.Password(), password, true);
#endregion
#region Wait for answer
if (Int32.Equals(ErrCode, GP30LowLevelErrors.NoError))
ErrCode = this.CommandInterface.RXProcessor(GP30RequestType.MultipleWrite);
#endregion
#region Debug message
debugMessage = this.CommandInterface.LowLevelMessages(ErrCode, out Ok);
#endregion
return Ok;
}
private Boolean GetLedModeRegister(out String debugMessage)
{
#region Definitions and initialisations
Boolean Ok = false;
Int32 ErrCode = GP30LowLevelErrors.NoError;
#endregion
#region Read register
ErrCode = this.CommandInterface.ReadRegister(GP30Registers.LedMode());
#endregion
#region Wait for answer
if (Int32.Equals(ErrCode, GP30LowLevelErrors.NoError))
ErrCode = this.CommandInterface.RXProcessor(GP30RequestType.ReadRegister);
#endregion
#region Debug message
debugMessage = this.CommandInterface.LowLevelMessages(ErrCode, out Ok);
#endregion
return Ok;
}
}
}