diff --git a/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs b/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs index be3dc49b0..b323f89e6 100644 --- a/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs +++ b/GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs @@ -170,77 +170,6 @@ namespace GenesisCordonelInterface.API #region ================================== INIT ================================== - /*public Task InitOneMeterFromExternAsync( - int slot, - ConfigSource cfg, - PasswordSource pwd, - PortConfig? req, - PortConfig? str, - CancellationToken token = default) - { - return GetWorker(slot).RunAsync(() => InitOneMeterFromExtern(slot, cfg, pwd, req, str), token); - } - - public PublicModels.GciInitSlotResult InitOneMeterFromExtern( - int slot, - ConfigSource cfg, - PasswordSource pwd, - PortConfig? req, - PortConfig? str) - { - const string operation = nameof(InitOneMeterFromExtern); - - try - { - LogInfo(operation, - $"Start. Slot={slot}, GciConfigSource={cfg}, PasswordSource={pwd}, " + - $"RequestPort={(req.HasValue ? req.Value.PortName.ToString() : "")}, " + - $"StreamingPort={(str.HasValue ? str.Value.PortName.ToString() : "")}"); - - var meter = GetMeter(slot); - - bool created = false; - - if (meter == null) - { - meter = new GenesisMeter(); - created = true; - } - - meter.useConfigSource = cfg; - meter.usePasswordSource = pwd; - - //meter.SetupFromExternConfig(slot, req, str, true); - meter.SetupGenesisMeter(slot, req, str, true); - - if (created) - _meterBatch.AddMeter(meter); - - //SetSlotSelected(slot, true); - - LogInfo(operation, - $"Success. Slot={slot}, Created={created}, MeterBatchCount={_meterBatch.ListOfMeters.Count}"); - - return new PublicModels.GciInitSlotResult - { - Success = true, - SlotId = slot, - Message = created ? "Slot created." : "Slot updated." - }; - } - catch (Exception ex) - { - LogError(operation, ex); - - return new PublicModels.GciInitSlotResult - { - Success = false, - SlotId = slot, - Message = ex.Message - }; - } - }*/ - public Task InitSlotAsync( int slot, ConfigSource cfg, @@ -560,15 +489,65 @@ namespace GenesisCordonelInterface.API } } - public Task CleanSlotsAsync( - CancellationToken token = default) + public Task CleanSlotAsync( + int slot, + CancellationToken token = default) { - return Task.Run(() => CleanSlots(), token); + return Task.Run(() => CleanSlot(slot), token); } - public PublicModels.GciCleanSlotsResult CleanSlots() + public PublicModels.GciCleanSlotResult CleanSlot(int slot) { - const string operation = nameof(CleanSlots); + const string operation = nameof(CleanSlot); + + try + { + LogInfo(operation, string.Format("Start. Slot={0}", slot)); + + var meter = GetMeter(slot); + + if (meter != null) + { + meter.DisposeMeter(); + _meterBatch.ListOfMeters.Remove(meter); + } + + ApiWorker worker; + + if (_workers.TryRemove(slot, out worker)) + { + worker.Dispose(); + } + + return new PublicModels.GciCleanSlotResult + { + SlotId = slot, + Success = true, + Message = string.Format("Slot {0} cleaned.", slot) + }; + } + catch (Exception ex) + { + LogError(operation, ex); + + return new PublicModels.GciCleanSlotResult + { + SlotId = slot, + Success = false, + Message = ex.Message + }; + } + } + + public Task CleanAllSlotsAsync( + CancellationToken token = default) + { + return Task.Run(() => CleanAllSlots(), token); + } + + public PublicModels.GciCleanAllSlotsResult CleanAllSlots() + { + const string operation = nameof(CleanAllSlots); try { @@ -591,7 +570,7 @@ namespace GenesisCordonelInterface.API } } - return new PublicModels.GciCleanSlotsResult + return new PublicModels.GciCleanAllSlotsResult { Success = true, Message = "Slots cleaned." @@ -601,7 +580,7 @@ namespace GenesisCordonelInterface.API { LogError(operation, ex); - return new PublicModels.GciCleanSlotsResult + return new PublicModels.GciCleanAllSlotsResult { Success = false, Message = ex.Message @@ -911,8 +890,8 @@ namespace GenesisCordonelInterface.API if (meter.IsLoggedOn) meter.Logout(); - //meter.DisposeMeter(); - meter.SoftDispose(); + meter.DisposeMeter(); + //meter.SoftDispose(); LogInfo(operation, $"Success. Slot={slot}"); diff --git a/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs b/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs index 0c719ac99..ffbfa7635 100644 --- a/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs +++ b/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs @@ -27,7 +27,7 @@ namespace GenesisCordonelInterface.API public PortDetectionResult DetectStreamingPort(int slot) { var result = _innerMeterAPI.DetectStreamingPort(slot); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -36,14 +36,14 @@ namespace GenesisCordonelInterface.API CancellationToken token = default(CancellationToken)) { var result = await _innerMeterAPI.DetectStreamingPortAsync(slot, token); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } public PortDetectionResult DetectRequestPort(int slot) { var result = _innerMeterAPI.DetectRequestPort(slot); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -52,7 +52,7 @@ namespace GenesisCordonelInterface.API CancellationToken token = default(CancellationToken)) { var result = await _innerMeterAPI.DetectRequestPortAsync(slot, token); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -60,23 +60,6 @@ namespace GenesisCordonelInterface.API #region ================================== INIT ================================== - /*public async Task InitSlotAsync(GciInitSlotRequest request, CancellationToken token = default) - { - if (request == null) - throw new ArgumentNullException(nameof(request)); - - var result = await _innerMeterAPI.InitOneMeterFromExternAsync( - request.SlotId, - ModelsMapping.MapConfigSource(request.ConfigSource), - ModelsMapping.MapPasswordSource(request.PasswordSource), - ModelsMapping.MapPort(request.RequestPort), - ModelsMapping.MapPort(request.StreamingPort), - token); - - RaiseMeterBatchStatusChanged(); - - return result; - }*/ public async Task InitSlotAsync( GciInitSlotRequest request, CancellationToken token = default) @@ -92,7 +75,7 @@ namespace GenesisCordonelInterface.API ModelsMapping.MapPort(request.StreamingPort), token); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -112,7 +95,7 @@ namespace GenesisCordonelInterface.API ModelsMapping.MapPort(request.StreamingPort), token); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -137,12 +120,26 @@ namespace GenesisCordonelInterface.API return result; } - public async Task CleanSlotsAsync( + public async Task CleanSlotAsync( + int slot, CancellationToken token = default) { - var result = await _innerMeterAPI.CleanSlotsAsync(token); + if (slot <= 0) + throw new ArgumentException("Invalid slot id.", nameof(slot)); - RaiseMeterBatchStatusChanged(); + var result = await _innerMeterAPI.CleanSlotAsync(slot, token); + + //RaiseMeterBatchStatusChanged(); + + return result; + } + + public async Task CleanAllSlotsAsync( + CancellationToken token = default) + { + var result = await _innerMeterAPI.CleanAllSlotsAsync(token); + + //RaiseMeterBatchStatusChanged(); return result; } @@ -186,7 +183,7 @@ namespace GenesisCordonelInterface.API { GciConnectResult result = await _innerMeterAPI.ConnectOneSlotAsync(slot, token); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -200,7 +197,7 @@ namespace GenesisCordonelInterface.API var result = await _innerMeterAPI.DisconnectAsync(slot, token); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -260,7 +257,7 @@ namespace GenesisCordonelInterface.API refreshSystemState, token); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } @@ -278,21 +275,21 @@ namespace GenesisCordonelInterface.API storeToDevice, refreshSystemState); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } public async Task SetMeterPasswordAsync(int slot, string password) { var result = await _innerMeterAPI.SetMeterPasswordAsync(slot, password); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } public GciSetPasswordResult SetMeterPassword(int slot, string password) { var result = _innerMeterAPI.SetMeterPassword(slot, password); - RaiseMeterBatchStatusChanged(); + //RaiseMeterBatchStatusChanged(); return result; } diff --git a/GenesisCordonelInterface/API/PublicModels.cs b/GenesisCordonelInterface/API/PublicModels.cs index 60f412421..33cc7cb12 100644 --- a/GenesisCordonelInterface/API/PublicModels.cs +++ b/GenesisCordonelInterface/API/PublicModels.cs @@ -309,7 +309,7 @@ namespace GenesisCordonelInterface.API } } - public class GciCleanSlotsResult + public class GciCleanAllSlotsResult { public bool Success { get; set; } public string Message { get; set; } @@ -322,6 +322,21 @@ namespace GenesisCordonelInterface.API Message); } } + public class GciCleanSlotResult + { + public int SlotId { get; set; } + public bool Success { get; set; } + public string Message { get; set; } + + public override string ToString() + { + return string.Format( + "SlotId={0}, Success={1}, Message={2}", + SlotId, + Success, + Message); + } + } public class GciGetPcbIdResult { diff --git a/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs b/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs index a6ddb8b52..e9c6c39be 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs @@ -379,26 +379,53 @@ namespace TBF.Rig.BridgeComponents.GciBridge return result; } + /// + /// Clears one initialized GCI slot and related GCI worker state. + /// + /// Trace: + /// GciBridge.CleanSlotAsync() + /// -> InterfaceOutsideToGCI.CleanSlotAsync() + /// -> InterfaceGCIToLaatzen.CleanSlotAsync() + /// -> selected slot cleanup + /// -> worker cleanup + /// + /// GCI slot id. + /// Cleanup operation result. + public async Task CleanSlotAsync(int slot) + { + EnsureExternalInterface(); + + if (slot <= 0) + throw new ArgumentException("Invalid slot id.", nameof(slot)); + + GciPublicModels.GciCleanSlotResult result = + await gciExternalInterface.CleanSlotAsync(slot); + + log.InfoFormat("{0}: CleanSlotAsync invoked. Slot={1}, Result={2}", Name, slot, result); + + return result; + } + /// /// Clears all initialized GCI slots and related GCI worker state. /// /// Trace: - /// GciBridge.CleanSlotsAsync() - /// -> InterfaceOutsideToGCI.CleanSlotsAsync() - /// -> InterfaceGCIToLaatzen.CleanSlotsAsync() + /// GciBridge.CleanAllSlotsAsync() + /// -> InterfaceOutsideToGCI.CleanAllSlotsAsync() + /// -> InterfaceGCIToLaatzen.CleanAllSlotsAsync() /// -> MeterBatch cleanup /// -> selected slot cleanup /// -> worker cleanup /// /// Cleanup operation result. - public async Task CleanSlotsAsync() + public async Task CleanAllSlotsAsync() { EnsureExternalInterface(); - GciPublicModels.GciCleanSlotsResult result = - await gciExternalInterface.CleanSlotsAsync(); + GciPublicModels.GciCleanAllSlotsResult result = + await gciExternalInterface.CleanAllSlotsAsync(); - log.InfoFormat("{0}: CleanSlotsAsync invoked.", Name); + log.InfoFormat("{0}: CleanAllSlotsAsync invoked.", Name); return result; } diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs index 460ce31ec..9a572f878 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterBatchConfigPanel.cs @@ -370,6 +370,11 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Debug _gridManager.AddEmptySlotRow(); } + public bool RemoveSlotRow(int slotId) + { + return _gridManager.RemoveSlot(slotId); + } + public List GetGridData() { return _gridManager.GetGridData(); diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs index ec7b7c4d7..c0e523df2 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs @@ -365,6 +365,35 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Grid return ""; } + public bool RemoveSlot(int slotId) + { + grid.SuspendLayout(); + + try + { + foreach (DataGridViewRow row in grid.Rows) + { + if (row.IsNewRow) + continue; + + if (row.Cells["Slot"].Value == null) + continue; + + if (Convert.ToInt32(row.Cells["Slot"].Value) == slotId) + { + grid.Rows.Remove(row); + return true; + } + } + + return false; + } + finally + { + grid.ResumeLayout(); + } + } + private string MapRequestPortTypeBack(string fullType) { return NormalizeRequestPortType(fullType); diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/ConfigurationView.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/ConfigurationView.cs index 83cf7177f..3f570df63 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/ConfigurationView.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/ConfigurationView.cs @@ -78,7 +78,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge { await ExecuteApiActionAsync(async () => { - await _gciApi.CleanSlotsAsync(); + await _gciApi.CleanAllSlotsAsync(); _gridManager.ClearSlots(); }); diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.Designer.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.Designer.cs index 7f7de47be..c0cc8e52b 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.Designer.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.Designer.cs @@ -9,7 +9,7 @@ private System.Windows.Forms.Button btnInitSlot; private System.Windows.Forms.Button btnUpdateSlot; private System.Windows.Forms.Button btnGetSlot; - private System.Windows.Forms.Button btnCleanSlots; + private System.Windows.Forms.Button btnCleanAllSlots; private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.TextBox txtLog; @@ -35,14 +35,15 @@ 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.btnInitSlot = new System.Windows.Forms.Button(); this.btnUpdateSlot = new System.Windows.Forms.Button(); this.btnGetSlot = new System.Windows.Forms.Button(); - this.btnCleanSlots = new System.Windows.Forms.Button(); + this.btnCleanAllSlots = new System.Windows.Forms.Button(); + this.btnCleanSlot = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); this.txtLog = new System.Windows.Forms.TextBox(); - this.btnLogin = new System.Windows.Forms.Button(); this.grpSlots.SuspendLayout(); this.SuspendLayout(); // @@ -63,7 +64,8 @@ this.grpSlots.Controls.Add(this.btnInitSlot); this.grpSlots.Controls.Add(this.btnUpdateSlot); this.grpSlots.Controls.Add(this.btnGetSlot); - this.grpSlots.Controls.Add(this.btnCleanSlots); + this.grpSlots.Controls.Add(this.btnCleanAllSlots); + this.grpSlots.Controls.Add(this.btnCleanSlot); this.grpSlots.Location = new System.Drawing.Point(10, 10); this.grpSlots.Name = "grpSlots"; this.grpSlots.Size = new System.Drawing.Size(689, 304); @@ -149,15 +151,6 @@ this.btnConnect.Text = "Connect(slot)"; this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click); // - // 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)"; - this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click); - // // btnDisconnect // this.btnDisconnect.Location = new System.Drawing.Point(15, 191); @@ -167,6 +160,15 @@ this.btnDisconnect.Text = "Disconnect(slot)"; this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click); // + // 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)"; + this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click); + // // btnGetPcbId // this.btnGetPcbId.Location = new System.Drawing.Point(15, 125); @@ -203,14 +205,23 @@ this.btnGetSlot.Text = "GetSlot(slot)"; this.btnGetSlot.Click += new System.EventHandler(this.btnGetSlot_Click); // - // btnCleanSlots + // btnCleanAllSlots // - this.btnCleanSlots.Location = new System.Drawing.Point(15, 91); - this.btnCleanSlots.Name = "btnCleanSlots"; - this.btnCleanSlots.Size = new System.Drawing.Size(150, 28); - this.btnCleanSlots.TabIndex = 2; - this.btnCleanSlots.Text = "CleanSlots()"; - this.btnCleanSlots.Click += new System.EventHandler(this.btnCleanSlots_Click); + 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.btnCleanAllSlots.Click += new System.EventHandler(this.btnCleanAllSlots_Click); + // + // btnCleanSlot + // + 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.btnCleanSlot.Click += new System.EventHandler(this.btnCleanSlot_Click); // // btnCancel // @@ -259,5 +270,6 @@ private System.Windows.Forms.ComboBox writeRegisterNameComboBox; private System.Windows.Forms.ComboBox readRegisterNameComboBox; private System.Windows.Forms.Button btnLogin; + private System.Windows.Forms.Button btnCleanSlot; } } \ No newline at end of file diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.cs index e132d5a26..82d5b35c7 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/GenesisCordonelInterfaceView.cs @@ -57,8 +57,14 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge return slots; } - private void RefreshGrid() + private void RefreshGrid(int? removedSlot = null) { + if (removedSlot.HasValue) + { + _mainView?._gciApi.SetSlotSelected(removedSlot.Value, false); + _mainView?._batchPanel?.RemoveSlotRow(removedSlot.Value); + } + if (_bridge?.gciExternalInterface != null) _bridge.gciExternalInterface.RaiseMeterBatchStatusChanged(); } @@ -152,13 +158,28 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge }); } - private void btnCleanSlots_Click(object sender, EventArgs e) + private void btnCleanSlot_Click(object sender, EventArgs e) { ExecuteAsync(async token => { - var result = await _bridge.CleanSlotsAsync(); + foreach (var slot in GetSelectedSlots()) + { + var result = await _bridge.CleanSlotAsync(slot.Slot); - LogResult("CleanSlotsAsync", result); + LogResult($"CleanSlotAsync slot {slot.Slot}", result); + + RefreshGrid(slot.Slot); + } + }); + } + + private void btnCleanAllSlots_Click(object sender, EventArgs e) + { + ExecuteAsync(async token => + { + var result = await _bridge.CleanAllSlotsAsync(); + + LogResult("CleanAllSlotsAsync", result); RefreshGrid(); }); @@ -224,81 +245,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge }); } - private void btnCancel_Click(object sender, EventArgs e) - { - _cts?.Cancel(); - Log("Cancel requested."); - } - - private async void ExecuteAsync(Func action) - { - try - { - SetBusy(true); - - _cts = new CancellationTokenSource(); - - await action(_cts.Token); - } - catch (OperationCanceledException) - { - Log("Operation canceled."); - } - catch (Exception ex) - { - Log("ERROR: " + ex); - - MessageBox.Show( - ex.Message, - "GciBridge API call failed", - MessageBoxButtons.OK, - MessageBoxIcon.Error); - } - finally - { - _cts?.Dispose(); - _cts = null; - - SetBusy(false); - } - } - - private void SetBusy(bool busy) - { - Cursor = busy ? Cursors.WaitCursor : Cursors.Default; - - btnInitSlot.Enabled = !busy; - btnUpdateSlot.Enabled = !busy; - btnGetSlot.Enabled = !busy; - btnCleanSlots.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; - - btnCancel.Enabled = busy; - } - - private void LogResult(string methodName, object result) - { - Log(methodName + " result:"); - Log(result == null ? "" : result.ToString()); - } - - private void Log(string message) - { - txtLog.AppendText( - DateTime.Now.ToString("HH:mm:ss.fff") + - " " + - message + - Environment.NewLine); - } - private void readRegisterButton_Click(object sender, EventArgs e) { ExecuteAsync(async token => @@ -363,6 +309,84 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge }); } + + + private void btnCancel_Click(object sender, EventArgs e) + { + _cts?.Cancel(); + Log("Cancel requested."); + } + + private async void ExecuteAsync(Func action) + { + try + { + SetBusy(true); + + _cts = new CancellationTokenSource(); + + await action(_cts.Token); + } + catch (OperationCanceledException) + { + Log("Operation canceled."); + } + catch (Exception ex) + { + Log("ERROR: " + ex); + + MessageBox.Show( + ex.Message, + "GciBridge API call failed", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + finally + { + _cts?.Dispose(); + _cts = null; + + SetBusy(false); + } + } + + private void SetBusy(bool busy) + { + Cursor = busy ? Cursors.WaitCursor : Cursors.Default; + + btnInitSlot.Enabled = !busy; + btnUpdateSlot.Enabled = !busy; + btnGetSlot.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; + + btnCancel.Enabled = busy; + } + + private void LogResult(string methodName, object result) + { + Log(methodName + " result:"); + Log(result == null ? "" : result.ToString()); + } + + private void Log(string message) + { + txtLog.AppendText( + DateTime.Now.ToString("HH:mm:ss.fff") + + " " + + message + + Environment.NewLine); + } + private void LoadRegisterComboBoxes() { var registers = _bridge.GetAllRegisterNames();