Develop - GciBridge -> GCI -> PreadjustmentUI functions 3

This commit is contained in:
Marek Frniak 2026-05-22 08:52:40 +02:00
parent bc72130d09
commit 9700ba7900
7 changed files with 754 additions and 359 deletions

View File

@ -9,6 +9,7 @@ using NLog.Fluent;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Linq;
using System.Reflection;
@ -21,6 +22,7 @@ using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts;
using Xylem.Common.Hardware.WaterMeter.WaterMeterRegisters;
using Xylem.Common.Ui.CordonelPreadjustmentUi;
using static GenesisCordonelInterface.API.PublicModels;
@ -93,13 +95,13 @@ namespace GenesisCordonelInterface.API
/// <returns></returns>
public List<MeterBatchDebugStatus> GetMeterBatchDebugStatuses()
{
List<GenesisMeter> meters;
List<ZeroFlowGenesisMeter> meters;
//just snapshot of list under lock
lock (_meterBatchLock)
{
meters = _meterBatch.ListOfMeters
.OfType<GenesisMeter>()
.OfType<ZeroFlowGenesisMeter>()
.ToList();
}
@ -167,7 +169,7 @@ namespace GenesisCordonelInterface.API
lock (_meterBatchLock)
{
return _meterBatch.ListOfMeters
.OfType<GenesisMeter>()
.OfType<ZeroFlowGenesisMeter>()
.FirstOrDefault(m => m.Slot == slot);
}
}
@ -208,7 +210,7 @@ namespace GenesisCordonelInterface.API
{
lock (_meterBatchLock)
{
foreach (var meter in _meterBatch.ListOfMeters.OfType<GenesisMeter>())
foreach (var meter in _meterBatch.ListOfMeters.OfType<ZeroFlowGenesisMeter>())
{
meter.DisposeMeter();
}
@ -370,7 +372,7 @@ namespace GenesisCordonelInterface.API
PortConfig? req,
PortConfig? str)
{
GenesisMeter meter = new GenesisMeter();
ZeroFlowGenesisMeter meter = new ZeroFlowGenesisMeter(0, 3, !(_meterControls is TempMeterStateControl), useForPreadjustmentUI: false);
meter.Slot = slot;
@ -379,7 +381,8 @@ namespace GenesisCordonelInterface.API
meter.requestPortConfig = req;
meter.streamingPortConfig = str;
//meter.SetupGenesisMeter(slot, req, str, true);
meter.onlineOperation = false;
lock (_meterBatchLock)
{
_meterBatch.AddMeter2(meter);
@ -1523,69 +1526,88 @@ namespace GenesisCordonelInterface.API
#region ================================== PreAdjustmentUI DETECT process ==================================
public Task<bool> Preadjustment_DetectAsync(
public Task<PreadjustmentDetectResult> Preadjustment_DetectAsync(
CancellationToken token = default)
{
return Task.Run(() => Preadjustment_DetectCore(
token),
token);
{
return Task.Run(() => Preadjustment_DetectCore(token), token);
}
private bool Preadjustment_DetectCore(
CancellationToken token)
private PreadjustmentDetectResult Preadjustment_DetectCore(
CancellationToken token)
{
MeterBatch globalMeterBatch = new MeterBatch();
MeterBatch thermoMeterBatch = new MeterBatch();
const string operation = nameof(Preadjustment_DetectCore);
if (globalMeterBatch == null)
throw new ArgumentNullException(nameof(globalMeterBatch));
try
{
MeterBatch globalMeterBatch = new MeterBatch();
MeterBatch thermoMeterBatch = new MeterBatch();
if (thermoMeterBatch == null)
throw new ArgumentNullException(nameof(thermoMeterBatch));
if (_settings == null)
throw new ArgumentNullException(nameof(_settings));
if (_settings == null)
throw new ArgumentNullException(nameof(_settings));
if (_meterControls == null)
throw new ArgumentNullException(nameof(_meterControls));
if (_meterControls == null)
throw new ArgumentNullException(nameof(_meterControls));
if (_tempMeterControls == null)
_tempMeterControls = new List<MeterStateControl>();
if (_tempMeterControls == null)
_tempMeterControls = new List<MeterStateControl>();
if (globalMeterBatch.ListOfMeters.Any())
globalMeterBatch.RemoveAllMeters();
// Clear previous batch content
if (globalMeterBatch.ListOfMeters.Any())
globalMeterBatch.RemoveAllMeters();
if (thermoMeterBatch.ListOfMeters.Any())
thermoMeterBatch.RemoveAllMeters();
if (thermoMeterBatch.ListOfMeters.Any())
thermoMeterBatch.RemoveAllMeters();
globalMeterBatch = _meterBatch;
globalMeterBatch = _meterBatch;
if (!_settings.GetTempUseTempFlansh())
_tempMeterControls.Clear();
// If manual temperature input is used,
// ignore temporary meter controls
if (!_settings.GetTempUseTempFlansh())
_tempMeterControls.Clear();
var allMeterControls = new List<MeterStateControl>();
var allMeterControls =
new List<MeterStateControl>();
allMeterControls.AddRange(_meterControls);
allMeterControls.AddRange(_tempMeterControls);
allMeterControls.AddRange(_meterControls);
allMeterControls.AddRange(_tempMeterControls);
CreateZeroFlowMeters(
globalMeterBatch,
thermoMeterBatch,
allMeterControls,
token);
CreateZeroFlowMeters(globalMeterBatch, thermoMeterBatch, allMeterControls, token);
SetEnableOpeningState(allMeterControls);
SetEnableOpeningState(allMeterControls);
if (!_meterControls.Any(a => a.EnableOpening))
{
return new PreadjustmentDetectResult
{
Success = false,
DetectedMeterCount = 0,
DetectedThermometerCount = _tempMeterControls.Count(t => t.IsEnabled),
ErrorMessage = "No enabled meter found."
};
}
if (!_meterControls.Any(a => a.EnableOpening))
return false;
SetUnknownStatus(allMeterControls);
SetUnknownStatus(allMeterControls);
CheckTemperatureMeters(
_settings,
_tempMeterControls,
token);
//CheckNormalMeters( meterControls, token); //open ports
CheckTemperatureMeters(_settings, _tempMeterControls, token);
return true;
return new PreadjustmentDetectResult
{
Success = true,
DetectedMeterCount = _meterControls.Count(m => m.IsEnabled),
DetectedThermometerCount = _tempMeterControls.Count(t => t.IsEnabled)
};
}
catch (Exception ex)
{
return new PreadjustmentDetectResult
{
Success = false,
ErrorMessage = ex.Message
};
}
}
private void CreateZeroFlowMeters(
@ -1702,246 +1724,494 @@ namespace GenesisCordonelInterface.API
#endregion
#region ================================== PreAdjustmentUI PREPARATION process ==================================
/// <summary>
/// Execute standalone preparation process.
///
/// Flow:
///
/// Create ProcessProgress
/// ↓
/// Create PreparationProcess
/// ↓
/// Start process
/// ↓
/// Wait for completion
/// ↓
/// Return result
///
/// Notes:
/// - GUI independent
/// - reusable from GCI workflow
/// - supports SinglePath and MultiPath mode
/// </summary>
public Task<bool> Preadjustment_PreparationAsync(
public Task<PreadjustmentProcessResult> Preadjustment_PreparationAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
IProcess process;
return GetWorker(slot).RunAsync(
() => Preadjustment_Preparation(slot, pp),
token);
}
/// <summary>
/// Executes standalone preparation process.
/// </summary>
public PreadjustmentProcessResult Preadjustment_Preparation(
int slot,
ProcessProgress pp)
{
const string operation = nameof(Preadjustment_Preparation);
try
{
LogInfo(operation, $"Start. Slot={slot}");
var meter = GetMeterThreadSafe(slot);
EnsureConnected(meter);
BaseProcess process =
CreatePreparationProcess(pp);
bool success =
ExecuteProcess(process, pp);
var result =
new PreadjustmentProcessResult
{
Success = success,
Slot = slot,
ProcessName = process.ProcessName,
ErrorMessage = success
? null
: process.FailedMessage
};
LogInfo(operation, result.ToString());
return result;
}
catch (Exception ex)
{
LogError(operation, ex);
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Preparation",
ErrorMessage = ex.Message
};
}
}
/// <summary>
/// Creates preparation process instance based on current configuration.
/// </summary>
/// <param name="pp">Current process progress context</param>
/// <returns>Configured preparation process</returns>
private BaseProcess CreatePreparationProcess(ProcessProgress pp)
{
if (pp.Setting.NumberOfPaths == 1)
{
process =
new SPPreparationProcess(
"Preparation Single",
PreAdjustmentControl.StatusPanelItems.Prepare,
PreAdjustmentControl.PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.PreparationFailed(pp.Setting.Culture),
60);
}
else
{
process =
new PreparationProcess(
"Preparation",
PreAdjustmentControl.StatusPanelItems.Prepare,
PreAdjustmentControl.PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.PreparationFailed(pp.Setting.Culture),
60);
return new SPPreparationProcess(
"Preparation Single",
PreAdjustmentControl.StatusPanelItems.Prepare,
PreAdjustmentControl.PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.PreparationFailed(pp.Setting.Culture),
60);
}
return ExecuteProcessAsync(
process,
pp,
token);
return new PreparationProcess(
"Preparation",
PreAdjustmentControl.StatusPanelItems.Prepare,
PreAdjustmentControl.PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.PreparationFailed(pp.Setting.Culture),
60);
}
#endregion
#region ================================== PreAdjustmentUI AMPLITUDE TEST process ==================================
/// <summary>
/// Execute standalone amplitude test process.
/// </summary>
public Task<bool> Preadjustment_AmplitudeTestAsync(
public Task<PreadjustmentProcessResult> Preadjustment_AmplitudeTestAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
if (pp.Setting.TempOnly)
return Task.FromResult(true);
return GetWorker(slot).RunAsync(
() => Preadjustment_AmplitudeTest(slot, pp),
token);
}
IProcess process;
public PreadjustmentProcessResult Preadjustment_AmplitudeTest(
int slot,
ProcessProgress pp)
{
const string operation = nameof(Preadjustment_AmplitudeTest);
try
{
LogInfo(operation, $"Start. Slot={slot}");
var meter = GetMeterThreadSafe(slot);
EnsureConnected(meter);
if (pp.Setting.TempOnly)
{
return new PreadjustmentProcessResult
{
Success = true,
Slot = slot,
ProcessName = "Amplitude Test"
};
}
BaseProcess process = CreateAmplitudeTestProcess(pp);
bool success = ExecuteProcess(process, pp);
LogInfo(operation, $"Finished. Slot={slot}, Success={success}");
return new PreadjustmentProcessResult
{
Success = success,
Slot = slot,
ProcessName = process.ProcessName,
ErrorMessage = success ? null : process.FailedMessage
};
}
catch (Exception ex)
{
LogError(operation, ex);
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Amplitude Test",
ErrorMessage = ex.Message
};
}
}
/// <summary>
/// Creates amplitude test process instance based on current configuration.
/// </summary>
/// <param name="pp">Current process progress context</param>
/// <returns>Configured amplitude test process</returns>
private BaseProcess CreateAmplitudeTestProcess(ProcessProgress pp)
{
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 new SPAmplitudeTestProcess(
"Amplitude Test Single",
PreAdjustmentControl.StatusPanelItems.Amplitude,
PreAdjustmentControl.PredefinedMessages.WaitUntilAmplitudeTestFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.AmplitudeFailed(pp.Setting.Culture),
4 * 60);
}
return ExecuteProcessAsync(
process,
pp,
token);
return new AmplitudeTestProcess(
"Amplitude Test",
PreAdjustmentControl.StatusPanelItems.Amplitude,
PreAdjustmentControl.PredefinedMessages.WaitUntilAmplitudeTestFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.AmplitudeFailed(pp.Setting.Culture),
4 * 60);
}
#endregion
#region ================================== PreAdjustmentUI TEMPERATURE CALIBRATION process ==================================
public Task<bool> Preadjustment_TemperatureCalibrationAsync(
public Task<PreadjustmentProcessResult> Preadjustment_TemperatureCalibrationAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
IProcess process;
return GetWorker(slot).RunAsync(
() => Preadjustment_TemperatureCalibration(slot, pp),
token);
}
public PreadjustmentProcessResult Preadjustment_TemperatureCalibration(
int slot,
ProcessProgress pp)
{
const string operation =
nameof(Preadjustment_TemperatureCalibration);
try
{
LogInfo(operation, $"Start. Slot={slot}");
var meter =
GetMeterThreadSafe(slot);
EnsureConnected(meter);
BaseProcess process =
CreateTemperatureCalibrationProcess(pp);
bool success =
ExecuteProcess(process, pp);
var result =
new PreadjustmentProcessResult
{
Success = success,
Slot = slot,
ProcessName = process.ProcessName,
ErrorMessage = success
? null
: process.FailedMessage
};
LogInfo(operation, result.ToString());
return result;
}
catch (Exception ex)
{
LogError(operation, ex);
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Temperature Calibration",
ErrorMessage = ex.Message
};
}
}
/// <summary>
/// Creates temperature calibration process instance based on current configuration.
/// </summary>
/// <param name="pp">Current process progress context</param>
/// <returns>Configured temperature calibration process</returns>
private BaseProcess CreateTemperatureCalibrationProcess(ProcessProgress pp)
{
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 new SPTemperatureCalibrationProcess(
"Temperature Calibration Single",
PreAdjustmentControl.StatusPanelItems.TempCal,
PreAdjustmentControl.PredefinedMessages.WaitUntilTemperatureCalibrationFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.TempCalFailed(pp.Setting.Culture),
2 * 60);
}
return ExecuteProcessAsync(
process,
pp,
token);
return new TemperatureCalibrationProcess(
"Temperature Calibration",
PreAdjustmentControl.StatusPanelItems.TempCal,
PreAdjustmentControl.PredefinedMessages.WaitUntilTemperatureCalibrationFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.TempCalFailed(pp.Setting.Culture),
2 * 60);
}
#endregion
#region ================================== PreAdjustmentUI OFFSET TEST process ==================================
public Task<bool> Preadjustment_OffsetTestAsync(
ProcessProgress pp,
CancellationToken token = default)
public Task<PreadjustmentProcessResult> Preadjustment_OffsetTestAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
if (pp.Setting.TempOnly)
return Task.FromResult(true);
return GetWorker(slot).RunAsync(
() => Preadjustment_OffsetTest(slot, pp),
token);
}
IProcess process;
public PreadjustmentProcessResult Preadjustment_OffsetTest(
int slot,
ProcessProgress pp)
{
const string operation =
nameof(Preadjustment_OffsetTest);
try
{
LogInfo(operation, $"Start. Slot={slot}");
var meter =
GetMeterThreadSafe(slot);
EnsureConnected(meter);
if (pp.Setting.TempOnly)
{
return new PreadjustmentProcessResult
{
Success = true,
Slot = slot,
ProcessName = "Offset Test"
};
}
BaseProcess process =
CreateOffsetTestProcess(pp);
bool success =
ExecuteProcess(process, pp);
var result =
new PreadjustmentProcessResult
{
Success = success,
Slot = slot,
ProcessName = process.ProcessName,
ErrorMessage = success
? null
: process.FailedMessage
};
LogInfo(operation, result.ToString());
return result;
}
catch (Exception ex)
{
LogError(operation, ex);
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Offset Test",
ErrorMessage = ex.Message
};
}
}
/// <summary>
/// Creates offset test process instance based on current configuration.
/// </summary>
/// <param name="pp">Current process progress context</param>
/// <returns>Configured offset test process</returns>
private BaseProcess CreateOffsetTestProcess(ProcessProgress pp)
{
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 new SPOffsetTestProcess(
"Offset Test Single",
PreAdjustmentControl.StatusPanelItems.Offset,
PreAdjustmentControl.PredefinedMessages.WaitUntilZeroflowOffsetTestFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.ZeroflowOffsetTestFailed(pp.Setting.Culture),
18 * 60);
}
return ExecuteProcessAsync(
process,
pp,
token);
return new OffsetTestProcess(
"Offset Test",
PreAdjustmentControl.StatusPanelItems.Offset,
PreAdjustmentControl.PredefinedMessages.WaitUntilZeroflowOffsetTestFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.ZeroflowOffsetTestFailed(pp.Setting.Culture),
18 * 60);
}
#endregion
#region ================================== PreAdjustmentUI COMPLETION process ==================================
public Task<bool> Preadjustment_CompletionAsync(
public Task<PreadjustmentProcessResult> Preadjustment_CompletionAsync(
int slot,
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,
return GetWorker(slot).RunAsync(
() => Preadjustment_Completion(slot, pp),
token);
}
#endregion
#region ================================== PreAdjustmentUI process threading ==================================
public async Task<bool> ExecuteProcessAsync(
IProcess process,
ProcessProgress pp,
CancellationToken token = default)
public PreadjustmentProcessResult Preadjustment_Completion(
int slot,
ProcessProgress pp)
{
return await Task.Run(() =>
const string operation =
nameof(Preadjustment_Completion);
try
{
pp.IsBusy = true;
LogInfo(operation, $"Start. Slot={slot}");
process.StartProcess(
pp,
_meterControls,
_tempMeterControls);
var meter =
GetMeterThreadSafe(slot);
while (pp.IsBusy && !token.IsCancellationRequested)
EnsureConnected(meter);
BaseProcess process =
CreateCompletionProcess(pp);
bool success =
ExecuteProcess(process, pp);
var result =
new PreadjustmentProcessResult
{
Success = success,
Slot = slot,
ProcessName = process.ProcessName,
ErrorMessage = success
? null
: process.FailedMessage
};
LogInfo(operation, result.ToString());
return result;
}
catch (Exception ex)
{
LogError(operation, ex);
return new PreadjustmentProcessResult
{
Thread.Sleep(50);
}
Success = false,
Slot = slot,
ProcessName = "Completion",
ErrorMessage = ex.Message
};
}
}
return !_meterControls.Any(
m => m.IsEnabled && m.Failed);
/// <summary>
/// Creates completion process instance based on current configuration.
/// </summary>
/// <param name="pp">Current process progress context</param>
/// <returns>Configured completion process</returns>
private BaseProcess CreateCompletionProcess(ProcessProgress pp)
{
if (pp.Setting.NumberOfPaths == 1)
{
return new SPCompletionProcess(
"Completion Single",
PreAdjustmentControl.StatusPanelItems.Completion,
PreAdjustmentControl.PredefinedMessages.WaitUntilCompletionFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.CompletionFailed(pp.Setting.Culture),
1 * 60);
}
}, token);
return new CompletionProcess(
"Completion",
PreAdjustmentControl.StatusPanelItems.Completion,
PreAdjustmentControl.PredefinedMessages.WaitUntilCompletionFinished(pp.Setting.Culture),
PreAdjustmentControl.PredefinedMessages.CompletionFailed(pp.Setting.Culture),
1 * 60);
}
#endregion
#region ================================== PreAdjustmentUI ExecuteProcess ==================================
private bool ExecuteProcess(
BaseProcess process,
ProcessProgress pp)
{
pp.IsBusy = true;
process.StartProcess(
pp,
_meterControls,
_tempMeterControls);
while (pp.IsBusy && !pp.StopSequence)
{
Thread.Sleep(50);
}
foreach (var meterCtrl in _meterControls)
{
if (meterCtrl.IsEnabled && meterCtrl.Failed)
{
pp.GenerateReturnNote(process.FailedMessage, meterCtrl);
meterCtrl.IsEnabled = false;
}
}
if (pp.StopSequence)
return false;
return _meterControls.Any(m => m.IsEnabled && !m.Failed);
}
#endregion
}
}

