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 Task1 = new Task(() => { 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 Task2 = new Task(() => { 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 Task3 = new Task(() => { 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 Task4 = new Task(() => { 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 Task5 = new Task(() => { 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 Task6 = new Task(() => { 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 Task7 = new Task(() => { 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 Task8 = new Task(() => { 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 Task9 = new Task(() => { 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 Task10 = new Task(() => { 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 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; } } }