diff --git a/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs b/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs index b451d1ad7..510c87cf0 100644 --- a/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs +++ b/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs @@ -243,6 +243,16 @@ namespace GenesisCordonelInterface.API return string.IsNullOrWhiteSpace(port) ? "" : port; } + public ConcurrentDictionary GetRegistersDicForSlot(int slot) + { + var meter = GetMeterThreadSafe(slot); + + if (meter == null) + throw new Exception($"Slot {slot} not initialized."); + + return meter.GetRegistersDic(); + } + #endregion #region ================================== INIT/UPDATE ================================== @@ -1748,6 +1758,163 @@ namespace GenesisCordonelInterface.API #endregion + #region ================================== PreAdjustmentUI AMPLITUDE TEST process ================================== + + /// + /// Execute standalone amplitude test process. + /// + public Task Preadjustment_AmplitudeTestAsync( + ProcessProgress pp, + CancellationToken token = default) + { + if (pp.Setting.TempOnly) + return Task.FromResult(true); + + IProcess process; + + if (pp.Setting.NumberOfPaths == 1) + { + process = + new SPAmplitudeTestProcess( + "Amplitude Test Single", + PreAdjustmentControl.StatusPanelItems.Amplitude, + PreAdjustmentControl.PredefinedMessages.WaitUntilAmplitudeTestFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.AmplitudeFailed(pp.Setting.Culture), + 4 * 60); + } + else + { + process = + new AmplitudeTestProcess( + "Amplitude Test", + PreAdjustmentControl.StatusPanelItems.Amplitude, + PreAdjustmentControl.PredefinedMessages.WaitUntilAmplitudeTestFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.AmplitudeFailed(pp.Setting.Culture), + 4 * 60); + } + + return ExecuteProcessAsync( + process, + pp, + token); + } + + #endregion + + #region ================================== PreAdjustmentUI TEMPERATURE CALIBRATION process ================================== + + public Task Preadjustment_TemperatureCalibrationAsync( + ProcessProgress pp, + CancellationToken token = default) + { + IProcess process; + + if (pp.Setting.NumberOfPaths == 1) + { + process = + new SPTemperatureCalibrationProcess( + "Temperature Calibration Single", + PreAdjustmentControl.StatusPanelItems.TempCal, + PreAdjustmentControl.PredefinedMessages.WaitUntilTemperatureCalibrationFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.TempCalFailed(pp.Setting.Culture), + 2 * 60); + } + else + { + process = + new TemperatureCalibrationProcess( + "Temperature Calibration", + PreAdjustmentControl.StatusPanelItems.TempCal, + PreAdjustmentControl.PredefinedMessages.WaitUntilTemperatureCalibrationFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.TempCalFailed(pp.Setting.Culture), + 2 * 60); + } + + return ExecuteProcessAsync( + process, + pp, + token); + } + + #endregion + + #region ================================== PreAdjustmentUI OFFSET TEST process ================================== + + public Task Preadjustment_OffsetTestAsync( + ProcessProgress pp, + CancellationToken token = default) + { + if (pp.Setting.TempOnly) + return Task.FromResult(true); + + IProcess process; + + if (pp.Setting.NumberOfPaths == 1) + { + process = + new SPOffsetTestProcess( + "Offset Test Single", + PreAdjustmentControl.StatusPanelItems.Offset, + PreAdjustmentControl.PredefinedMessages.WaitUntilZeroflowOffsetTestFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.ZeroflowOffsetTestFailed(pp.Setting.Culture), + 18 * 60); + } + else + { + process = + new OffsetTestProcess( + "Offset Test", + PreAdjustmentControl.StatusPanelItems.Offset, + PreAdjustmentControl.PredefinedMessages.WaitUntilZeroflowOffsetTestFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.ZeroflowOffsetTestFailed(pp.Setting.Culture), + 18 * 60); + } + + return ExecuteProcessAsync( + process, + pp, + token); + } + + #endregion + + #region ================================== PreAdjustmentUI COMPLETION process ================================== + + public Task Preadjustment_CompletionAsync( + ProcessProgress pp, + CancellationToken token = default) + { + IProcess process; + + if (pp.Setting.NumberOfPaths == 1) + { + process = + new SPCompletionProcess( + "Completion Single", + PreAdjustmentControl.StatusPanelItems.Completion, + PreAdjustmentControl.PredefinedMessages.WaitUntilCompletionFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.CompletionFailed(pp.Setting.Culture), + 1 * 60); + } + else + { + process = + new CompletionProcess( + "Completion", + PreAdjustmentControl.StatusPanelItems.Completion, + PreAdjustmentControl.PredefinedMessages.WaitUntilCompletionFinished(pp.Setting.Culture), + PreAdjustmentControl.PredefinedMessages.CompletionFailed(pp.Setting.Culture), + 1 * 60); + } + + return ExecuteProcessAsync( + process, + pp, + token); + } + + #endregion + #region ================================== PreAdjustmentUI process threading ================================== public async Task ExecuteProcessAsync( diff --git a/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs b/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs index 40b6bd4ab..7082ea5ad 100644 --- a/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs +++ b/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs @@ -466,11 +466,37 @@ namespace GenesisCordonelInterface.API ProcessProgress pp, CancellationToken token = default) { - return _innerMeterAPI.Preadjustment_PreparationAsync( - pp, - token); + return _innerMeterAPI.Preadjustment_PreparationAsync(pp, token); } - + public Task Preadjustment_AmplitudeTestAsync( + ProcessProgress pp, + CancellationToken token = default) + { + return _innerMeterAPI.Preadjustment_AmplitudeTestAsync(pp, token); + } + + public Task Preadjustment_TemperatureCalibrationAsync( + ProcessProgress pp, + CancellationToken token = default) + { + return _innerMeterAPI.Preadjustment_TemperatureCalibrationAsync(pp, token); + } + + public Task Preadjustment_OffsetTestAsync( + ProcessProgress pp, + CancellationToken token = default) + { + return _innerMeterAPI.Preadjustment_OffsetTestAsync(pp, token); + } + + public Task Preadjustment_CompletionAsync( + ProcessProgress pp, + CancellationToken token = default) + { + return _innerMeterAPI.Preadjustment_CompletionAsync(pp, token); + } + + } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/Threading/RetryWorker/RetryWorker.cs b/GenesisCordonelInterface/Core/Threading/RetryWorker/RetryWorker.cs index 003395fbf..73f98e42f 100644 --- a/GenesisCordonelInterface/Core/Threading/RetryWorker/RetryWorker.cs +++ b/GenesisCordonelInterface/Core/Threading/RetryWorker/RetryWorker.cs @@ -25,6 +25,15 @@ namespace GenesisCordonelInterface.Core.Threading public static class RetryWorker { + /// + /// Executes an asynchronous operation with retry and timeout protection. + /// + /// Important: + /// The timeout here protects the caller from waiting forever, but it does not forcibly abort + /// the underlying hardware operation. Because hardware/COM calls may continue running after + /// the timeout signal, this method waits for the original action to finish before starting + /// the next retry. This prevents overlapping COM requests on the same device. + /// public static async Task> RunWithRetryAsync( Func> action, Func isSuccess, @@ -41,21 +50,53 @@ namespace GenesisCordonelInterface.Core.Threading for (int attempt = 1; attempt <= maxAttempts; attempt++) { - var actionTask = action(); - var timeoutTask = Task.Delay(timeoutMs); + Task actionTask = null; - var completedTask = await Task.WhenAny(actionTask, timeoutTask); - - if (completedTask == timeoutTask) + try { - timedOut = true; - log?.Invoke($"{operationName} timeout attempt {attempt}/{maxAttempts}"); - } - else - { - lastResult = await actionTask; + log?.Invoke($"{operationName} started. Attempt {attempt}/{maxAttempts}"); - if (isSuccess(lastResult)) + // Start real operation, for example Connect/GetPcbId/Login. + actionTask = action(); + + // Start independent timeout timer. + var timeoutTask = Task.Delay(timeoutMs); + + // Wait until either operation completes or timeout expires. + var completedTask = await Task.WhenAny(actionTask, timeoutTask) + .ConfigureAwait(false); + + if (completedTask == timeoutTask) + { + timedOut = true; + + log?.Invoke( + $"{operationName} timed out. Attempt {attempt}/{maxAttempts}. " + + "Waiting for the running operation to finish before retry."); + + // Critical part: + // Do NOT immediately start another retry. + // The hardware operation may still be active in ApiWorker. + // Starting another attempt immediately could corrupt communication. + try + { + lastResult = await actionTask.ConfigureAwait(false); + } + catch (Exception ex) + { + log?.Invoke( + $"{operationName} finished after timeout with exception: " + + $"{ex.GetType().Name}: {ex.Message}"); + } + } + else + { + // Operation completed before timeout. + lastResult = await actionTask.ConfigureAwait(false); + } + + // Decide whether the returned result means success. + if (lastResult != null && isSuccess(lastResult)) { return new RetryResult { @@ -63,15 +104,29 @@ namespace GenesisCordonelInterface.Core.Threading Success = true, Attempts = attempt, Duration = DateTime.Now - started, - TimedOut = false + TimedOut = timedOut }; } - logResult?.Invoke($"{operationName} failed attempt {attempt}/{maxAttempts}", lastResult); + logResult?.Invoke( + $"{operationName} failed. Attempt {attempt}/{maxAttempts}", + lastResult); + } + catch (Exception ex) + { + // Covers exceptions thrown before timeout handling or by action startup. + log?.Invoke( + $"{operationName} exception on attempt {attempt}/{maxAttempts}: " + + $"{ex.GetType().Name}: {ex.Message}"); } + // Delay before next retry, except after the final attempt. if (attempt < maxAttempts) - await Task.Delay(delayMs); + { + log?.Invoke($"{operationName} waiting {delayMs} ms before retry."); + + await Task.Delay(delayMs).ConfigureAwait(false); + } } return new RetryResult diff --git a/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs b/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs index 48403914b..cb7bd1b48 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs @@ -1505,6 +1505,182 @@ namespace TBF.Rig.BridgeComponents.GciBridge #endregion + #region ================================== PreAdjustment AMPLITUDE TEST bridge ================================== + + public async Task Preadjustment_AmplitudeTestAsync( + ProcessProgress pp, + CancellationToken token = default) + { + const string operation = nameof(Preadjustment_AmplitudeTestAsync); + + try + { + EnsureExternalInterface(); + + if (pp == null) + throw new ArgumentNullException(nameof(pp)); + + log.InfoFormat("{0}: {1} Start.", Name, operation); + + bool result = + await gciExternalInterface + .Preadjustment_AmplitudeTestAsync( + pp, + token) + .ConfigureAwait(false); + + log.InfoFormat( + "{0}: {1} Finish. Success={2}", + Name, + operation, + result); + + return result; + } + catch (Exception ex) + { + log.Error( + string.Format("{0}: {1} failed.", Name, operation), + ex); + + return false; + } + } + + #endregion + + #region ================================== PreAdjustment TEMPERATURE CALIBRATION bridge ================================== + + public async Task Preadjustment_TemperatureCalibrationAsync( + ProcessProgress pp, + CancellationToken token = default) + { + const string operation = nameof(Preadjustment_TemperatureCalibrationAsync); + + try + { + EnsureExternalInterface(); + + if (pp == null) + throw new ArgumentNullException(nameof(pp)); + + log.InfoFormat("{0}: {1} Start.", Name, operation); + + bool result = + await gciExternalInterface + .Preadjustment_TemperatureCalibrationAsync( + pp, + token) + .ConfigureAwait(false); + + log.InfoFormat( + "{0}: {1} Finish. Success={2}", + Name, + operation, + result); + + return result; + } + catch (Exception ex) + { + log.Error( + string.Format("{0}: {1} failed.", Name, operation), + ex); + + return false; + } + } + + #endregion + + #region ================================== PreAdjustment OFFSET TEST bridge ================================== + + public async Task Preadjustment_OffsetTestAsync( + ProcessProgress pp, + CancellationToken token = default) + { + const string operation = nameof(Preadjustment_OffsetTestAsync); + + try + { + EnsureExternalInterface(); + + if (pp == null) + throw new ArgumentNullException(nameof(pp)); + + log.InfoFormat("{0}: {1} Start.", Name, operation); + + bool result = + await gciExternalInterface + .Preadjustment_OffsetTestAsync( + pp, + token) + .ConfigureAwait(false); + + log.InfoFormat( + "{0}: {1} Finish. Success={2}", + Name, + operation, + result); + + return result; + } + catch (Exception ex) + { + log.Error( + string.Format("{0}: {1} failed.", Name, operation), + ex); + + return false; + } + } + + #endregion + + #region ================================== PreAdjustment COMPLETION bridge ================================== + + public async Task Preadjustment_CompletionAsync( + ProcessProgress pp, + CancellationToken token = default) + { + const string operation = nameof(Preadjustment_CompletionAsync); + + try + { + EnsureExternalInterface(); + + if (pp == null) + throw new ArgumentNullException(nameof(pp)); + + log.InfoFormat("{0}: {1} Start.", Name, operation); + + bool result = + await gciExternalInterface + .Preadjustment_CompletionAsync( + pp, + token) + .ConfigureAwait(false); + + log.InfoFormat( + "{0}: {1} Finish. Success={2}", + Name, + operation, + result); + + return result; + } + catch (Exception ex) + { + log.Error( + string.Format("{0}: {1} failed.", Name, operation), + ex); + + return false; + } + } + + #endregion + #region ======================================= Helpers ======================================= private UDSRPublicModels.DataQuery CreatePasswordQuery(string pcbId) { diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs index 34e236265..9d37054e2 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs @@ -15,6 +15,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Debug private MainForm _mainform; private MainView _mainView; public Grid.MeterGridManager _gridManager; + public event Action SelectedSlotsChanged; private bool isRefreshing; private List comPorts = new List(); @@ -267,8 +268,16 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Debug if (columnName == "Selected") { - bool selected = Convert.ToBoolean(grid.Rows[e.RowIndex].Cells["Selected"].Value); + bool selected = + Convert.ToBoolean( + grid.Rows[e.RowIndex] + .Cells["Selected"] + .Value); + _api.SetSlotSelected(slot, selected); + + SelectedSlotsChanged?.Invoke(); + return; } diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs index f4299069c..451ab33fb 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs @@ -1,4 +1,5 @@ -using System; +using Common; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.Designer.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.Designer.cs index b08992b0c..2ddcfac27 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.Designer.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.Designer.cs @@ -7,9 +7,8 @@ private System.Windows.Forms.GroupBox grpSlots; private System.Windows.Forms.Button preparationActionButton; - private System.Windows.Forms.Button btnUpdateSlot; private System.Windows.Forms.Button detectActionButton; - private System.Windows.Forms.Button btnCleanAllSlots; + private System.Windows.Forms.Button temperatureCalibrationActionButton; private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.TextBox txtLog; @@ -25,47 +24,41 @@ private void InitializeComponent() { this.grpSlots = new System.Windows.Forms.GroupBox(); - this.writeRegisterNameComboBox = new System.Windows.Forms.ComboBox(); - this.readRegisterNameComboBox = new System.Windows.Forms.ComboBox(); - this.label4 = new System.Windows.Forms.Label(); - this.writeRegisterValueTextBox = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.writeRegisterButton = new System.Windows.Forms.Button(); - this.readRegisterButton = new System.Windows.Forms.Button(); - this.btnConnect = new System.Windows.Forms.Button(); - this.btnDisconnect = new System.Windows.Forms.Button(); - this.btnLogin = new System.Windows.Forms.Button(); - this.btnGetPcbId = new System.Windows.Forms.Button(); + this.completionActionButton = new System.Windows.Forms.Button(); + this.offsetTestActionButton = new System.Windows.Forms.Button(); this.preparationActionButton = new System.Windows.Forms.Button(); - this.btnUpdateSlot = new System.Windows.Forms.Button(); this.detectActionButton = new System.Windows.Forms.Button(); - this.btnCleanAllSlots = new System.Windows.Forms.Button(); - this.btnCleanSlot = new System.Windows.Forms.Button(); + this.temperatureCalibrationActionButton = new System.Windows.Forms.Button(); + this.amplitudeTestActionButton = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); this.txtLog = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); this.grpSlots.SuspendLayout(); this.SuspendLayout(); // // grpSlots // - this.grpSlots.Controls.Add(this.writeRegisterNameComboBox); - this.grpSlots.Controls.Add(this.readRegisterNameComboBox); + this.grpSlots.Controls.Add(this.label7); + this.grpSlots.Controls.Add(this.label6); + this.grpSlots.Controls.Add(this.label5); this.grpSlots.Controls.Add(this.label4); - this.grpSlots.Controls.Add(this.writeRegisterValueTextBox); this.grpSlots.Controls.Add(this.label3); this.grpSlots.Controls.Add(this.label2); - this.grpSlots.Controls.Add(this.writeRegisterButton); - this.grpSlots.Controls.Add(this.readRegisterButton); - this.grpSlots.Controls.Add(this.btnConnect); - this.grpSlots.Controls.Add(this.btnDisconnect); - this.grpSlots.Controls.Add(this.btnLogin); - this.grpSlots.Controls.Add(this.btnGetPcbId); + this.grpSlots.Controls.Add(this.label1); + this.grpSlots.Controls.Add(this.button1); + this.grpSlots.Controls.Add(this.completionActionButton); + this.grpSlots.Controls.Add(this.offsetTestActionButton); this.grpSlots.Controls.Add(this.preparationActionButton); - this.grpSlots.Controls.Add(this.btnUpdateSlot); this.grpSlots.Controls.Add(this.detectActionButton); - this.grpSlots.Controls.Add(this.btnCleanAllSlots); - this.grpSlots.Controls.Add(this.btnCleanSlot); + this.grpSlots.Controls.Add(this.temperatureCalibrationActionButton); + this.grpSlots.Controls.Add(this.amplitudeTestActionButton); this.grpSlots.Location = new System.Drawing.Point(10, 10); this.grpSlots.Name = "grpSlots"; this.grpSlots.Size = new System.Drawing.Size(689, 304); @@ -74,146 +67,56 @@ this.grpSlots.Text = "Slots by selection in the table"; this.grpSlots.Enter += new System.EventHandler(this.grpSlots_Enter); // - // writeRegisterNameComboBox + // completionActionButton // - this.writeRegisterNameComboBox.FormattingEnabled = true; - this.writeRegisterNameComboBox.Location = new System.Drawing.Point(300, 264); - this.writeRegisterNameComboBox.Name = "writeRegisterNameComboBox"; - this.writeRegisterNameComboBox.Size = new System.Drawing.Size(213, 21); - this.writeRegisterNameComboBox.TabIndex = 15; + this.completionActionButton.Location = new System.Drawing.Point(390, 249); + this.completionActionButton.Name = "completionActionButton"; + this.completionActionButton.Size = new System.Drawing.Size(150, 28); + this.completionActionButton.TabIndex = 3; + this.completionActionButton.Text = "Completition"; // - // readRegisterNameComboBox + // offsetTestActionButton // - this.readRegisterNameComboBox.FormattingEnabled = true; - this.readRegisterNameComboBox.Location = new System.Drawing.Point(300, 230); - this.readRegisterNameComboBox.Name = "readRegisterNameComboBox"; - this.readRegisterNameComboBox.Size = new System.Drawing.Size(213, 21); - this.readRegisterNameComboBox.TabIndex = 14; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(224, 233); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(78, 13); - this.label4.TabIndex = 13; - this.label4.Text = "Register name:"; - // - // writeRegisterValueTextBox - // - this.writeRegisterValueTextBox.Location = new System.Drawing.Point(555, 264); - this.writeRegisterValueTextBox.Name = "writeRegisterValueTextBox"; - this.writeRegisterValueTextBox.Size = new System.Drawing.Size(117, 20); - this.writeRegisterValueTextBox.TabIndex = 12; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(517, 267); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(36, 13); - this.label3.TabIndex = 10; - this.label3.Text = "value:"; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(224, 267); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(78, 13); - this.label2.TabIndex = 9; - this.label2.Text = "Register name:"; - // - // writeRegisterButton - // - this.writeRegisterButton.Location = new System.Drawing.Point(15, 259); - this.writeRegisterButton.Name = "writeRegisterButton"; - this.writeRegisterButton.Size = new System.Drawing.Size(203, 28); - this.writeRegisterButton.TabIndex = 7; - this.writeRegisterButton.Text = "WriteRegister(slot, registerName, value)"; - this.writeRegisterButton.Click += new System.EventHandler(this.writeRegisterButton_Click); - // - // readRegisterButton - // - this.readRegisterButton.Location = new System.Drawing.Point(15, 225); - this.readRegisterButton.Name = "readRegisterButton"; - this.readRegisterButton.Size = new System.Drawing.Size(203, 28); - this.readRegisterButton.TabIndex = 6; - this.readRegisterButton.Text = "ReadRegister(slot, registerName)"; - // - // btnConnect - // - this.btnConnect.Location = new System.Drawing.Point(15, 158); - this.btnConnect.Name = "btnConnect"; - this.btnConnect.Size = new System.Drawing.Size(150, 28); - this.btnConnect.TabIndex = 3; - this.btnConnect.Text = "Connect(slot)"; - // - // btnDisconnect - // - this.btnDisconnect.Location = new System.Drawing.Point(15, 191); - this.btnDisconnect.Name = "btnDisconnect"; - this.btnDisconnect.Size = new System.Drawing.Size(150, 28); - this.btnDisconnect.TabIndex = 4; - this.btnDisconnect.Text = "Disconnect(slot)"; - // - // btnLogin - // - this.btnLogin.Location = new System.Drawing.Point(171, 158); - this.btnLogin.Name = "btnLogin"; - this.btnLogin.Size = new System.Drawing.Size(150, 28); - this.btnLogin.TabIndex = 17; - this.btnLogin.Text = "Login(slot)"; - // - // btnGetPcbId - // - this.btnGetPcbId.Location = new System.Drawing.Point(15, 125); - this.btnGetPcbId.Name = "btnGetPcbId"; - this.btnGetPcbId.Size = new System.Drawing.Size(150, 28); - this.btnGetPcbId.TabIndex = 5; - this.btnGetPcbId.Text = "GetPcb(slot)"; + this.offsetTestActionButton.Location = new System.Drawing.Point(334, 215); + this.offsetTestActionButton.Name = "offsetTestActionButton"; + this.offsetTestActionButton.Size = new System.Drawing.Size(150, 28); + this.offsetTestActionButton.TabIndex = 5; + this.offsetTestActionButton.Text = "Offset test"; // // preparationActionButton // - this.preparationActionButton.Location = new System.Drawing.Point(15, 25); + this.preparationActionButton.Location = new System.Drawing.Point(203, 113); this.preparationActionButton.Name = "preparationActionButton"; this.preparationActionButton.Size = new System.Drawing.Size(150, 28); this.preparationActionButton.TabIndex = 0; this.preparationActionButton.Text = "Preparation"; this.preparationActionButton.Click += new System.EventHandler(this.preparationActionButton_Click); // - // btnUpdateSlot - // - this.btnUpdateSlot.Location = new System.Drawing.Point(171, 25); - this.btnUpdateSlot.Name = "btnUpdateSlot"; - this.btnUpdateSlot.Size = new System.Drawing.Size(150, 28); - this.btnUpdateSlot.TabIndex = 16; - this.btnUpdateSlot.Text = "UpdateSlot(slot)"; - // // detectActionButton // - this.detectActionButton.Location = new System.Drawing.Point(15, 58); + this.detectActionButton.Location = new System.Drawing.Point(171, 79); this.detectActionButton.Name = "detectActionButton"; this.detectActionButton.Size = new System.Drawing.Size(150, 28); this.detectActionButton.TabIndex = 1; this.detectActionButton.Text = "Detect"; this.detectActionButton.Click += new System.EventHandler(this.detectActionButton_Click); // - // btnCleanAllSlots + // temperatureCalibrationActionButton // - this.btnCleanAllSlots.Location = new System.Drawing.Point(171, 92); - this.btnCleanAllSlots.Name = "btnCleanAllSlots"; - this.btnCleanAllSlots.Size = new System.Drawing.Size(150, 28); - this.btnCleanAllSlots.TabIndex = 2; - this.btnCleanAllSlots.Text = "CleanAllSlots()"; + this.temperatureCalibrationActionButton.Location = new System.Drawing.Point(285, 181); + this.temperatureCalibrationActionButton.Name = "temperatureCalibrationActionButton"; + this.temperatureCalibrationActionButton.Size = new System.Drawing.Size(150, 28); + this.temperatureCalibrationActionButton.TabIndex = 2; + this.temperatureCalibrationActionButton.Text = "Temperature calibration"; + this.temperatureCalibrationActionButton.Click += new System.EventHandler(this.amplitudeTestActionButton_Click); // - // btnCleanSlot + // amplitudeTestActionButton // - this.btnCleanSlot.Location = new System.Drawing.Point(15, 92); - this.btnCleanSlot.Name = "btnCleanSlot"; - this.btnCleanSlot.Size = new System.Drawing.Size(150, 28); - this.btnCleanSlot.TabIndex = 18; - this.btnCleanSlot.Text = "CleanSlot(slot)"; + this.amplitudeTestActionButton.Location = new System.Drawing.Point(246, 147); + this.amplitudeTestActionButton.Name = "amplitudeTestActionButton"; + this.amplitudeTestActionButton.Size = new System.Drawing.Size(150, 28); + this.amplitudeTestActionButton.TabIndex = 18; + this.amplitudeTestActionButton.Text = "Amplitude test"; // // btnCancel // @@ -239,6 +142,84 @@ this.txtLog.TabIndex = 5; this.txtLog.WordWrap = false; // + // button1 + // + this.button1.Location = new System.Drawing.Point(17, 28); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(150, 28); + this.button1.TabIndex = 108; + this.button1.Text = "Preadjustment init"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(176, 121); + this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(22, 13); + this.label1.TabIndex = 109; + this.label1.Text = "--->"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(219, 155); + this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(22, 13); + this.label2.TabIndex = 110; + this.label2.Text = "--->"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(258, 189); + this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(22, 13); + this.label3.TabIndex = 111; + this.label3.Text = "--->"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(307, 223); + this.label4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(22, 13); + this.label4.TabIndex = 112; + this.label4.Text = "--->"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(363, 257); + this.label5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(22, 13); + this.label5.TabIndex = 113; + this.label5.Text = "--->"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(14, 87); + this.label6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(117, 13); + this.label6.TabIndex = 114; + this.label6.Text = "Preadjustment process:"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(144, 87); + this.label7.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(22, 13); + this.label7.TabIndex = 115; + this.label7.Text = "--->"; + // // PreadjustmentActionsView // this.BackColor = System.Drawing.SystemColors.Control; @@ -254,18 +235,16 @@ } - private System.Windows.Forms.Button btnConnect; - private System.Windows.Forms.Button btnDisconnect; - private System.Windows.Forms.Button btnGetPcbId; - private System.Windows.Forms.Button readRegisterButton; - private System.Windows.Forms.TextBox writeRegisterValueTextBox; + private System.Windows.Forms.Button completionActionButton; + private System.Windows.Forms.Button offsetTestActionButton; + private System.Windows.Forms.Button amplitudeTestActionButton; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label2; - private System.Windows.Forms.Button writeRegisterButton; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.ComboBox writeRegisterNameComboBox; - private System.Windows.Forms.ComboBox readRegisterNameComboBox; - private System.Windows.Forms.Button btnLogin; - private System.Windows.Forms.Button btnCleanSlot; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; } } \ No newline at end of file diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.cs index fbd1b728a..bc3505b57 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/PreadjustmentActionsView.cs @@ -120,19 +120,15 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge Cursor = busy ? Cursors.WaitCursor : Cursors.Default; preparationActionButton.Enabled = !busy; - btnUpdateSlot.Enabled = !busy; detectActionButton.Enabled = !busy; - btnCleanAllSlots.Enabled = !busy; - btnGetPcbId.Enabled = !busy; - btnConnect.Enabled = !busy; - btnDisconnect.Enabled = !busy; - readRegisterButton.Enabled = !busy; - writeRegisterButton.Enabled = !busy; - readRegisterNameComboBox.Enabled = !busy; - writeRegisterNameComboBox.Enabled = !busy; - writeRegisterValueTextBox.Enabled = !busy; - btnLogin.Enabled = !busy; - btnCleanSlot.Enabled = !busy; + temperatureCalibrationActionButton.Enabled = !busy; + offsetTestActionButton.Enabled = !busy; + completionActionButton.Enabled = !busy; + amplitudeTestActionButton.Enabled = !busy; + amplitudeTestActionButton.Enabled = !busy; + temperatureCalibrationActionButton.Enabled = !busy; + offsetTestActionButton.Enabled = !busy; + completionActionButton.Enabled = !busy; btnCancel.Enabled = busy; } @@ -154,13 +150,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge private void LoadRegisterComboBoxes() { - var registers = _bridge.GetAllRegisterNames(); - readRegisterNameComboBox.Items.Clear(); - writeRegisterNameComboBox.Items.Clear(); - - readRegisterNameComboBox.Items.AddRange(registers.ToArray()); - writeRegisterNameComboBox.Items.AddRange(registers.ToArray()); } private void grpSlots_Enter(object sender, EventArgs e) @@ -281,6 +271,70 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge return settings; } + private void amplitudeTestActionButton_Click(object sender, EventArgs e) + { + ExecuteAsync(async token => + { + var pp = CreatePreparationProgress(); + + bool success = await _bridge.Preadjustment_AmplitudeTestAsync(pp, token); + + Log(success + ? "Amplitude Test completed." + : "Amplitude Test failed."); + + RefreshGrid(); + }); + } + + private void temperatureCalibrationActionButton_Click(object sender, EventArgs e) + { + ExecuteAsync(async token => + { + var pp = CreatePreparationProgress(); + + bool success = await _bridge.Preadjustment_TemperatureCalibrationAsync(pp, token); + + Log(success + ? "Temperature Calibration completed." + : "Temperature Calibration failed."); + + RefreshGrid(); + }); + } + + private void offsetTestActionButton_Click(object sender, EventArgs e) + { + ExecuteAsync(async token => + { + var pp = CreatePreparationProgress(); + + bool success = await _bridge.Preadjustment_OffsetTestAsync(pp, token); + + Log(success + ? "Offset Test completed." + : "Offset Test failed."); + + RefreshGrid(); + }); + } + + private void completionActionButton_Click(object sender, EventArgs e) + { + ExecuteAsync(async token => + { + var pp = CreatePreparationProgress(); + + bool success = await _bridge.Preadjustment_CompletionAsync(pp, token); + + Log(success + ? "Completion completed." + : "Completion failed."); + + RefreshGrid(); + }); + } + private void writeRegisterButton_Click(object sender, EventArgs e) { /*ExecuteAsync(async token => diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.Designer.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.Designer.cs index 32a7ee738..ae6c642c4 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.Designer.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.Designer.cs @@ -42,6 +42,7 @@ this.btnGetSlot = new System.Windows.Forms.Button(); this.btnCleanAllSlots = new System.Windows.Forms.Button(); this.btnCleanSlot = new System.Windows.Forms.Button(); + this.writeRegisterValueTypeLabel = new System.Windows.Forms.Label(); this.btnCancel = new System.Windows.Forms.Button(); this.txtLog = new System.Windows.Forms.TextBox(); this.grpSlots.SuspendLayout(); @@ -49,6 +50,9 @@ // // grpSlots // + this.grpSlots.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.grpSlots.Controls.Add(this.writeRegisterNameComboBox); this.grpSlots.Controls.Add(this.readRegisterNameComboBox); this.grpSlots.Controls.Add(this.label4); @@ -66,9 +70,10 @@ this.grpSlots.Controls.Add(this.btnGetSlot); this.grpSlots.Controls.Add(this.btnCleanAllSlots); this.grpSlots.Controls.Add(this.btnCleanSlot); + this.grpSlots.Controls.Add(this.writeRegisterValueTypeLabel); this.grpSlots.Location = new System.Drawing.Point(10, 10); this.grpSlots.Name = "grpSlots"; - this.grpSlots.Size = new System.Drawing.Size(689, 304); + this.grpSlots.Size = new System.Drawing.Size(726, 304); this.grpSlots.TabIndex = 2; this.grpSlots.TabStop = false; this.grpSlots.Text = "Slots by selection in the table"; @@ -103,7 +108,7 @@ // this.writeRegisterValueTextBox.Location = new System.Drawing.Point(555, 264); this.writeRegisterValueTextBox.Name = "writeRegisterValueTextBox"; - this.writeRegisterValueTextBox.Size = new System.Drawing.Size(117, 20); + this.writeRegisterValueTextBox.Size = new System.Drawing.Size(85, 20); this.writeRegisterValueTextBox.TabIndex = 12; // // label3 @@ -223,6 +228,15 @@ this.btnCleanSlot.Text = "CleanSlot(slot)"; this.btnCleanSlot.Click += new System.EventHandler(this.btnCleanSlot_Click); // + // writeRegisterValueTypeLabel + // + this.writeRegisterValueTypeLabel.AutoSize = true; + this.writeRegisterValueTypeLabel.Location = new System.Drawing.Point(646, 267); + this.writeRegisterValueTypeLabel.Name = "writeRegisterValueTypeLabel"; + this.writeRegisterValueTypeLabel.Size = new System.Drawing.Size(36, 13); + this.writeRegisterValueTypeLabel.TabIndex = 19; + this.writeRegisterValueTypeLabel.Text = "type: -"; + // // btnCancel // this.btnCancel.Enabled = false; @@ -243,18 +257,18 @@ this.txtLog.Name = "txtLog"; this.txtLog.ReadOnly = true; this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.txtLog.Size = new System.Drawing.Size(689, 232); + this.txtLog.Size = new System.Drawing.Size(726, 232); this.txtLog.TabIndex = 5; this.txtLog.WordWrap = false; // - // GenesisCordonelInterfaceView + // SlotsComPortsRegistersActionsView // this.BackColor = System.Drawing.SystemColors.Control; this.Controls.Add(this.grpSlots); this.Controls.Add(this.btnCancel); this.Controls.Add(this.txtLog); - this.Name = "GenesisCordonelInterfaceView"; - this.Size = new System.Drawing.Size(719, 603); + this.Name = "SlotsComPortsRegistersActionsView"; + this.Size = new System.Drawing.Size(756, 603); this.grpSlots.ResumeLayout(false); this.grpSlots.PerformLayout(); this.ResumeLayout(false); @@ -275,5 +289,6 @@ private System.Windows.Forms.ComboBox readRegisterNameComboBox; private System.Windows.Forms.Button btnLogin; private System.Windows.Forms.Button btnCleanSlot; + private System.Windows.Forms.Label writeRegisterValueTypeLabel; } } \ No newline at end of file diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.cs index eb9331d09..0050571d7 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/SlotsComPortsRegistersActionsView.cs @@ -17,6 +17,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge private CancellationTokenSource _cts; private readonly Action _addSlotAction; private readonly Action _saveAction; + private readonly Dictionary _registerTypes = + new Dictionary(StringComparer.OrdinalIgnoreCase); public SlotsComPortsRegistersActionsView( MainView mainview, @@ -33,6 +35,13 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge InitializeComponent(); LoadRegisterComboBoxes(); + + _mainView._batchPanel.SelectedSlotsChanged -= LoadRegisterComboBoxes; + _mainView._batchPanel.SelectedSlotsChanged += LoadRegisterComboBoxes; + writeRegisterNameComboBox.SelectedIndexChanged -= writeRegisterNameComboBox_SelectedIndexChanged; + writeRegisterNameComboBox.SelectedIndexChanged += writeRegisterNameComboBox_SelectedIndexChanged; + writeRegisterNameComboBox.TextChanged -= writeRegisterNameComboBox_SelectedIndexChanged; + writeRegisterNameComboBox.TextChanged += writeRegisterNameComboBox_SelectedIndexChanged; } private void AddSlot() @@ -48,14 +57,14 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge private List GetSelectedSlots() { if (_mainView == null || _mainView._batchPanel == null) - throw new Exception("Meter batch grid is not available."); + { + Log("Meter batch grid is not available."); - var slots = _mainView._batchPanel.GetSelectedGridData(); + return new List(); + } - if (slots.Count == 0) - throw new Exception("No selected slots in grid."); - - return slots; + return _mainView._batchPanel.GetSelectedGridData() + ?? new List(); } private void RefreshGrid(int? removedSlot = null) @@ -414,16 +423,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge if (string.IsNullOrWhiteSpace(valueText)) throw new Exception("Write register value is empty."); - object value; - - if (registerName == "GENESISFLOW_LedMode") - { - value = byte.Parse(valueText); - } - else - { - value = valueText; - } + object value = ConvertTextToRegisterValue(registerName, valueText); var tasks = GetSelectedSlots() .Select(async slot => @@ -530,18 +530,162 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge private void LoadRegisterComboBoxes() { - var registers = _bridge.GetAllRegisterNames(); + _registerTypes.Clear(); readRegisterNameComboBox.Items.Clear(); writeRegisterNameComboBox.Items.Clear(); - readRegisterNameComboBox.Items.AddRange(registers.ToArray()); - writeRegisterNameComboBox.Items.AddRange(registers.ToArray()); + var selectedSlots = GetSelectedSlots(); + + if (selectedSlots.Count == 0) + { + Log("No selected slot."); + return; + } + + int slot = selectedSlots + .OrderBy(x => x.Slot) + .First() + .Slot; + + var registers = _mainView._laatzenApi.GetRegistersDicForSlot(slot); + + var uniqueRegisters = registers + .GroupBy(x => x.Key.GetIdent()) + .Select(g => g.First()) + .OrderBy(x => x.Key.GetIdent()) + .ToList(); + + foreach (var item in uniqueRegisters) + { + string registerName = item.Key.GetIdent(); + Type dataType = item.Key.DataType; + + _registerTypes[registerName] = dataType; + + readRegisterNameComboBox.Items.Add(registerName); + writeRegisterNameComboBox.Items.Add(registerName); + } + + Log($"Loaded {uniqueRegisters.Count} unique registers from slot {slot}"); } private void grpSlots_Enter(object sender, EventArgs e) { } + + private void writeRegisterNameComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + string registerName = Convert.ToString(writeRegisterNameComboBox.Text).Trim(); + + if (_registerTypes.TryGetValue(registerName, out var type)) + { + writeRegisterValueTypeLabel.Text = $"type: {type.Name}"; + } + else + { + writeRegisterValueTypeLabel.Text = "type: -"; + } + } + + private object ConvertTextToRegisterValue( + string registerName, + string valueText) + { + if (!_registerTypes.TryGetValue( + registerName, + out var targetType)) + { + throw new Exception( + $"Unknown register type for register '{registerName}'."); + } + + return ConvertTextToType( + valueText, + targetType, + registerName); + } + + private object ConvertTextToType( + string valueText, + Type targetType, + string registerName) + { + if (targetType == typeof(string)) + return valueText; + + if (targetType.IsEnum) + { + return Enum.Parse( + targetType, + valueText, + true); + } + + if (targetType == typeof(byte[])) + { + return ParseByteArray(valueText); + } + + if (targetType.Name == "Enum8") + { + return byte.Parse(valueText); + } + + try + { + return Convert.ChangeType( + valueText, + targetType, + System.Globalization.CultureInfo.InvariantCulture); + } + catch (Exception ex) + { + throw new Exception( + $"Value '{valueText}' cannot be converted to '{targetType.Name}' for register '{registerName}'.", + ex); + } + } + + private byte[] ParseByteArray(string valueText) + { + valueText = valueText.Trim(); + + if (valueText.Contains("-") || + valueText.Contains(" ")) + { + return valueText + .Split( + new[] { '-', ' ', ',', ';' }, + StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.Replace("0x", "")) + .Select(x => Convert.ToByte(x, 16)) + .ToArray(); + } + + valueText = + valueText.Replace("0x", ""); + + if (valueText.Length % 2 != 0) + { + throw new Exception( + "Hex string length must be even."); + } + + byte[] result = + new byte[valueText.Length / 2]; + + for (int i = 0; i < result.Length; i++) + { + string hex = + valueText.Substring(i * 2, 2); + + result[i] = + Convert.ToByte(hex, 16); + } + + return result; + } } } \ No newline at end of file diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index 2eaeb68a6..a98f0bdee 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -4450,6 +4450,10 @@ {d0c8d887-ed52-40ab-a069-90bce0e801e2} CordonelPreadjustmentUi + + {f4aaf7e6-7333-4284-b735-e32deb076c64} + Registers + {6d2777bb-7a88-466d-a49b-3266f9bf0160} ProductionOrderCore