View File

@ -456,47 +456,50 @@ namespace GenesisCordonelInterface.API
// Preadjustment
public Task<bool> Preadjustment_DetectAsync(
public Task<PreadjustmentDetectResult> Preadjustment_DetectAsync(
CancellationToken token = default)
{
return _innerMeterAPI.Preadjustment_DetectAsync(token);
}
public Task<bool> Preadjustment_PreparationAsync(
public Task<PreadjustmentProcessResult> Preadjustment_PreparationAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
return _innerMeterAPI.Preadjustment_PreparationAsync(pp, token);
return _innerMeterAPI.Preadjustment_PreparationAsync(slot, pp, token);
}
public Task<bool> Preadjustment_AmplitudeTestAsync(
public Task<PreadjustmentProcessResult> Preadjustment_AmplitudeTestAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
return _innerMeterAPI.Preadjustment_AmplitudeTestAsync(pp, token);
return _innerMeterAPI.Preadjustment_AmplitudeTestAsync(slot, pp, token);
}
public Task<bool> Preadjustment_TemperatureCalibrationAsync(
public Task<PreadjustmentProcessResult> Preadjustment_TemperatureCalibrationAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
return _innerMeterAPI.Preadjustment_TemperatureCalibrationAsync(pp, token);
return _innerMeterAPI.Preadjustment_TemperatureCalibrationAsync(slot, pp, token);
}
public Task<bool> Preadjustment_OffsetTestAsync(
public Task<PreadjustmentProcessResult> Preadjustment_OffsetTestAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
return _innerMeterAPI.Preadjustment_OffsetTestAsync(pp, token);
return _innerMeterAPI.Preadjustment_OffsetTestAsync(slot, pp, token);
}
public Task<bool> Preadjustment_CompletionAsync(
public Task<PreadjustmentProcessResult> Preadjustment_CompletionAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
return _innerMeterAPI.Preadjustment_CompletionAsync(pp, token);
return _innerMeterAPI.Preadjustment_CompletionAsync(slot, pp, token);
}
}
}

View File

@ -447,6 +447,42 @@ namespace GenesisCordonelInterface.API
Message);
}
}
public class PreadjustmentProcessResult
{
public bool Success { get; set; }
public int Slot { get; set; }
public string ProcessName { get; set; }
public string ErrorMessage { get; set; }
/// <inheritdoc />
public override string ToString()
{
return
$"Success={Success}, " +
$"Slot={Slot}, " +
$"Process={ProcessName}, " +
$"Error={ErrorMessage ?? "None"}";
}
}
public class PreadjustmentDetectResult
{
public bool Success { get; set; }
public int DetectedMeterCount { get; set; }
public int DetectedThermometerCount { get; set; }
public string ErrorMessage { get; set; }
/// <inheritdoc />
public override string ToString()
{
return
$"Success={Success}, " +
$"Meters={DetectedMeterCount}, " +
$"Thermometers={DetectedThermometerCount}, " +
$"Error={ErrorMessage ?? "None"}";
}
}
#endregion
}
}

View File

@ -18,6 +18,7 @@ using TBF.Rig.Input.DataStorage.UniDataStorageReader;
using TBF.Rig.Input.DataStorage.UniDataStorageReader.Searching.Database;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Ui.CordonelPreadjustmentUi;
using static GenesisCordonelInterface.API.PublicModels;
using static TBF.Rig.BridgeComponents.GciBridge.Interfaces.PublicModels;
using GciGUIType = GenesisCordonelInterface.UI.MainView;
using GciPublicModels = GenesisCordonelInterface.API.PublicModels;
@ -1425,7 +1426,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
#region ================================== Preadjustment DETECT bridge ==================================
public async Task<bool> Preadjustment_DetectAsync(
public async Task<PreadjustmentDetectResult> Preadjustment_DetectAsync(
CancellationToken token = default)
{
const string operation = nameof(Preadjustment_DetectAsync);
@ -1436,13 +1437,13 @@ namespace TBF.Rig.BridgeComponents.GciBridge
log.InfoFormat("{0}: {1} Start.", Name, operation);
bool result =
await gciExternalInterface.Preadjustment_DetectAsync(
token)
PreadjustmentDetectResult result =
await gciExternalInterface
.Preadjustment_DetectAsync(token)
.ConfigureAwait(false);
log.InfoFormat(
"{0}: {1} Finish. Success={2}",
"{0}: {1} Finish. {2}",
Name,
operation,
result);
@ -1455,15 +1456,21 @@ namespace TBF.Rig.BridgeComponents.GciBridge
string.Format("{0}: {1} failed.", Name, operation),
ex);
return false;
return new PreadjustmentDetectResult
{
Success = false,
ErrorMessage = ex.Message
};
}
}
#endregion
#region ================================== PreAdjustment PREPARATION bridge ==================================
public async Task<bool> Preadjustment_PreparationAsync(
public async Task<PreadjustmentProcessResult> Preadjustment_PreparationAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
@ -1476,17 +1483,22 @@ namespace TBF.Rig.BridgeComponents.GciBridge
if (pp == null)
throw new ArgumentNullException(nameof(pp));
log.InfoFormat("{0}: {1} Start.", Name, operation);
log.InfoFormat(
"{0}: {1} Start. Slot={2}",
Name,
operation,
slot);
bool result =
PreadjustmentProcessResult result =
await gciExternalInterface
.Preadjustment_PreparationAsync(
slot,
pp,
token)
.ConfigureAwait(false);
log.InfoFormat(
"{0}: {1} Finish. Success={2}",
"{0}: {1} Finish. {2}",
Name,
operation,
result);
@ -1499,15 +1511,23 @@ namespace TBF.Rig.BridgeComponents.GciBridge
string.Format("{0}: {1} failed.", Name, operation),
ex);
return false;
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Preparation",
ErrorMessage = ex.Message
};
}
}
#endregion
#region ================================== PreAdjustment AMPLITUDE TEST bridge ==================================
public async Task<bool> Preadjustment_AmplitudeTestAsync(
public async Task<PreadjustmentProcessResult> Preadjustment_AmplitudeTestAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
@ -1520,17 +1540,22 @@ namespace TBF.Rig.BridgeComponents.GciBridge
if (pp == null)
throw new ArgumentNullException(nameof(pp));
log.InfoFormat("{0}: {1} Start.", Name, operation);
log.InfoFormat(
"{0}: {1} Start. Slot={2}",
Name,
operation,
slot);
bool result =
PreadjustmentProcessResult result =
await gciExternalInterface
.Preadjustment_AmplitudeTestAsync(
slot,
pp,
token)
.ConfigureAwait(false);
log.InfoFormat(
"{0}: {1} Finish. Success={2}",
"{0}: {1} Finish. {2}",
Name,
operation,
result);
@ -1543,7 +1568,13 @@ namespace TBF.Rig.BridgeComponents.GciBridge
string.Format("{0}: {1} failed.", Name, operation),
ex);
return false;
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Amplitude Test",
ErrorMessage = ex.Message
};
}
}
@ -1551,7 +1582,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
#region ================================== PreAdjustment TEMPERATURE CALIBRATION bridge ==================================
public async Task<bool> Preadjustment_TemperatureCalibrationAsync(
public async Task<PreadjustmentProcessResult> Preadjustment_TemperatureCalibrationAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
@ -1564,17 +1596,22 @@ namespace TBF.Rig.BridgeComponents.GciBridge
if (pp == null)
throw new ArgumentNullException(nameof(pp));
log.InfoFormat("{0}: {1} Start.", Name, operation);
log.InfoFormat(
"{0}: {1} Start. Slot={2}",
Name,
operation,
slot);
bool result =
PreadjustmentProcessResult result =
await gciExternalInterface
.Preadjustment_TemperatureCalibrationAsync(
slot,
pp,
token)
.ConfigureAwait(false);
log.InfoFormat(
"{0}: {1} Finish. Success={2}",
"{0}: {1} Finish. {2}",
Name,
operation,
result);
@ -1587,15 +1624,23 @@ namespace TBF.Rig.BridgeComponents.GciBridge
string.Format("{0}: {1} failed.", Name, operation),
ex);
return false;
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Temperature Calibration",
ErrorMessage = ex.Message
};
}
}
#endregion
#region ================================== PreAdjustment OFFSET TEST bridge ==================================
public async Task<bool> Preadjustment_OffsetTestAsync(
public async Task<PreadjustmentProcessResult> Preadjustment_OffsetTestAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
@ -1608,17 +1653,22 @@ namespace TBF.Rig.BridgeComponents.GciBridge
if (pp == null)
throw new ArgumentNullException(nameof(pp));
log.InfoFormat("{0}: {1} Start.", Name, operation);
log.InfoFormat(
"{0}: {1} Start. Slot={2}",
Name,
operation,
slot);
bool result =
PreadjustmentProcessResult result =
await gciExternalInterface
.Preadjustment_OffsetTestAsync(
slot,
pp,
token)
.ConfigureAwait(false);
log.InfoFormat(
"{0}: {1} Finish. Success={2}",
"{0}: {1} Finish. {2}",
Name,
operation,
result);
@ -1631,15 +1681,23 @@ namespace TBF.Rig.BridgeComponents.GciBridge
string.Format("{0}: {1} failed.", Name, operation),
ex);
return false;
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Offset Test",
ErrorMessage = ex.Message
};
}
}
#endregion
#region ================================== PreAdjustment COMPLETION bridge ==================================
public async Task<bool> Preadjustment_CompletionAsync(
public async Task<PreadjustmentProcessResult> Preadjustment_CompletionAsync(
int slot,
ProcessProgress pp,
CancellationToken token = default)
{
@ -1652,17 +1710,22 @@ namespace TBF.Rig.BridgeComponents.GciBridge
if (pp == null)
throw new ArgumentNullException(nameof(pp));
log.InfoFormat("{0}: {1} Start.", Name, operation);
log.InfoFormat(
"{0}: {1} Start. Slot={2}",
Name,
operation,
slot);
bool result =
PreadjustmentProcessResult result =
await gciExternalInterface
.Preadjustment_CompletionAsync(
slot,
pp,
token)
.ConfigureAwait(false);
log.InfoFormat(
"{0}: {1} Finish. Success={2}",
"{0}: {1} Finish. {2}",
Name,
operation,
result);
@ -1675,7 +1738,13 @@ namespace TBF.Rig.BridgeComponents.GciBridge
string.Format("{0}: {1} failed.", Name, operation),
ex);
return false;
return new PreadjustmentProcessResult
{
Success = false,
Slot = slot,
ProcessName = "Completion",
ErrorMessage = ex.Message
};
}
}

View File

@ -15,7 +15,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Debug
private MainForm _mainform;
private MainView _mainView;
public Grid.MeterGridManager _gridManager;
public event Action SelectedSlotsChanged;
public event Action GetMeterRegistersClicked;
private bool isRefreshing;
private List<string> comPorts = new List<string>();
@ -37,6 +37,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Debug
_mainView._gciApi.MeterBatchStatusChanged += Api_MeterBatchStatusChanged; //global event of table
grid.CellContentClick += grid_CellContentClick;
UpdateGrid(_api.GetMeterBatchDebugStatuses());
}
@ -276,7 +279,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Debug
_api.SetSlotSelected(slot, selected);
SelectedSlotsChanged?.Invoke();
//SelectedSlotsChanged?.Invoke();
return;
}
@ -311,13 +314,14 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.Debug
if (columnName == "DetectRequest")
{
await DetectRequestPortAsync(slot);
//await DetectRequestPortAsync(slot);
GetMeterRegistersClicked?.Invoke();
return;
}
if (columnName == "DetectStreaming")
{
await DetectStreamingPortAsync(slot);
//await DetectStreamingPortAsync(slot);
return;
}
}

View File

@ -10,6 +10,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Ui.CordonelPreadjustmentUi;
using static GenesisCordonelInterface.API.PublicModels;
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.PreadjustmentMeter;
using GciPublicModels = GenesisCordonelInterface.API.PublicModels;
@ -164,31 +165,68 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
{
ExecuteAsync(async token =>
{
var selectedSlots =
_mainView._batchPanel.GetSelectedGridData();
if (!selectedSlots.Any())
{
Log("No selected slots.");
return;
}
var pp = CreatePreparationProgress();
bool success = await _bridge.Preadjustment_PreparationAsync(
pp,
await ExecutePreadjustmentForSelectedSlotsAsync(
_bridge.Preadjustment_PreparationAsync,
"Preparation",
token);
});
}
Log(
success
? "Preparation completed."
: "Preparation failed.");
private void amplitudeTestActionButton_Click(
object sender,
EventArgs e)
{
ExecuteAsync(async token =>
{
await ExecutePreadjustmentForSelectedSlotsAsync(
_bridge.Preadjustment_AmplitudeTestAsync,
"Amplitude Test",
token);
});
}
private void temperatureCalibrationActionButton_Click(
object sender,
EventArgs e)
{
ExecuteAsync(async token =>
{
await ExecutePreadjustmentForSelectedSlotsAsync(
_bridge.Preadjustment_TemperatureCalibrationAsync,
"Temperature Calibration",
token);
});
}
private void offsetTestActionButton_Click(
object sender,
EventArgs e)
{
ExecuteAsync(async token =>
{
await ExecutePreadjustmentForSelectedSlotsAsync(
_bridge.Preadjustment_OffsetTestAsync,
"Offset Test",
token);
});
}
private void completionActionButton_Click(
object sender,
EventArgs e)
{
ExecuteAsync(async token =>
{
await ExecutePreadjustmentForSelectedSlotsAsync(
_bridge.Preadjustment_CompletionAsync,
"Completion",
token);
});
}
private void detectActionButton_Click(
object sender,
EventArgs e)
object sender,
EventArgs e)
{
ExecuteAsync(async token =>
{
@ -201,23 +239,24 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
return;
}
_mainView._laatzenApi._settings = CreatePreAdjustmentSettings(selectedSlots);
_mainView._laatzenApi._settings =
CreatePreAdjustmentSettings(selectedSlots);
_mainView._laatzenApi._meterControls = CreateMeterControls(selectedSlots);
_mainView._laatzenApi._meterControls =
CreateMeterControls(selectedSlots);
bool success = await _bridge.Preadjustment_DetectAsync(
token);
PreadjustmentDetectResult result =
await _bridge.Preadjustment_DetectAsync(token);
Log(
success
? "Detect completed."
: "Detect failed.");
result.Success
? "Detect completed. " + result
: "Detect failed. " + result);
RefreshGrid();
});
}
private ProcessProgress CreatePreparationProgress()
{
return new ProcessProgress
@ -271,69 +310,7 @@ 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)
{
@ -388,5 +365,41 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
RefreshGrid();
});*/
}
private async Task ExecutePreadjustmentForSelectedSlotsAsync(
Func<int, ProcessProgress, CancellationToken, Task<PreadjustmentProcessResult>> action,
string processName,
CancellationToken token)
{
var selectedSlots =
_mainView._batchPanel.GetSelectedGridData();
if (!selectedSlots.Any())
{
Log(processName + ": no selected slots.");
return;
}
var pp =
CreatePreparationProgress();
foreach (var selectedSlot in selectedSlots)
{
PreadjustmentProcessResult result =
await action(
selectedSlot.Slot,
pp,
token);
Log(result.Success
? processName + " completed. " + result
: processName + " failed. " + result);
if (!result.Success)
break;
}
RefreshGrid();
}
}
}

View File

@ -36,8 +36,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
LoadRegisterComboBoxes();
_mainView._batchPanel.SelectedSlotsChanged -= LoadRegisterComboBoxes;
_mainView._batchPanel.SelectedSlotsChanged += LoadRegisterComboBoxes;
_mainView._batchPanel.GetMeterRegistersClicked -= LoadRegisterComboBoxes;
_mainView._batchPanel.GetMeterRegistersClicked += LoadRegisterComboBoxes;
writeRegisterNameComboBox.SelectedIndexChanged -= writeRegisterNameComboBox_SelectedIndexChanged;
writeRegisterNameComboBox.SelectedIndexChanged += writeRegisterNameComboBox_SelectedIndexChanged;
writeRegisterNameComboBox.TextChanged -= writeRegisterNameComboBox_SelectedIndexChanged;