Merge branch 'feature/task/Cordonel-preadjustmentUI-GenesisMeter-ZeroFlowGenesisMeter' into develop/UnionTown
This commit is contained in:
commit
88903f3dac
17
GenesisCordonelInterface/API/Enums.cs
Normal file
17
GenesisCordonelInterface/API/Enums.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GenesisCordonelInterface.API
|
||||
{
|
||||
public class Enums
|
||||
{
|
||||
public enum DataStorageReaderTypes : sbyte
|
||||
{
|
||||
LoginPasswordsReader,
|
||||
CalibrationParamsReader
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,7 +42,6 @@ namespace GenesisCordonelInterface.API
|
||||
private readonly MeterBatch _meterBatch = new MeterBatch();
|
||||
|
||||
//Preadjustment
|
||||
public PreAdjustmentSettingsContainer _settings = new PreAdjustmentSettingsContainer();
|
||||
public ProcessProgress _progressProcess = new ProcessProgress();
|
||||
public List<MeterStateControl> _meterControls = new List<MeterStateControl>();
|
||||
public List<MeterStateControl> _tempMeterControls = new List<MeterStateControl>();
|
||||
@ -55,6 +54,11 @@ namespace GenesisCordonelInterface.API
|
||||
|
||||
private readonly ConcurrentDictionary<int, bool> _selectedSlots = new ConcurrentDictionary<int, bool>();
|
||||
|
||||
public InterfaceGCIToLaatzen()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== Worker ==================================
|
||||
@ -1592,22 +1596,30 @@ namespace GenesisCordonelInterface.API
|
||||
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return Task.Run(() => Preadjustment_DetectCore(selectedSlots, token), token);
|
||||
return Task.Run(() => Preadjustment_Detect(selectedSlots, token), token);
|
||||
}
|
||||
public PreadjustmentDetectResult PreAdjustment_DetectDirect(
|
||||
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return Preadjustment_Detect(selectedSlots, token);
|
||||
}
|
||||
|
||||
private PreadjustmentDetectResult Preadjustment_DetectCore(
|
||||
private PreadjustmentDetectResult Preadjustment_Detect(
|
||||
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token)
|
||||
CancellationToken token = default)
|
||||
{
|
||||
const string operation = nameof(Preadjustment_DetectCore);
|
||||
const string operation = nameof(Preadjustment_Detect);
|
||||
|
||||
try
|
||||
{
|
||||
LogInfo(operation, "Start.");
|
||||
|
||||
MeterBatch globalMeterBatch = new MeterBatch();
|
||||
MeterBatch thermoMeterBatch = new MeterBatch();
|
||||
|
||||
if (_settings == null)
|
||||
throw new ArgumentNullException(nameof(_settings));
|
||||
if (_progressProcess.Setting == null)
|
||||
throw new ArgumentNullException(nameof(_progressProcess.Setting));
|
||||
|
||||
if (_meterControls == null)
|
||||
throw new ArgumentNullException(nameof(_meterControls));
|
||||
@ -1624,7 +1636,7 @@ namespace GenesisCordonelInterface.API
|
||||
globalMeterBatch = _meterBatch;
|
||||
_meterControls = CreateMeterControls(selectedSlots);
|
||||
|
||||
if (!_settings.GetTempUseTempFlansh())
|
||||
if (!_progressProcess.Setting.GetTempUseTempFlansh())
|
||||
_tempMeterControls.Clear();
|
||||
|
||||
var allMeterControls = new List<MeterStateControl>();
|
||||
@ -1654,7 +1666,7 @@ namespace GenesisCordonelInterface.API
|
||||
SetUnknownStatus(allMeterControls);
|
||||
|
||||
CheckTemperatureMeters(
|
||||
_settings,
|
||||
_progressProcess.Setting,
|
||||
_tempMeterControls,
|
||||
token);
|
||||
|
||||
@ -1684,7 +1696,6 @@ namespace GenesisCordonelInterface.API
|
||||
{
|
||||
var ctl = new MeterStateControl(slot.Slot);
|
||||
|
||||
ctl.SetChecked(true);
|
||||
ctl.IsEnabled = true;
|
||||
|
||||
controls.Add(ctl);
|
||||
@ -1818,11 +1829,16 @@ namespace GenesisCordonelInterface.API
|
||||
token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_PreparationDirect()
|
||||
{
|
||||
return PreAdjustment_Preparation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes standalone preparation process.
|
||||
/// </summary>
|
||||
public PreAdjustmentProcessResult PreAdjustment_Preparation(
|
||||
int slot)
|
||||
int slot = -1)
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_Preparation);
|
||||
|
||||
@ -1830,9 +1846,6 @@ namespace GenesisCordonelInterface.API
|
||||
{
|
||||
LogInfo(operation, $"Start. Slot={slot}");
|
||||
|
||||
var meter = GetMeterThreadSafe(slot);
|
||||
EnsureConnected(meter);
|
||||
|
||||
BaseProcess process = CreatePreparationProcess(_progressProcess);
|
||||
|
||||
bool success =
|
||||
@ -1891,6 +1904,17 @@ namespace GenesisCordonelInterface.API
|
||||
PreAdjustmentControl.PredefinedMessages.PreparationFailed(pp.Setting.Culture),
|
||||
60);
|
||||
}
|
||||
public bool PreAdjustment_PushCalibrationParams(double temperature)
|
||||
{
|
||||
if (_progressProcess != null)
|
||||
{
|
||||
_progressProcess.PushedTestBenchTemp = temperature;
|
||||
_progressProcess.TempretureSelected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -1904,8 +1928,13 @@ namespace GenesisCordonelInterface.API
|
||||
token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTestDirect()
|
||||
{
|
||||
return PreAdjustment_AmplitudeTest();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTest(
|
||||
int slot)
|
||||
int slot = -1)
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_AmplitudeTest);
|
||||
|
||||
@ -1913,9 +1942,6 @@ namespace GenesisCordonelInterface.API
|
||||
{
|
||||
LogInfo(operation, $"Start. Slot={slot}");
|
||||
|
||||
var meter = GetMeterThreadSafe(slot);
|
||||
EnsureConnected(meter);
|
||||
|
||||
if (_progressProcess.Setting.TempOnly)
|
||||
{
|
||||
return new PreAdjustmentProcessResult
|
||||
@ -1992,19 +2018,19 @@ namespace GenesisCordonelInterface.API
|
||||
token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect()
|
||||
{
|
||||
return PreAdjustment_TemperatureCalibration();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibration(
|
||||
int slot)
|
||||
int slot = -1)
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_TemperatureCalibration);
|
||||
|
||||
try
|
||||
{
|
||||
LogInfo(operation, $"Start. Slot={slot}");
|
||||
|
||||
var meter =
|
||||
GetMeterThreadSafe(slot);
|
||||
|
||||
EnsureConnected(meter);
|
||||
LogInfo(operation, $"Start.");
|
||||
|
||||
BaseProcess process = CreateTemperatureCalibrationProcess(_progressProcess);
|
||||
|
||||
@ -2039,6 +2065,18 @@ namespace GenesisCordonelInterface.API
|
||||
}
|
||||
}
|
||||
|
||||
public bool PreAdjustment_PushTemperature(double temperature)
|
||||
{
|
||||
if (_progressProcess != null)
|
||||
{
|
||||
_progressProcess.PushedTestBenchTemp = temperature;
|
||||
_progressProcess.TempretureSelected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates temperature calibration process instance based on current configuration.
|
||||
/// </summary>
|
||||
@ -2077,8 +2115,13 @@ namespace GenesisCordonelInterface.API
|
||||
token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_OffsetTestDirect()
|
||||
{
|
||||
return PreAdjustment_OffsetTest();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_OffsetTest(
|
||||
int slot)
|
||||
int slot = -1)
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_OffsetTest);
|
||||
|
||||
@ -2086,10 +2129,6 @@ namespace GenesisCordonelInterface.API
|
||||
{
|
||||
LogInfo(operation, $"Start. Slot={slot}");
|
||||
|
||||
var meter = GetMeterThreadSafe(slot);
|
||||
|
||||
EnsureConnected(meter);
|
||||
|
||||
if (_progressProcess.Setting.TempOnly)
|
||||
{
|
||||
return new PreAdjustmentProcessResult
|
||||
@ -2171,19 +2210,19 @@ namespace GenesisCordonelInterface.API
|
||||
token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_CompletionDirect()
|
||||
{
|
||||
return PreAdjustment_Completion();
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_Completion(
|
||||
int slot)
|
||||
int slot = -1)
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_Completion);
|
||||
|
||||
try
|
||||
{
|
||||
LogInfo(operation, $"Start. Slot={slot}");
|
||||
|
||||
var meter =
|
||||
GetMeterThreadSafe(slot);
|
||||
|
||||
EnsureConnected(meter);
|
||||
LogInfo(operation, $"Start.");
|
||||
|
||||
BaseProcess process = CreateCompletionProcess(_progressProcess);
|
||||
|
||||
|
||||
@ -1,11 +1,16 @@
|
||||
using CordonelPreadjustmentUi;
|
||||
using CordonelPreadjustmentUi.Processes.Itinerary;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Config;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
|
||||
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
|
||||
using Xylem.Common.Ui.CordonelPreadjustmentUi;
|
||||
using static GenesisCordonelInterface.API.PublicModels;
|
||||
|
||||
@ -35,13 +40,55 @@ namespace GenesisCordonelInterface.API
|
||||
/// Occurs when meter batch status information changes.
|
||||
/// </summary>
|
||||
public event Action<List<MeterBatchDebugStatus>> MeterBatchStatusChanged;
|
||||
private readonly IMeterLoginPasswordReader loginPasswordsReader;
|
||||
private readonly IPreAdjustmentCalibrationParamsReader calibrationParamsReader;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the public GCI facade.
|
||||
/// </summary>
|
||||
public InterfaceOutsideToGCI()
|
||||
{
|
||||
_innerMeterAPI = new InterfaceGCIToLaatzen();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the public GCI facade.
|
||||
/// </summary>
|
||||
public InterfaceOutsideToGCI(
|
||||
InterfaceGCIToLaatzen innerMeterApi,
|
||||
IMeterLoginPasswordReader passwordReader,
|
||||
IPreAdjustmentCalibrationParamsReader calibrationReader)
|
||||
{
|
||||
_innerMeterAPI = innerMeterApi?? throw new ArgumentNullException(nameof(innerMeterApi));
|
||||
loginPasswordsReader = passwordReader ?? throw new ArgumentNullException(nameof(passwordReader));
|
||||
calibrationParamsReader = calibrationReader ?? throw new ArgumentNullException(nameof(calibrationReader));
|
||||
|
||||
//init handlers
|
||||
//_innerMeterAPI._progressProcess.OnRequestedCalibrationParamsFromDb += RequestedCalibrationParamsFromDb;
|
||||
}
|
||||
|
||||
private async void RequestedCalibrationParamsFromDb(
|
||||
object sender,
|
||||
EventArgsProcessProgress e)
|
||||
{
|
||||
try
|
||||
{
|
||||
DataQuery query = new DataQuery();
|
||||
query.QueryParams.Add(((int)e.Value.Setting.MeterSize).ToString());
|
||||
|
||||
Dictionary<string, UInt32> calibrationParams = await ReadPreAdjustmentCalibrationParamsAsync(query).ConfigureAwait(false);
|
||||
|
||||
e.Value.PushedCalibrationParams = calibrationParams;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
e.Value.DebugMessage(
|
||||
$"Calibration params reading failed: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
e.Value.CalibrationParamsReadEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
// Laatzen ToolBox actions
|
||||
@ -50,7 +97,7 @@ namespace GenesisCordonelInterface.API
|
||||
|
||||
public PortDetectionResult DetectStreamingPort(int slot)
|
||||
{
|
||||
var result = _innerMeterAPI.DetectStreamingPort(slot);
|
||||
var result = _innerMeterAPI?.DetectStreamingPort(slot);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
@ -59,14 +106,14 @@ namespace GenesisCordonelInterface.API
|
||||
int slot,
|
||||
CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var result = await _innerMeterAPI.DetectStreamingPortAsync(slot, token);
|
||||
var result = await _innerMeterAPI?.DetectStreamingPortAsync(slot, token);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
|
||||
public PortDetectionResult DetectRequestPort(int slot)
|
||||
{
|
||||
var result = _innerMeterAPI.DetectRequestPort(slot);
|
||||
var result = _innerMeterAPI?.DetectRequestPort(slot);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
@ -75,7 +122,7 @@ namespace GenesisCordonelInterface.API
|
||||
int slot,
|
||||
CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var result = await _innerMeterAPI.DetectRequestPortAsync(slot, token);
|
||||
var result = await _innerMeterAPI?.DetectRequestPortAsync(slot, token);
|
||||
//RaiseMeterBatchStatusChanged();
|
||||
return result;
|
||||
}
|
||||
@ -484,6 +531,7 @@ namespace GenesisCordonelInterface.API
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== DEBUG STATUS ==================================
|
||||
@ -497,7 +545,7 @@ namespace GenesisCordonelInterface.API
|
||||
/// </returns>
|
||||
public List<WorkerDebugStatus> GetWorkerDebugStatuses()
|
||||
{
|
||||
return _innerMeterAPI.GetWorkerDebugStatuses();
|
||||
return _innerMeterAPI?.GetWorkerDebugStatuses();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -509,7 +557,7 @@ namespace GenesisCordonelInterface.API
|
||||
/// </returns>
|
||||
public List<MeterBatchDebugStatus> GetMeterBatchDebugStatuses()
|
||||
{
|
||||
return _innerMeterAPI.GetMeterBatchDebugStatuses();
|
||||
return _innerMeterAPI?.GetMeterBatchDebugStatuses();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -538,7 +586,7 @@ namespace GenesisCordonelInterface.API
|
||||
/// <param name="selected">Selection state.</param>
|
||||
public void SetSlotSelected(int slot, bool selected)
|
||||
{
|
||||
_innerMeterAPI.SetSlotSelected(slot, selected);
|
||||
_innerMeterAPI?.SetSlotSelected(slot, selected);
|
||||
RaiseMeterBatchStatusChanged();
|
||||
}
|
||||
|
||||
@ -551,7 +599,7 @@ namespace GenesisCordonelInterface.API
|
||||
/// </returns>
|
||||
public bool IsSlotSelected(int slot)
|
||||
{
|
||||
return _innerMeterAPI.IsSlotSelected(slot);
|
||||
return (bool)(_innerMeterAPI?.IsSlotSelected(slot));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -562,7 +610,7 @@ namespace GenesisCordonelInterface.API
|
||||
/// </returns>
|
||||
public List<int> GetSelectedSlots()
|
||||
{
|
||||
return _innerMeterAPI.GetSelectedSlots();
|
||||
return _innerMeterAPI?.GetSelectedSlots();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -577,7 +625,7 @@ namespace GenesisCordonelInterface.API
|
||||
/// </returns>
|
||||
public List<string> GetAllRegisterNames()
|
||||
{
|
||||
return _innerMeterAPI.GetAllRegisterNames();
|
||||
return _innerMeterAPI?.GetAllRegisterNames();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -589,7 +637,10 @@ namespace GenesisCordonelInterface.API
|
||||
ProcessProgress pp,
|
||||
List<MeterStateControl> mc)
|
||||
{
|
||||
return _innerMeterAPI.Preadjustment_Initialization(pp, mc);
|
||||
//init handlers
|
||||
pp.OnRequestedCalibrationParamsFromDb += RequestedCalibrationParamsFromDb;
|
||||
|
||||
return _innerMeterAPI?.Preadjustment_Initialization(pp, mc);
|
||||
}
|
||||
|
||||
public Task<PreadjustmentDetectResult> PreAdjustment_DetectAsync(
|
||||
@ -599,6 +650,13 @@ namespace GenesisCordonelInterface.API
|
||||
return _innerMeterAPI.PreAdjustment_DetectAsync(selectedSlots, token);
|
||||
}
|
||||
|
||||
public PreadjustmentDetectResult PreAdjustment_DetectDirect(
|
||||
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_DetectDirect(selectedSlots, token);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_PreparationAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
@ -606,6 +664,11 @@ namespace GenesisCordonelInterface.API
|
||||
return _innerMeterAPI.PreAdjustment_PreparationAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_PreparationDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_PreparationDirect();
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_AmplitudeTestAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
@ -613,6 +676,11 @@ namespace GenesisCordonelInterface.API
|
||||
return _innerMeterAPI.PreAdjustment_AmplitudeTestAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTestDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_AmplitudeTestDirect();
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_TemperatureCalibrationAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
@ -620,6 +688,17 @@ namespace GenesisCordonelInterface.API
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationDirect();
|
||||
}
|
||||
|
||||
public bool PreAdjustment_PushTemperature(
|
||||
double temperature)
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_PushTemperature(temperature);
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_OffsetTestAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
@ -627,6 +706,11 @@ namespace GenesisCordonelInterface.API
|
||||
return _innerMeterAPI.PreAdjustment_OffsetTestAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_OffsetTestDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_OffsetTestDirect();
|
||||
}
|
||||
|
||||
public Task<PreAdjustmentProcessResult> PreAdjustment_CompletionAsync(
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
@ -634,6 +718,68 @@ namespace GenesisCordonelInterface.API
|
||||
return _innerMeterAPI.PreAdjustment_CompletionAsync(slot, token);
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_CompletionDirect()
|
||||
{
|
||||
return _innerMeterAPI.PreAdjustment_CompletionDirect();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== UNI DATA STORAGE READER ==================================
|
||||
|
||||
//LoginPasswords reading
|
||||
|
||||
/// <summary>
|
||||
/// Reads meter login password from configured GCI data storage.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing PCB ID or another configured lookup value.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token used to cancel the asynchronous operation.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Password if found; otherwise null.
|
||||
/// </returns>
|
||||
public Task<string> ReadMeterLoginPasswordAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return loginPasswordsReader.ReadMeterLoginPasswordAsync(
|
||||
query,
|
||||
token);
|
||||
}
|
||||
|
||||
//CalibrationParams reading
|
||||
|
||||
/// <summary>
|
||||
/// Reads pre-adjustment calibration parameters
|
||||
/// from configured GCI data storage.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing meter size or another configured lookup value.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token used to cancel the asynchronous operation.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Dictionary:
|
||||
///
|
||||
/// Key:
|
||||
/// Calibration parameter name
|
||||
///
|
||||
/// Value:
|
||||
/// Calibration parameter value
|
||||
/// </returns>
|
||||
public Task<Dictionary<string, UInt32>> ReadPreAdjustmentCalibrationParamsAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return calibrationParamsReader.ReadCalibrationParamsAsync(
|
||||
query,
|
||||
token);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -21,15 +21,16 @@
|
||||
"PreAdjustmentCalibrationParams": {
|
||||
|
||||
"___Documentation___": {
|
||||
"Description": "Reads pre-adjustment values from CSV",
|
||||
"DataSource": "Relative path resolved from application directory",
|
||||
"QueryTemplate": "CSV/JSON syntax: SELECT [ReturnColumn] WHERE [MatchColumn]=QUERYPARAM or SELECT COLUMN(1) WHERE COLUMN(0)=QUERYPARAM"
|
||||
"Description": "Reads pre-adjustment calibration parameters by meter size",
|
||||
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
|
||||
"DataSource": "Database connection string",
|
||||
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [MeterSize]=QUERYPARAM -> meter size provided during ReadCalibrationParamsAsync()."
|
||||
},
|
||||
|
||||
"Name": "PreAdjustmentCalibrationParams",
|
||||
"Type": "LocalCsv",
|
||||
"DataSource": "Data\\preadjustment_params.csv",
|
||||
"QueryTemplate": "SELECT [Offset] WHERE [PcbId] = QUERYPARAM"
|
||||
"Type": "LocalDatabase",
|
||||
"DataSource": "Server=(localdb)\\MojaDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
|
||||
"QueryTemplate": "SELECT [ParameterName], [ParameterValue] FROM [dbo].[PreAdjustmentCalibrationParams] WHERE [MeterSize] = QUERYPARAM"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
GenesisCordonelInterface/Core/Config/GciConfig.cs
Normal file
32
GenesisCordonelInterface/Core/Config/GciConfig.cs
Normal file
@ -0,0 +1,32 @@
|
||||
namespace GenesisCordonelInterface.Core.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Root GCI configuration object loaded from gci_config.json.
|
||||
///
|
||||
/// This class represents the top-level configuration structure
|
||||
/// and serves as an entry point for all configurable GCI features.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// {
|
||||
/// "DataStorageSection":
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
/// }
|
||||
/// </summary>
|
||||
public class GciConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Data storage configuration section.
|
||||
///
|
||||
/// Contains definitions for all configured readers and writers,
|
||||
/// such as:
|
||||
///
|
||||
/// - MeterLoginPasswords
|
||||
/// - PreAdjustmentCalibrationParams
|
||||
/// - future storage providers
|
||||
/// </summary>
|
||||
public DataStorage.Config.GciDataStorageConfig DataStorageSection { get; set; }
|
||||
}
|
||||
}
|
||||
177
GenesisCordonelInterface/Core/Config/GciConfigLoader.cs
Normal file
177
GenesisCordonelInterface/Core/Config/GciConfigLoader.cs
Normal file
@ -0,0 +1,177 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GenesisCordonelInterface.Core.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads GCI configuration from gci_config.json.
|
||||
///
|
||||
/// Responsibilities:
|
||||
/// - Locate configuration file
|
||||
/// - Deserialize JSON into strongly typed objects
|
||||
/// - Normalize relative file paths
|
||||
/// - Preserve database connection strings and REST URLs
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// Config/
|
||||
/// gci_config.json
|
||||
///
|
||||
/// Data/
|
||||
/// meter_passwords.csv
|
||||
///
|
||||
/// Relative paths:
|
||||
/// Data\file.csv
|
||||
///
|
||||
/// become:
|
||||
///
|
||||
/// C:\App\bin\Debug\Data\file.csv
|
||||
///
|
||||
/// Database sources remain unchanged:
|
||||
///
|
||||
/// Server=(localdb)\MojaDB;Database=...
|
||||
/// </summary>
|
||||
public static class GciConfigLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads default GCI configuration from:
|
||||
///
|
||||
/// Config\gci_config.json
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Loaded GCI configuration.
|
||||
/// </returns>
|
||||
public static GciConfig LoadDefault()
|
||||
{
|
||||
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
string configPath = Path.Combine(
|
||||
baseDirectory,
|
||||
"Config",
|
||||
"gci_config.json");
|
||||
|
||||
return Load(configPath, baseDirectory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads GCI configuration from specified file.
|
||||
/// </summary>
|
||||
/// <param name="configPath">
|
||||
/// Path to configuration json file.
|
||||
/// </param>
|
||||
/// <param name="baseDirectory">
|
||||
/// Base directory used for resolving relative paths.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Loaded configuration object.
|
||||
/// </returns>
|
||||
public static GciConfig Load(
|
||||
string configPath,
|
||||
string baseDirectory = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(configPath))
|
||||
throw new ArgumentException(
|
||||
"Config path must not be empty.",
|
||||
nameof(configPath));
|
||||
|
||||
if (!File.Exists(configPath))
|
||||
throw new FileNotFoundException(
|
||||
"GCI config file was not found.",
|
||||
configPath);
|
||||
|
||||
string json = File.ReadAllText(configPath);
|
||||
|
||||
GciConfig config =
|
||||
JsonConvert.DeserializeObject<GciConfig>(json);
|
||||
|
||||
if (config == null)
|
||||
throw new InvalidOperationException(
|
||||
"GCI config could not be loaded.");
|
||||
|
||||
NormalizeDataStoragePaths(
|
||||
config,
|
||||
baseDirectory ?? Path.GetDirectoryName(configPath));
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes paths for all configured data storage entries.
|
||||
///
|
||||
/// Converts relative file paths into absolute paths.
|
||||
/// Database connection strings remain untouched.
|
||||
/// </summary>
|
||||
/// <param name="config">
|
||||
/// Loaded configuration object.
|
||||
/// </param>
|
||||
/// <param name="baseDirectory">
|
||||
/// Base path used for relative resolution.
|
||||
/// </param>
|
||||
private static void NormalizeDataStoragePaths(
|
||||
GciConfig config,
|
||||
string baseDirectory)
|
||||
{
|
||||
if (config.DataStorageSection == null)
|
||||
return;
|
||||
|
||||
NormalizePath(
|
||||
config.DataStorageSection.MeterLoginPasswords,
|
||||
baseDirectory);
|
||||
|
||||
NormalizePath(
|
||||
config.DataStorageSection.PreAdjustmentCalibrationParams,
|
||||
baseDirectory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts relative file paths into absolute paths.
|
||||
///
|
||||
/// Applies only to:
|
||||
/// - LocalCsv
|
||||
/// - RemoteCsv
|
||||
/// - LocalJson
|
||||
/// - RemoteJson
|
||||
///
|
||||
/// Does not modify:
|
||||
/// - Database connection strings
|
||||
/// - REST URLs
|
||||
/// </summary>
|
||||
/// <param name="storageConfig">
|
||||
/// Storage configuration.
|
||||
/// </param>
|
||||
/// <param name="baseDirectory">
|
||||
/// Base path for resolution.
|
||||
/// </param>
|
||||
private static void NormalizePath(
|
||||
DataStorageConfig storageConfig,
|
||||
string baseDirectory)
|
||||
{
|
||||
if (storageConfig == null)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(storageConfig.DataSource))
|
||||
return;
|
||||
|
||||
// Database connection strings and URLs
|
||||
// must never be treated as file paths.
|
||||
if (storageConfig.Type == DataStorageType.LocalDatabase ||
|
||||
storageConfig.Type == DataStorageType.RemoteDatabase ||
|
||||
storageConfig.Type == DataStorageType.RestApi)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Path.IsPathRooted(storageConfig.DataSource))
|
||||
return;
|
||||
|
||||
storageConfig.DataSource =
|
||||
Path.GetFullPath(
|
||||
Path.Combine(
|
||||
baseDirectory,
|
||||
storageConfig.DataSource));
|
||||
}
|
||||
}
|
||||
}
|
||||
36
GenesisCordonelInterface/Core/Config/gci_config.json
Normal file
36
GenesisCordonelInterface/Core/Config/gci_config.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"_Comment": "GCI DataStorage configuration",
|
||||
|
||||
"DataStorageSection": {
|
||||
|
||||
"MeterLoginPasswords": {
|
||||
|
||||
"___Documentation___": {
|
||||
"Description": "Reads login passwords for meters by PCB ID",
|
||||
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
|
||||
"DataSource": "Database connection string",
|
||||
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [PcbId]=QUERYPARAM -> PCB ID provided during GetPasswordAsync()."
|
||||
},
|
||||
|
||||
"Name": "MeterLoginPasswords",
|
||||
"Type": "LocalDatabase",
|
||||
"DataSource": "Server=(localdb)\\SensusLocalDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
|
||||
"QueryTemplate": "SELECT [Password] FROM [dbo].[SkeletonKeys] WHERE [PcbId] = QUERYPARAM"
|
||||
},
|
||||
|
||||
"PreAdjustmentCalibrationParams": {
|
||||
|
||||
"___Documentation___": {
|
||||
"Description": "Reads pre-adjustment calibration parameters by meter size",
|
||||
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
|
||||
"DataSource": "Database connection string",
|
||||
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [MeterSize]=QUERYPARAM -> meter size provided during ReadCalibrationParamsAsync()."
|
||||
},
|
||||
|
||||
"Name": "PreAdjustmentCalibrationParams",
|
||||
"Type": "LocalDatabase",
|
||||
"DataSource": "Server=(localdb)\\SensusLocalDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
|
||||
"QueryTemplate": "SELECT [ParameterName], [ParameterValue] FROM [dbo].[PreAdjustmentCalibrationParams] WHERE [MeterSize] = QUERYPARAM"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,5 +46,17 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
|
||||
/// WHERE [PcbId]=QUERYPARAM
|
||||
/// </summary>
|
||||
public string QueryTemplate { get; set; }
|
||||
|
||||
public DataStorageConfig(
|
||||
string name,
|
||||
DataStorageType type,
|
||||
string dataSource,
|
||||
string queryTemplate)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
DataSource = dataSource;
|
||||
QueryTemplate = queryTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,17 +2,52 @@
|
||||
|
||||
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
|
||||
{
|
||||
public class DatabaseSearchResult
|
||||
/// <summary>
|
||||
/// Represents result returned by database-based
|
||||
/// data storage readers.
|
||||
///
|
||||
/// Supports both:
|
||||
///
|
||||
/// - Single-row lookups
|
||||
/// (e.g. MeterLoginPasswords)
|
||||
///
|
||||
/// - Multi-row queries
|
||||
/// (e.g. PreAdjustmentCalibrationParams)
|
||||
/// </summary>
|
||||
internal class DatabaseSearchResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether at least one record
|
||||
/// was found.
|
||||
/// </summary>
|
||||
public bool Found { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Executed SQL query text.
|
||||
/// Mainly intended for diagnostics
|
||||
/// and troubleshooting.
|
||||
/// </summary>
|
||||
public string Query { get; set; }
|
||||
|
||||
public Dictionary<string, object> Values { get; set; }
|
||||
/// <summary>
|
||||
/// First returned row represented as
|
||||
/// column/value pairs.
|
||||
///
|
||||
/// Preserved for backward compatibility
|
||||
/// with existing readers expecting
|
||||
/// a single database record.
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Values { get; }
|
||||
= new Dictionary<string, object>();
|
||||
|
||||
public DatabaseSearchResult()
|
||||
{
|
||||
Values = new Dictionary<string, object>();
|
||||
}
|
||||
/// <summary>
|
||||
/// All returned rows represented as
|
||||
/// a collection of column/value dictionaries.
|
||||
///
|
||||
/// Intended for queries returning
|
||||
/// multiple records.
|
||||
/// </summary>
|
||||
public List<Dictionary<string, object>> Rows { get; }
|
||||
= new List<Dictionary<string, object>>();
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
@ -14,76 +15,152 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
|
||||
/// QueryTemplate must contain QUERYPARAM placeholder.
|
||||
///
|
||||
/// Example:
|
||||
/// SELECT [Password] FROM [dbo].[SkeletonKeys] WHERE [PcbId] = QUERYPARAM
|
||||
///
|
||||
/// The placeholder is internally converted to SQL parameter @value.
|
||||
/// SELECT [Password]
|
||||
/// FROM [dbo].[SkeletonKeys]
|
||||
/// WHERE [PcbId] = QUERYPARAM
|
||||
///
|
||||
/// or
|
||||
///
|
||||
/// SELECT [ParameterName], [ParameterValue]
|
||||
/// FROM [dbo].[PreAdjustmentCalibrationParams]
|
||||
/// WHERE [Dn_InternalId] = QUERYPARAM
|
||||
///
|
||||
/// The placeholder is internally converted
|
||||
/// to SQL parameter @value.
|
||||
///
|
||||
/// Supports both:
|
||||
///
|
||||
/// - Single-row lookups
|
||||
/// - Multi-row result sets
|
||||
/// </summary>
|
||||
public class DatabaseDataStorageReader : IDataStorageReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Data storage configuration containing connection string and query template.
|
||||
/// Data storage configuration containing
|
||||
/// connection string and query template.
|
||||
/// </summary>
|
||||
private readonly DataStorageConfig config;
|
||||
|
||||
/// <summary>
|
||||
/// Creates SQL Server data storage reader using provided configuration.
|
||||
/// Creates SQL Server data storage reader
|
||||
/// using provided configuration.
|
||||
/// </summary>
|
||||
/// <param name="config">
|
||||
/// Data storage configuration loaded from gci_config.json.
|
||||
/// Data storage configuration loaded
|
||||
/// from gci_config.json.
|
||||
/// </param>
|
||||
public DatabaseDataStorageReader(DataStorageConfig config)
|
||||
public DatabaseDataStorageReader(
|
||||
DataStorageConfig config)
|
||||
{
|
||||
this.config = config ?? throw new ArgumentNullException(nameof(config));
|
||||
this.config =
|
||||
config ?? throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes configured SQL query and returns first matching row.
|
||||
/// Executes configured SQL query and returns
|
||||
/// matching database records.
|
||||
///
|
||||
/// Single-row queries populate:
|
||||
/// DatabaseSearchResult.Values
|
||||
///
|
||||
/// Multi-row queries populate:
|
||||
/// DatabaseSearchResult.Rows
|
||||
///
|
||||
/// For backward compatibility, the first row
|
||||
/// is also stored in Values.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Query object containing lookup parameter.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// DatabaseSearchResult containing returned SQL columns and values.
|
||||
/// DatabaseSearchResult containing returned
|
||||
/// database records.
|
||||
///
|
||||
/// Values contains the first returned row.
|
||||
///
|
||||
/// Rows contains the complete result set.
|
||||
/// </returns>
|
||||
public object GetData(DataQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
|
||||
ReaderDiagnosticResult sourceResult = TestSource(true);
|
||||
ReaderDiagnosticResult sourceResult =
|
||||
TestSource(true);
|
||||
|
||||
if (!sourceResult.Success)
|
||||
throw new InvalidOperationException(sourceResult.Message);
|
||||
|
||||
string sqlText = PrepareSqlText(config.QueryTemplate);
|
||||
object queryValue = ExtractQueryValue(query);
|
||||
string sqlText =
|
||||
PrepareSqlText(config.QueryTemplate);
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(config.DataSource))
|
||||
using (SqlCommand command = new SqlCommand(sqlText, connection))
|
||||
object queryValue =
|
||||
ExtractQueryValue(query);
|
||||
|
||||
using (SqlConnection connection =
|
||||
new SqlConnection(config.DataSource))
|
||||
|
||||
using (SqlCommand command =
|
||||
new SqlCommand(sqlText, connection))
|
||||
{
|
||||
AddQueryParameter(command, queryValue);
|
||||
|
||||
connection.Open();
|
||||
|
||||
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
|
||||
// Full result set is required because some
|
||||
// storage definitions return multiple records
|
||||
// (e.g. PreAdjustmentCalibrationParams).
|
||||
using (SqlDataReader reader =
|
||||
command.ExecuteReader())
|
||||
{
|
||||
DatabaseSearchResult result = new DatabaseSearchResult
|
||||
DatabaseSearchResult result =
|
||||
new DatabaseSearchResult
|
||||
{
|
||||
Query = sqlText
|
||||
};
|
||||
|
||||
if (!reader.Read())
|
||||
while (reader.Read())
|
||||
{
|
||||
result.Found = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Found = true;
|
||||
|
||||
// Represents one database row.
|
||||
Dictionary<string, object> row =
|
||||
new Dictionary<string, object>();
|
||||
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
object value = reader.GetValue(i);
|
||||
result.Values[reader.GetName(i)] =
|
||||
value == DBNull.Value ? null : value;
|
||||
object value =
|
||||
reader.GetValue(i);
|
||||
|
||||
object normalizedValue =
|
||||
value == DBNull.Value
|
||||
? null
|
||||
: value;
|
||||
|
||||
row[reader.GetName(i)] =
|
||||
normalizedValue;
|
||||
}
|
||||
|
||||
// Preserve first row for legacy consumers
|
||||
// expecting a single returned database record
|
||||
// (e.g. MeterLoginPasswordReader).
|
||||
if (result.Rows.Count == 0)
|
||||
{
|
||||
foreach (var item in row)
|
||||
{
|
||||
result.Values[item.Key] =
|
||||
item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Store complete database result set.
|
||||
result.Rows.Add(row);
|
||||
}
|
||||
|
||||
if (result.Rows.Count == 0)
|
||||
{
|
||||
result.Found = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -92,7 +169,8 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether SQL Server connection can be opened.
|
||||
/// Tests whether SQL Server connection
|
||||
/// can be opened.
|
||||
/// </summary>
|
||||
/// <param name="enableDiagnostics">
|
||||
/// Enables detailed diagnostic output.
|
||||
@ -100,45 +178,70 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
|
||||
/// <returns>
|
||||
/// Diagnostic result of SQL connection test.
|
||||
/// </returns>
|
||||
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
|
||||
public ReaderDiagnosticResult TestSource(
|
||||
bool enableDiagnostics)
|
||||
{
|
||||
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
|
||||
ReaderDiagnosticResult result =
|
||||
new ReaderDiagnosticResult();
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(config.DataSource))
|
||||
throw new InvalidOperationException("Data source is empty.");
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Data source is empty.");
|
||||
}
|
||||
|
||||
Log(result, enableDiagnostics, "Opening SQL connection.");
|
||||
Log(
|
||||
result,
|
||||
enableDiagnostics,
|
||||
"Opening SQL connection.");
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(config.DataSource))
|
||||
using (SqlConnection connection =
|
||||
new SqlConnection(config.DataSource))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
Log(result, enableDiagnostics, "Connection opened successfully.");
|
||||
Log(
|
||||
result,
|
||||
enableDiagnostics,
|
||||
"Connection opened successfully.");
|
||||
|
||||
using (SqlCommand command = new SqlCommand("SELECT 1", connection))
|
||||
using (SqlCommand command =
|
||||
new SqlCommand("SELECT 1", connection))
|
||||
{
|
||||
object value = command.ExecuteScalar();
|
||||
Log(result, enableDiagnostics, "Test query result: " + value);
|
||||
object value =
|
||||
command.ExecuteScalar();
|
||||
|
||||
Log(
|
||||
result,
|
||||
enableDiagnostics,
|
||||
"Test query result: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
result.Success = true;
|
||||
result.Message = "Connection to SQL Server OK.";
|
||||
result.Message =
|
||||
"Connection to SQL Server OK.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = "Failed to connect to SQL Server. " + ex.Message;
|
||||
Log(result, enableDiagnostics, ex.ToString());
|
||||
result.Message =
|
||||
"Failed to connect to SQL Server. " + ex.Message;
|
||||
|
||||
Log(
|
||||
result,
|
||||
enableDiagnostics,
|
||||
ex.ToString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether configured SQL query can be prepared and executed.
|
||||
/// Tests whether configured SQL query
|
||||
/// can be prepared and executed.
|
||||
/// </summary>
|
||||
/// <param name="enableDiagnostics">
|
||||
/// Enables detailed diagnostic output.
|
||||
@ -146,16 +249,22 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
|
||||
/// <returns>
|
||||
/// Diagnostic result of query execution test.
|
||||
/// </returns>
|
||||
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
|
||||
public ReaderDiagnosticResult TestQuery(
|
||||
bool enableDiagnostics)
|
||||
{
|
||||
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
|
||||
ReaderDiagnosticResult result =
|
||||
new ReaderDiagnosticResult();
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(config.QueryTemplate))
|
||||
throw new InvalidOperationException("Query template is empty.");
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Query template is empty.");
|
||||
}
|
||||
|
||||
string sqlText = PrepareSqlText(config.QueryTemplate);
|
||||
string sqlText =
|
||||
PrepareSqlText(config.QueryTemplate);
|
||||
|
||||
Log(result, enableDiagnostics, "Original template:");
|
||||
Log(result, enableDiagnostics, config.QueryTemplate);
|
||||
@ -163,69 +272,91 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
|
||||
Log(result, enableDiagnostics, "Prepared SQL:");
|
||||
Log(result, enableDiagnostics, sqlText);
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(config.DataSource))
|
||||
using (SqlCommand command = new SqlCommand(sqlText, connection))
|
||||
using (SqlConnection connection =
|
||||
new SqlConnection(config.DataSource))
|
||||
|
||||
using (SqlCommand command =
|
||||
new SqlCommand(sqlText, connection))
|
||||
{
|
||||
AddQueryParameter(command, "TEST");
|
||||
|
||||
connection.Open();
|
||||
object value = command.ExecuteScalar();
|
||||
|
||||
object value =
|
||||
command.ExecuteScalar();
|
||||
|
||||
result.Data = value;
|
||||
|
||||
Log(result, enableDiagnostics, "Query executed successfully.");
|
||||
Log(
|
||||
result,
|
||||
enableDiagnostics,
|
||||
"Query executed successfully.");
|
||||
}
|
||||
|
||||
result.Success = true;
|
||||
result.Message = "Query executed successfully.";
|
||||
result.Message =
|
||||
"Query executed successfully.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Message = "Query execution failed. " + ex.Message;
|
||||
Log(result, enableDiagnostics, ex.ToString());
|
||||
result.Message =
|
||||
"Query execution failed. " + ex.Message;
|
||||
|
||||
Log(
|
||||
result,
|
||||
enableDiagnostics,
|
||||
ex.ToString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts configured QueryTemplate to executable SQL text.
|
||||
/// Converts configured QueryTemplate
|
||||
/// to executable SQL text.
|
||||
/// </summary>
|
||||
/// <param name="queryTemplate">
|
||||
/// SQL query template containing QUERYPARAM placeholder.
|
||||
/// SQL query template containing
|
||||
/// QUERYPARAM placeholder.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// SQL text with QUERYPARAM replaced by @value parameter.
|
||||
/// SQL text with QUERYPARAM replaced
|
||||
/// by @value parameter.
|
||||
/// </returns>
|
||||
private static string PrepareSqlText(string queryTemplate)
|
||||
private static string PrepareSqlText(
|
||||
string queryTemplate)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(queryTemplate))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Query template must not be empty.",
|
||||
nameof(queryTemplate));
|
||||
}
|
||||
|
||||
if (!queryTemplate.Contains("QUERYPARAM"))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Query template must contain QUERYPARAM placeholder.");
|
||||
}
|
||||
|
||||
return queryTemplate.Replace("QUERYPARAM", "@value");
|
||||
return queryTemplate.Replace(
|
||||
"QUERYPARAM",
|
||||
"@value");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts first query parameter value.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing query parameters.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// First query parameter value.
|
||||
/// </returns>
|
||||
private static object ExtractQueryValue(DataQuery query)
|
||||
private static object ExtractQueryValue(
|
||||
DataQuery query)
|
||||
{
|
||||
if (query.QueryParams == null ||
|
||||
query.QueryParams.Count == 0)
|
||||
{
|
||||
if (query.QueryParams == null || query.QueryParams.Count == 0)
|
||||
throw new InvalidOperationException(
|
||||
"DataQuery does not contain any query parameter.");
|
||||
}
|
||||
|
||||
return query.QueryParams[0];
|
||||
}
|
||||
@ -233,32 +364,25 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
|
||||
/// <summary>
|
||||
/// Adds lookup parameter to SQL command.
|
||||
/// </summary>
|
||||
/// <param name="command">
|
||||
/// SQL command.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// Query parameter value.
|
||||
/// </param>
|
||||
private static void AddQueryParameter(SqlCommand command, object value)
|
||||
private static void AddQueryParameter(
|
||||
SqlCommand command,
|
||||
object value)
|
||||
{
|
||||
command.Parameters.Clear();
|
||||
|
||||
SqlParameter parameter = command.Parameters.Add("@value", SqlDbType.Variant);
|
||||
parameter.Value = value ?? DBNull.Value;
|
||||
SqlParameter parameter =
|
||||
command.Parameters.Add(
|
||||
"@value",
|
||||
SqlDbType.Variant);
|
||||
|
||||
parameter.Value =
|
||||
value ?? DBNull.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds diagnostic line when diagnostics are enabled.
|
||||
/// Adds diagnostic line when diagnostics
|
||||
/// are enabled.
|
||||
/// </summary>
|
||||
/// <param name="result">
|
||||
/// Diagnostic result object.
|
||||
/// </param>
|
||||
/// <param name="enableDiagnostics">
|
||||
/// Indicates whether diagnostics are enabled.
|
||||
/// </param>
|
||||
/// <param name="message">
|
||||
/// Diagnostic message.
|
||||
/// </param>
|
||||
private static void Log(
|
||||
ReaderDiagnosticResult result,
|
||||
bool enableDiagnostics,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Threading;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords
|
||||
@ -27,7 +28,7 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.Meter
|
||||
/// <returns>
|
||||
/// Password if found; otherwise null.
|
||||
/// </returns>
|
||||
string GetPassword(string queryParam);
|
||||
string GetPassword(DataQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Reads meter login password asynchronously.
|
||||
@ -43,8 +44,8 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.Meter
|
||||
/// <returns>
|
||||
/// Password if found; otherwise null.
|
||||
/// </returns>
|
||||
Task<string> GetPasswordAsync(
|
||||
string queryParam,
|
||||
Task<string> ReadMeterLoginPasswordAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default);
|
||||
}
|
||||
}
|
||||
@ -7,11 +7,13 @@ using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// Reads meter login password from configured GCI data storage.
|
||||
/// </summary>
|
||||
public class MeterLoginPasswordReader : IMeterLoginPasswordReader
|
||||
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads meter login password from configured GCI data storage.
|
||||
/// </summary>
|
||||
public class MeterLoginPasswordReader : IMeterLoginPasswordReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Universal data storage reader selected by configuration.
|
||||
/// Can represent database, CSV, JSON or REST reader.
|
||||
@ -33,24 +35,39 @@ public class MeterLoginPasswordReader : IMeterLoginPasswordReader
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously reads meter login password by query parameter.
|
||||
/// Asynchronously reads meter login password using
|
||||
/// the provided data query.
|
||||
///
|
||||
/// Thread-safe implementation may serialize
|
||||
/// access to the underlying storage.
|
||||
/// </summary>
|
||||
/// <param name="queryParam">PCB ID or another configured lookup value.</param>
|
||||
/// <param name="token">Cancellation token.</param>
|
||||
/// <returns>Password if found; otherwise null.</returns>
|
||||
public async Task<string> GetPasswordAsync(
|
||||
string queryParam,
|
||||
/// <param name="query">
|
||||
/// Data query containing lookup parameter values.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Password if found; otherwise null.
|
||||
/// </returns>
|
||||
public async Task<string> ReadMeterLoginPasswordAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(queryParam))
|
||||
throw new ArgumentException("Query parameter must not be empty.", nameof(queryParam));
|
||||
if (query == null)
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
|
||||
if (query.QueryParams.Count == 0)
|
||||
throw new ArgumentException(
|
||||
"Query does not contain any parameter.",
|
||||
nameof(query));
|
||||
|
||||
await readLock.WaitAsync(token);
|
||||
|
||||
try
|
||||
{
|
||||
return await Task.Run(
|
||||
() => GetPassword(queryParam),
|
||||
() => GetPassword(query),
|
||||
token);
|
||||
}
|
||||
finally
|
||||
@ -60,32 +77,50 @@ public class MeterLoginPasswordReader : IMeterLoginPasswordReader
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads meter login password by query parameter.
|
||||
/// Reads meter login password using
|
||||
/// the provided data query.
|
||||
/// </summary>
|
||||
/// <param name="queryParam">PCB ID or another configured lookup value.</param>
|
||||
/// <returns>Password if found; otherwise null.</returns>
|
||||
public string GetPassword(string queryParam)
|
||||
/// <param name="query">
|
||||
/// Data query containing lookup parameter values.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Password if found; otherwise null.
|
||||
/// </returns>
|
||||
public string GetPassword(
|
||||
DataQuery query)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(queryParam))
|
||||
throw new ArgumentException("Query parameter must not be empty.", nameof(queryParam));
|
||||
if (query == null)
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
|
||||
DataQuery query = new DataQuery();
|
||||
query.QueryParams.Add(queryParam);
|
||||
if (query.QueryParams.Count == 0)
|
||||
throw new ArgumentException(
|
||||
"Query does not contain any parameter.",
|
||||
nameof(query));
|
||||
|
||||
object result = reader.GetData(query);
|
||||
object result =
|
||||
reader.GetData(query);
|
||||
|
||||
if (result is ReaderDiagnosticResult csvResult)
|
||||
return csvResult.Data?.ToString();
|
||||
if (result is ReaderDiagnosticResult diagnosticResult)
|
||||
{
|
||||
return diagnosticResult.Data?.ToString();
|
||||
}
|
||||
|
||||
if (result is DatabaseSearchResult dbResult)
|
||||
{
|
||||
if (!dbResult.Found || dbResult.Values == null || dbResult.Values.Count == 0)
|
||||
if (!dbResult.Found ||
|
||||
dbResult.Values == null ||
|
||||
dbResult.Values.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (object value in dbResult.Values.Values)
|
||||
{
|
||||
return value?.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return result?.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,43 +1,62 @@
|
||||
using System.Collections.Generic;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to pre-adjustment calibration parameters
|
||||
/// stored in the configured data source.
|
||||
/// stored in the configured GCI data source.
|
||||
///
|
||||
/// Expected structure:
|
||||
/// Dn_InternalId | ParameterName | ParameterValue
|
||||
///
|
||||
/// MeterSize | ParameterName | ParameterValue
|
||||
///
|
||||
/// Example:
|
||||
/// 3 | GENESISFLOW_MinValidToF | 21990232
|
||||
/// 3 | GENESISFLOW_Timeout | 1
|
||||
///
|
||||
/// Parameters are grouped by Dn_InternalId and returned
|
||||
/// 2 | GENESISFLOW_MinValidToF | 21990232
|
||||
/// 2 | GENESISFLOW_Timeout | 1
|
||||
///
|
||||
/// Parameters are grouped by MeterSize and returned
|
||||
/// as key/value pairs where:
|
||||
///
|
||||
/// Key = ParameterName
|
||||
/// Value = ParameterValue
|
||||
/// </summary>
|
||||
internal interface IPreAdjustmentCalibrationParamsReader
|
||||
public interface IPreAdjustmentCalibrationParamsReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads all calibration parameters assigned
|
||||
/// to a specific DN identifier.
|
||||
/// Reads all pre-adjustment calibration parameters
|
||||
/// using the provided data query synchronously.
|
||||
/// </summary>
|
||||
/// <param name="dnInternalId">
|
||||
/// Internal DN identifier (meter size).
|
||||
/// <param name="query">
|
||||
/// Data query containing meter size as lookup parameter.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Dictionary:
|
||||
///
|
||||
/// Key:
|
||||
/// GENESISFLOW parameter name
|
||||
///
|
||||
/// Value:
|
||||
/// Stored parameter value
|
||||
/// Dictionary where key is GENESISFLOW parameter name
|
||||
/// and value is stored parameter value.
|
||||
/// </returns>
|
||||
Task<Dictionary<string, string>> ReadParamsAsync(int dnInternalId);
|
||||
Dictionary<string, UInt32> GetCalibrationParams(
|
||||
DataQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Reads all pre-adjustment calibration parameters
|
||||
/// using the provided data query asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing meter size as lookup parameter.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Dictionary where key is GENESISFLOW parameter name
|
||||
/// and value is stored parameter value.
|
||||
/// </returns>
|
||||
Task<Dictionary<string, UInt32>> ReadCalibrationParamsAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default);
|
||||
}
|
||||
}
|
||||
@ -1,87 +1,305 @@
|
||||
using System;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads pre-adjustment calibration parameters
|
||||
/// from SQL database storage.
|
||||
/// from configured GCI data storage.
|
||||
///
|
||||
/// Expected table:
|
||||
/// The underlying storage type is selected
|
||||
/// through IDataStorageReader and may represent:
|
||||
///
|
||||
/// dbo.PreAdjustmentCalibrationParams
|
||||
/// - SQL database
|
||||
/// - CSV
|
||||
/// - JSON
|
||||
/// - REST API
|
||||
///
|
||||
/// Columns:
|
||||
/// Dn_InternalId
|
||||
/// ParameterName
|
||||
/// ParameterValue
|
||||
/// Expected storage structure:
|
||||
///
|
||||
/// MeterSize | ParameterName | ParameterValue
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// 3 | GENESISFLOW_MinValidToF | 21990232
|
||||
/// 3 | GENESISFLOW_Timeout | 1
|
||||
/// 2 | GENESISFLOW_MinValidToF | 21990232
|
||||
/// 2 | GENESISFLOW_Timeout | 1
|
||||
///
|
||||
/// Returns values as dictionary:
|
||||
/// Returned data are represented as:
|
||||
///
|
||||
/// GENESISFLOW_MinValidToF -> 21990232
|
||||
/// GENESISFLOW_Timeout -> 1
|
||||
/// Key = ParameterName
|
||||
/// Value = ParameterValue
|
||||
/// </summary>
|
||||
internal class PreAdjustmentCalibrationParamsReader: IPreAdjustmentCalibrationParamsReader
|
||||
public class PreAdjustmentCalibrationParamsReader
|
||||
: IPreAdjustmentCalibrationParamsReader
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
/// <summary>
|
||||
/// Universal data storage reader selected by configuration.
|
||||
/// Can represent database, CSV, JSON or REST reader.
|
||||
/// </summary>
|
||||
private readonly IDataStorageReader reader;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes calibration parameter reader.
|
||||
/// Ensures that only one calibration parameter lookup
|
||||
/// is executed at a time.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">
|
||||
/// SQL database connection string.
|
||||
private readonly SemaphoreSlim readLock =
|
||||
new SemaphoreSlim(1, 1);
|
||||
|
||||
/// <summary>
|
||||
/// Creates calibration parameter reader using
|
||||
/// provided data storage configuration.
|
||||
/// </summary>
|
||||
/// <param name="config">
|
||||
/// Data storage configuration loaded from gci_config.json.
|
||||
/// </param>
|
||||
public PreAdjustmentCalibrationParamsReader(
|
||||
string connectionString)
|
||||
DataStorageConfig config)
|
||||
{
|
||||
_connectionString = connectionString?? throw new ArgumentNullException(nameof(connectionString));
|
||||
if (config == null)
|
||||
throw new ArgumentNullException(nameof(config));
|
||||
|
||||
reader = DataStorageReaderFactory.Create(config);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<Dictionary<string, string>> ReadParamsAsync(int dnInternalId)
|
||||
/// <summary>
|
||||
/// Reads all pre-adjustment calibration parameters
|
||||
/// using the provided data query asynchronously.
|
||||
///
|
||||
/// The query is expected to contain meter size
|
||||
/// as the first lookup parameter.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing lookup parameter values.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Dictionary:
|
||||
///
|
||||
/// Key:
|
||||
/// GENESISFLOW parameter name
|
||||
///
|
||||
/// Value:
|
||||
/// Stored parameter value
|
||||
/// </returns>
|
||||
public async Task<Dictionary<string, UInt32>> ReadCalibrationParamsAsync(
|
||||
DataQuery query,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var result = new Dictionary<string, string>();
|
||||
ValidateQuery(query);
|
||||
|
||||
const string query = @"
|
||||
SELECT ParameterName, ParameterValue
|
||||
FROM dbo.PreAdjustmentCalibrationParams
|
||||
WHERE Dn_InternalId=@Dn_InternalId";
|
||||
return await Task.Run(
|
||||
() => GetCalibrationParams(query),
|
||||
token).ConfigureAwait(false); ;
|
||||
|
||||
using (var connection = new SqlConnection(_connectionString))
|
||||
/*await readLock.WaitAsync(token);
|
||||
|
||||
using (var command = new SqlCommand(query, connection))
|
||||
try
|
||||
{
|
||||
command.Parameters.AddWithValue(
|
||||
"@Dn_InternalId",
|
||||
dnInternalId);
|
||||
|
||||
await connection.OpenAsync();
|
||||
|
||||
using (var reader =
|
||||
await command.ExecuteReaderAsync())
|
||||
{
|
||||
while (await reader.ReadAsync())
|
||||
{
|
||||
var parameterName = reader["ParameterName"].ToString();
|
||||
|
||||
var parameterValue = reader["ParameterValue"].ToString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(parameterName))
|
||||
{
|
||||
result[parameterName] = parameterValue;
|
||||
return await Task.Run(
|
||||
() => GetCalibrationParams(query),
|
||||
token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
readLock.Release();
|
||||
}*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all pre-adjustment calibration parameters
|
||||
/// using the provided data query.
|
||||
///
|
||||
/// The query is expected to contain meter size
|
||||
/// as the first lookup parameter.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query containing lookup parameter values.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Dictionary:
|
||||
///
|
||||
/// Key:
|
||||
/// GENESISFLOW parameter name
|
||||
///
|
||||
/// Value:
|
||||
/// Stored parameter value
|
||||
/// </returns>
|
||||
public Dictionary<string, UInt32> GetCalibrationParams(
|
||||
DataQuery query)
|
||||
{
|
||||
ValidateQuery(query);
|
||||
|
||||
object result =
|
||||
reader.GetData(query);
|
||||
|
||||
return ConvertResultToDictionary(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that data query exists
|
||||
/// and contains at least one lookup parameter.
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// Data query to validate.
|
||||
/// </param>
|
||||
private static void ValidateQuery(
|
||||
DataQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
throw new ArgumentNullException(nameof(query));
|
||||
|
||||
if (query.QueryParams == null ||
|
||||
query.QueryParams.Count == 0)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Query does not contain any parameter.",
|
||||
nameof(query));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
/// <summary>
|
||||
/// Converts provider-specific result objects
|
||||
/// returned by IDataStorageReader into a unified
|
||||
/// dictionary representation.
|
||||
/// </summary>
|
||||
/// <param name="result">
|
||||
/// Raw result returned by the configured storage reader.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Dictionary containing calibration parameter
|
||||
/// name/value pairs.
|
||||
/// </returns>
|
||||
private Dictionary<string, UInt32> ConvertResultToDictionary(
|
||||
object result)
|
||||
{
|
||||
Dictionary<string, UInt32> values =
|
||||
new Dictionary<string, UInt32>();
|
||||
|
||||
if (result == null)
|
||||
return values;
|
||||
|
||||
if (result is DatabaseSearchResult dbResult)
|
||||
{
|
||||
if (!dbResult.Found)
|
||||
return values;
|
||||
|
||||
foreach (Dictionary<string, object> row in dbResult.Rows)
|
||||
{
|
||||
if (!row.TryGetValue("ParameterName", out object parameterNameObject))
|
||||
continue;
|
||||
|
||||
if (!row.TryGetValue("ParameterValue", out object parameterValueObject))
|
||||
continue;
|
||||
|
||||
string parameterName =
|
||||
parameterNameObject?.ToString();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(parameterName))
|
||||
continue;
|
||||
|
||||
if (TryConvertToUInt32(parameterValueObject, out UInt32 parameterValue))
|
||||
{
|
||||
values[parameterName] =
|
||||
parameterValue;
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
if (result is ReaderDiagnosticResult diagnosticResult)
|
||||
{
|
||||
if (diagnosticResult.Data is Dictionary<string, UInt32> uintDictionary)
|
||||
return uintDictionary;
|
||||
|
||||
if (diagnosticResult.Data is Dictionary<string, string> stringDictionary)
|
||||
{
|
||||
foreach (var item in stringDictionary)
|
||||
{
|
||||
if (TryConvertToUInt32(item.Value, out UInt32 value))
|
||||
values[item.Key] = value;
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
if (diagnosticResult.Data is Dictionary<string, object> objectDictionary)
|
||||
{
|
||||
foreach (var item in objectDictionary)
|
||||
{
|
||||
if (TryConvertToUInt32(item.Value, out UInt32 value))
|
||||
values[item.Key] = value;
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
if (result is Dictionary<string, UInt32> directUIntDictionary)
|
||||
return directUIntDictionary;
|
||||
|
||||
if (result is Dictionary<string, string> directStringDictionary)
|
||||
{
|
||||
foreach (var item in directStringDictionary)
|
||||
{
|
||||
if (TryConvertToUInt32(item.Value, out UInt32 value))
|
||||
values[item.Key] = value;
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
if (result is Dictionary<string, object> directObjectDictionary)
|
||||
{
|
||||
foreach (var item in directObjectDictionary)
|
||||
{
|
||||
if (TryConvertToUInt32(item.Value, out UInt32 value))
|
||||
values[item.Key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private static bool TryConvertToUInt32(
|
||||
object value,
|
||||
out UInt32 result)
|
||||
{
|
||||
result = 0;
|
||||
|
||||
if (value == null)
|
||||
return false;
|
||||
|
||||
if (value is UInt32 uintValue)
|
||||
{
|
||||
result = uintValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value is int intValue && intValue >= 0)
|
||||
{
|
||||
result = Convert.ToUInt32(intValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value is long longValue &&
|
||||
longValue >= 0 &&
|
||||
longValue <= UInt32.MaxValue)
|
||||
{
|
||||
result = Convert.ToUInt32(longValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return UInt32.TryParse(
|
||||
value.ToString(),
|
||||
out result);
|
||||
}
|
||||
}
|
||||
}
|
||||
73
GenesisCordonelInterface/Core/Engine/Engine.cs
Normal file
73
GenesisCordonelInterface/Core/Engine/Engine.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using GenesisCordonelInterface.API;
|
||||
using GenesisCordonelInterface.Core.Config;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using UdsReaderType_CalibrationParams = GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams.PreAdjustmentCalibrationParamsReader;
|
||||
using UdsReaderType_LoginPasswords = GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords.MeterLoginPasswordReader;
|
||||
using GciPublicModels = GenesisCordonelInterface.API.PublicModels;
|
||||
using GciEnums = GenesisCordonelInterface.API.Enums;
|
||||
using GciType = GenesisCordonelInterface.API.InterfaceOutsideToGCI;
|
||||
using GciDataStorageReadingModels = GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using GciGUIType = GenesisCordonelInterface.UI.MainView;
|
||||
|
||||
namespace GenesisCordonelInterface.Core
|
||||
{
|
||||
public class Engine
|
||||
{
|
||||
GciConfig gciConfig;
|
||||
|
||||
public UdsReaderType_LoginPasswords loginPasswordsDataStorageReader;
|
||||
public UdsReaderType_CalibrationParams calibrationParamsStorageReader;
|
||||
//readonly UdsWriterType writer;
|
||||
|
||||
//diag GUI for GCI
|
||||
GciGUIType gciGUI;
|
||||
Form gciGuiHostForm;
|
||||
|
||||
//diag GUI for GciBridge
|
||||
public UserControl gciBridgeGUIUserControl;
|
||||
public UI.MainForm gciBridgeGuiForm;
|
||||
|
||||
public InterfaceOutsideToGCI gciExternalInterface;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the public GCI facade.
|
||||
/// </summary>
|
||||
public Engine()
|
||||
{
|
||||
gciConfig = GciConfigLoader.LoadDefault();
|
||||
|
||||
loginPasswordsDataStorageReader = new UdsReaderType_LoginPasswords
|
||||
(
|
||||
new GciDataStorageReadingModels.DataStorageConfig
|
||||
(
|
||||
nameof(GciEnums.DataStorageReaderTypes.LoginPasswordsReader),
|
||||
GciDataStorageReadingModels.DataStorageType.LocalDatabase,
|
||||
gciConfig.DataStorageSection.MeterLoginPasswords.DataSource,
|
||||
gciConfig.DataStorageSection.MeterLoginPasswords.QueryTemplate
|
||||
)
|
||||
);
|
||||
calibrationParamsStorageReader = new UdsReaderType_CalibrationParams
|
||||
(
|
||||
new GciDataStorageReadingModels.DataStorageConfig
|
||||
(
|
||||
nameof(GciEnums.DataStorageReaderTypes.CalibrationParamsReader),
|
||||
GciDataStorageReadingModels.DataStorageType.LocalDatabase,
|
||||
gciConfig.DataStorageSection.PreAdjustmentCalibrationParams.DataSource,
|
||||
gciConfig.DataStorageSection.PreAdjustmentCalibrationParams.QueryTemplate
|
||||
)
|
||||
);
|
||||
|
||||
gciExternalInterface = new InterfaceOutsideToGCI(
|
||||
new InterfaceGCIToLaatzen(),
|
||||
loginPasswordsDataStorageReader,
|
||||
calibrationParamsStorageReader);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,9 +60,10 @@
|
||||
<Compile Include="API\InterfaceOutsideToGCI.cs" />
|
||||
<Compile Include="API\InterfaceGCIToLaatzen.cs" />
|
||||
<Compile Include="API\PublicModels.cs" />
|
||||
<Compile Include="Core\DataStorage\Config\GciConfig.cs" />
|
||||
<Compile Include="Core\DataStorage\Config\GciConfigLoader.cs" />
|
||||
<Compile Include="Core\Config\GciConfig.cs" />
|
||||
<Compile Include="Core\Config\GciConfigLoader.cs" />
|
||||
<Compile Include="Core\DataStorage\Config\GciDataStorageConfig.cs" />
|
||||
<Compile Include="API\Enums.cs" />
|
||||
<Compile Include="Core\DataStorage\Reading\Common\Providers\CsvDataStorageReader.cs" />
|
||||
<Compile Include="Core\DataStorage\Reading\Common\Providers\DatabaseDataStorageReader.cs" />
|
||||
<Compile Include="Core\DataStorage\Reading\Common\Models\DatabaseSearchResult.cs" />
|
||||
@ -80,6 +81,7 @@
|
||||
<Compile Include="Core\DataStorage\Reading\Implementation\MeterLoginPasswords\MeterLoginPasswordReader.cs" />
|
||||
<Compile Include="Core\DataStorage\Reading\Implementation\PreAdjustmentCalibrationParams\IPreAdjustmentCalibrationParamsReader.cs" />
|
||||
<Compile Include="Core\DataStorage\Reading\Implementation\PreAdjustmentCalibrationParams\PreAdjustmentCalibrationParamsReader.cs" />
|
||||
<Compile Include="Core\Engine\Engine.cs" />
|
||||
<Compile Include="Core\Logging\UiLogBus.cs" />
|
||||
<Compile Include="Core\Logging\UiTarget.cs" />
|
||||
<Compile Include="Core\Threading\ApiWorker\ApiWorker.cs" />
|
||||
@ -200,9 +202,11 @@
|
||||
<EmbeddedResource Include="UI\StaraTuraAPI_GenesisCordonelInterface\FrmGCIAPI.resx">
|
||||
<DependentUpon>FrmGCIAPI.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<Content Include="Config\gci_config.json">
|
||||
<Content Include="Core\Config\gci_config.json">
|
||||
<Link>Config\gci_config.json</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Core\Config\gci_config.json" />
|
||||
<None Include="docs\articles\API\index.md" />
|
||||
<None Include="docs\articles\API\PublicModels.md" />
|
||||
<None Include="docs\articles\API\InterfaceGCIToLaatzen.md" />
|
||||
@ -245,6 +249,7 @@
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Config\" />
|
||||
<Folder Include="Core\DataStorage\Writing\NewFolder1\" />
|
||||
<Folder Include="RuntimePackage\Package\" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -122,6 +122,7 @@ namespace GenesisCordonelInterface.UI.Debug
|
||||
{
|
||||
isRefreshing = true;
|
||||
|
||||
if(data != null)
|
||||
foreach (var meter in data)
|
||||
{
|
||||
EnsurePortValueExists(meter.RequestPort);
|
||||
|
||||
36
GenesisCordonelInterface/bin/Debug/Config/gci_config.json
Normal file
36
GenesisCordonelInterface/bin/Debug/Config/gci_config.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"_Comment": "GCI DataStorage configuration",
|
||||
|
||||
"DataStorageSection": {
|
||||
|
||||
"MeterLoginPasswords": {
|
||||
|
||||
"___Documentation___": {
|
||||
"Description": "Reads login passwords for meters by PCB ID",
|
||||
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
|
||||
"DataSource": "Database connection string",
|
||||
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [PcbId]=QUERYPARAM -> PCB ID provided during GetPasswordAsync()."
|
||||
},
|
||||
|
||||
"Name": "MeterLoginPasswords",
|
||||
"Type": "LocalDatabase",
|
||||
"DataSource": "Server=(localdb)\\SensusLocalDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
|
||||
"QueryTemplate": "SELECT [Password] FROM [dbo].[SkeletonKeys] WHERE [PcbId] = QUERYPARAM"
|
||||
},
|
||||
|
||||
"PreAdjustmentCalibrationParams": {
|
||||
|
||||
"___Documentation___": {
|
||||
"Description": "Reads pre-adjustment calibration parameters by meter size",
|
||||
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
|
||||
"DataSource": "Database connection string",
|
||||
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [MeterSize]=QUERYPARAM -> meter size provided during ReadCalibrationParamsAsync()."
|
||||
},
|
||||
|
||||
"Name": "PreAdjustmentCalibrationParams",
|
||||
"Type": "LocalDatabase",
|
||||
"DataSource": "Server=(localdb)\\SensusLocalDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
|
||||
"QueryTemplate": "SELECT [ParameterName], [ParameterValue] FROM [dbo].[PreAdjustmentCalibrationParams] WHERE [MeterSize] = QUERYPARAM"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,12 @@
|
||||
using CordonelPreadjustmentUi;
|
||||
using CordonelPreadjustmentUi.Processes.Itinerary;
|
||||
using GenesisCordonelInterface.API;
|
||||
using GenesisCordonelInterface.Core;
|
||||
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using GenesisCordonelInterface.Core.Threading;
|
||||
using GraphLib;
|
||||
using log4net;
|
||||
using NHibernate.Mapping;
|
||||
///
|
||||
/// Copyright (c) 2015-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
@ -20,10 +24,14 @@ 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 GciEngine = GenesisCordonelInterface.Core.Engine;
|
||||
using GciEnums = GenesisCordonelInterface.API.Enums;
|
||||
using GciGUIType = GenesisCordonelInterface.UI.MainView;
|
||||
using GciPublicModels = GenesisCordonelInterface.API.PublicModels;
|
||||
using GciType = GenesisCordonelInterface.API.InterfaceOutsideToGCI;
|
||||
using UdsReaderType = TBF.Rig.Input.DataStorage.UniDataStorageReader.Reader;
|
||||
using GciUDSRPublicModels = GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
|
||||
using UdsReaderType_CalibrationParams = GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams.PreAdjustmentCalibrationParamsReader;
|
||||
using UdsReaderType_LoginPasswords = GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords.MeterLoginPasswordReader;//TBF.Rig.Input.DataStorageSection.UniDataStorageReader.Reader;
|
||||
using UDSRPublicModels = TBF.Rig.Input.DataStorage.UniDataStorageReader.Interfaces.PublicModels;
|
||||
using UdsWriterType = TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writer;
|
||||
|
||||
@ -44,9 +52,12 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
|
||||
readonly GciBridgeCfg gciBridgeCfg;
|
||||
|
||||
readonly UdsReaderType reader;
|
||||
readonly Reader reader;
|
||||
readonly UdsWriterType writer;
|
||||
|
||||
//GCI main init
|
||||
public GciEngine _gciEngine;
|
||||
|
||||
//diag GUI for GCI
|
||||
GciGUIType gciGUI;
|
||||
Form gciGuiHostForm;
|
||||
@ -55,18 +66,18 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
public UserControl gciBridgeGUIUserControl;
|
||||
public UI.MainForm gciBridgeGuiForm;
|
||||
|
||||
public GciType gciExternalInterface;
|
||||
|
||||
public bool HasReader { get { return reader != null; } }
|
||||
public bool HasWriter { get { return writer != null; } }
|
||||
public bool IsGuiInitialized { get { return gciGUI != null; } }
|
||||
public bool IsExternalInitialized { get { return gciExternalInterface != null; } }
|
||||
public GciType GciExternalInterface { get { return gciExternalInterface; } }
|
||||
public bool IsExternalInitialized { get { return _gciEngine.gciExternalInterface != null; } }
|
||||
public GciType gciExternalInterface { get { return _gciEngine.gciExternalInterface; } }
|
||||
public GciBridgeCfg GciBridgeCfg { get { return gciBridgeCfg; } }
|
||||
|
||||
public UdsReaderType GetReader()
|
||||
public UdsReaderType_LoginPasswords GetLoginPasswordsDataStorageReader()
|
||||
{
|
||||
return reader;
|
||||
return _gciEngine.loginPasswordsDataStorageReader;
|
||||
}
|
||||
public UdsReaderType_CalibrationParams GetCalibrationParamsStorageReader()
|
||||
{
|
||||
return _gciEngine.calibrationParamsStorageReader;
|
||||
}
|
||||
|
||||
public UdsWriterType GetWriter()
|
||||
@ -84,7 +95,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
|
||||
if (!string.IsNullOrEmpty(gciBridgeCfg.ReaderName))
|
||||
{
|
||||
reader = TbfComponents.FindComponent(gciBridgeCfg.ReaderName, components) as UdsReaderType;
|
||||
reader = TbfComponents.FindComponent(gciBridgeCfg.ReaderName, components) as Reader;
|
||||
if (reader == null) throw new Exception("Cannot find reader component '" + gciBridgeCfg.ReaderName + "'");
|
||||
}
|
||||
|
||||
@ -94,6 +105,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (writer == null) throw new Exception("Cannot find writer component '" + gciBridgeCfg.WriterName + "'");
|
||||
}
|
||||
|
||||
_gciEngine = new GciEngine();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
@ -130,17 +143,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
gciBridgeGuiForm.Height = 600;
|
||||
gciBridgeGuiForm.StartPosition = FormStartPosition.CenterScreen;
|
||||
|
||||
/*gciBridgeGUI = new MainView(this, gciBridgeGuiForm);
|
||||
gciBridgeGUI.Dock = DockStyle.Fill;
|
||||
|
||||
gciBridgeGuiForm.Controls.Add(gciBridgeGUI);
|
||||
|
||||
gciBridgeGuiForm.FormClosed += (s, e) =>
|
||||
{
|
||||
gciBridgeGUI = null;
|
||||
gciBridgeGuiForm = null;
|
||||
};*/
|
||||
|
||||
log.InfoFormat("{0}: GciBridge GUI view initialized.", Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -179,10 +181,10 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
{
|
||||
try
|
||||
{
|
||||
if (gciExternalInterface != null)
|
||||
if (_gciEngine.gciExternalInterface != null)
|
||||
return;
|
||||
|
||||
gciExternalInterface = new GciType();
|
||||
_gciEngine.gciExternalInterface = new GciType();
|
||||
|
||||
log.InfoFormat("{0}: GCI external interface initialized.", Name);
|
||||
}
|
||||
@ -255,14 +257,15 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (!IsExternalInitialized)
|
||||
TryInitializeExternalInterface();
|
||||
|
||||
if (gciExternalInterface == null)
|
||||
if (_gciEngine.gciExternalInterface == null)
|
||||
throw new Exception("GCI external interface is not initialized.");
|
||||
}
|
||||
|
||||
void EnsureReader()
|
||||
{
|
||||
if (reader == null)
|
||||
throw new Exception("UniDataStorageReader is not linked to GciBridge.");
|
||||
/*if (reader == null)
|
||||
throw new Exception("UniDataStorageReader is not linked to GciBridge.");*/
|
||||
|
||||
}
|
||||
|
||||
// API:
|
||||
@ -293,7 +296,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (request.SlotId <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(request));
|
||||
|
||||
var result = await gciExternalInterface
|
||||
var result = await _gciEngine.gciExternalInterface
|
||||
.InitSlotAsync(request, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@ -374,7 +377,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (request.SlotId <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(request));
|
||||
|
||||
var result = await gciExternalInterface
|
||||
var result = await _gciEngine.gciExternalInterface
|
||||
.UpdateSlotAsync(request, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@ -450,7 +453,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
GciPublicModels.GciSlotInfo result =
|
||||
await gciExternalInterface.GetSlotAsync(slotId, token);
|
||||
await _gciEngine.gciExternalInterface.GetSlotAsync(slotId, token);
|
||||
|
||||
log.InfoFormat("{0}: GetSlotAsync({1}) invoked. Result={2}", Name, slotId, result);
|
||||
|
||||
@ -526,7 +529,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
throw new ArgumentException("Invalid slot id.", nameof(slot));
|
||||
|
||||
GciPublicModels.GciCleanSlotResult result =
|
||||
await gciExternalInterface.CleanSlotAsync(slot, token);
|
||||
await _gciEngine.gciExternalInterface.CleanSlotAsync(slot, token);
|
||||
|
||||
log.InfoFormat("{0}: CleanSlotAsync invoked. Slot={1}, Result={2}", Name, slot, result);
|
||||
|
||||
@ -599,7 +602,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
EnsureExternalInterface();
|
||||
|
||||
GciPublicModels.GciCleanAllSlotsResult result =
|
||||
await gciExternalInterface.CleanAllSlotsAsync(token);
|
||||
await _gciEngine.gciExternalInterface.CleanAllSlotsAsync(token);
|
||||
|
||||
log.InfoFormat("{0}: CleanAllSlotsAsync invoked.", Name);
|
||||
|
||||
@ -673,7 +676,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (slotId <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(slotId));
|
||||
|
||||
var result = await gciExternalInterface
|
||||
var result = await _gciEngine.gciExternalInterface
|
||||
.GetPcbIdAsync(slotId, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@ -790,7 +793,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (slot <= 0)
|
||||
throw new ArgumentException("Invalid slot id.", nameof(slot));
|
||||
|
||||
var result = await gciExternalInterface
|
||||
var result = await _gciEngine.gciExternalInterface
|
||||
.ConnectOneSlotAsync(slot, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@ -822,7 +825,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (slotId <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
var result = await gciExternalInterface.LoginOneSlotAsync(slotId, token);
|
||||
var result = await _gciEngine.gciExternalInterface.LoginOneSlotAsync(slotId, token);
|
||||
|
||||
log.InfoFormat("{0}: LoginAsync({1}) invoked. Result={2}", Name, slotId, result);
|
||||
|
||||
@ -893,7 +896,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (slotId <= 0)
|
||||
throw new ArgumentException("Invalid slot id.");
|
||||
|
||||
var result = await gciExternalInterface.DisconnectAsync(slotId, token);
|
||||
var result = await _gciEngine.gciExternalInterface.DisconnectAsync(slotId, token);
|
||||
|
||||
log.InfoFormat("{0}: DisconnectAsync({1}) invoked. Result={2}", Name, slotId, result);
|
||||
|
||||
@ -976,7 +979,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
throw new ArgumentException("Password is empty.");
|
||||
|
||||
GciPublicModels.GciSetPasswordResult result =
|
||||
await gciExternalInterface.SetPasswordAsync(slotId, password, token);
|
||||
await _gciEngine.gciExternalInterface.SetPasswordAsync(slotId, password, token);
|
||||
|
||||
log.InfoFormat("{0}: SetPasswordAsync({1}) invoked. Result={2}", Name, slotId, result);
|
||||
|
||||
@ -1051,7 +1054,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (string.IsNullOrWhiteSpace(registerName))
|
||||
throw new ArgumentException("Register name is empty.");
|
||||
|
||||
var result = await gciExternalInterface.ReadRegisterAsync(slotId, registerName, token);
|
||||
var result = await _gciEngine.gciExternalInterface.ReadRegisterAsync(slotId, registerName, token);
|
||||
|
||||
log.InfoFormat("{0}: ReadRegisterAsync({1}, {2}) invoked. Result={3}",
|
||||
Name, slotId, registerName, result);
|
||||
@ -1141,7 +1144,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
if (string.IsNullOrWhiteSpace(registerName))
|
||||
throw new ArgumentException("Register name is empty.");
|
||||
|
||||
var result = await gciExternalInterface.WriteRegisterAsync(
|
||||
var result = await _gciEngine.gciExternalInterface.WriteRegisterAsync(
|
||||
slotId,
|
||||
registerName,
|
||||
value,
|
||||
@ -1222,7 +1225,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
/// Reads password data from UniDataStorageReader by PCB ID.
|
||||
///
|
||||
/// Trace:
|
||||
/// GciBridge.GetPasswordAsync()
|
||||
/// GciBridge.ReadMeterLoginPasswordAsync()
|
||||
/// -> UniDataStorageReader.Reader.GetDataFromStorageByParameterAsync()
|
||||
/// -> Reader queue/lock
|
||||
/// -> Reader.GetDataFromStorageByParameter()
|
||||
@ -1243,9 +1246,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
|
||||
try
|
||||
{
|
||||
UDSRPublicModels.DataQuery query = CreatePasswordQuery(pcbId);
|
||||
GciUDSRPublicModels.DataQuery query = CreatePasswordQuery(pcbId);
|
||||
|
||||
object data = await reader.GetDataFromStorageByParameterAsync(query, token);
|
||||
object data = await _gciEngine.gciExternalInterface.ReadMeterLoginPasswordAsync(query, token);
|
||||
|
||||
string password = ExtractPassword(data);
|
||||
|
||||
@ -1261,7 +1264,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("GetPasswordAsync failed.", ex);
|
||||
log.Error("ReadMeterLoginPasswordAsync failed.", ex);
|
||||
|
||||
return new UdsPasswordResult
|
||||
{
|
||||
@ -1273,7 +1276,132 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads pre-adjustment calibration parameters
|
||||
/// from UniDataStorageReader by meter size.
|
||||
///
|
||||
/// Trace:
|
||||
/// GciBridge.GetPreAdjustmentCalibrationParamsAsync()
|
||||
/// -> UniDataStorageReader.Reader.GetDataFromStorageByParameterAsync()
|
||||
/// -> Reader queue/lock
|
||||
/// -> Reader.GetDataFromStorageByParameter()
|
||||
/// -> selected storage reader by configuration
|
||||
/// -> DatabaseReader.GetData()
|
||||
/// -> RestApiReader.GetData()
|
||||
/// -> JsonReader.GetData()
|
||||
/// -> CsvReader.GetData()
|
||||
///
|
||||
/// Expected result:
|
||||
///
|
||||
/// Key:
|
||||
/// Calibration parameter name
|
||||
///
|
||||
/// Value:
|
||||
/// Calibration parameter value
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// GENESISFLOW_MinValidToF -> 13743895
|
||||
/// GENESISFLOW_Timeout -> 1
|
||||
/// </summary>
|
||||
/// <param name="meterSize">
|
||||
/// Meter size used as query parameter.
|
||||
/// </param>
|
||||
/// <param name="token">
|
||||
/// Cancellation token.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Calibration parameter lookup result.
|
||||
/// </returns>
|
||||
public async Task<UdsPreAdjustmentCalibrationParamsResult> GetPreAdjustmentCalibrationParamsAsync(
|
||||
int meterSize,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
EnsureReader();
|
||||
|
||||
if (meterSize < 0)
|
||||
throw new ArgumentException(
|
||||
"Meter size must not be negative.",
|
||||
nameof(meterSize));
|
||||
|
||||
try
|
||||
{
|
||||
GciUDSRPublicModels.DataQuery query = CreatePreAdjustmentCalibrationParamsQuery(meterSize);
|
||||
|
||||
object data = await _gciEngine.gciExternalInterface.ReadPreAdjustmentCalibrationParamsAsync(query, token);
|
||||
|
||||
Dictionary<string, UInt32> calibrationParams =
|
||||
ExtractPreAdjustmentCalibrationParams(data);
|
||||
|
||||
return new UdsPreAdjustmentCalibrationParamsResult
|
||||
{
|
||||
Success = calibrationParams != null &&
|
||||
calibrationParams.Count > 0,
|
||||
MeterSize = meterSize,
|
||||
CalibrationParams = calibrationParams,
|
||||
Message = calibrationParams != null &&
|
||||
calibrationParams.Count > 0
|
||||
? "Pre-adjustment calibration parameters found."
|
||||
: "Pre-adjustment calibration parameters were not found."
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error(
|
||||
"GetPreAdjustmentCalibrationParamsAsync failed.",
|
||||
ex);
|
||||
|
||||
return new UdsPreAdjustmentCalibrationParamsResult
|
||||
{
|
||||
Success = false,
|
||||
MeterSize = meterSize,
|
||||
CalibrationParams = null,
|
||||
Message = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private GciUDSRPublicModels.DataQuery CreatePreAdjustmentCalibrationParamsQuery(
|
||||
int meterSize)
|
||||
{
|
||||
GciUDSRPublicModels.DataQuery query =
|
||||
new GciUDSRPublicModels.DataQuery();
|
||||
|
||||
query.QueryParams.Add(
|
||||
meterSize.ToString());
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
private Dictionary<string, UInt32> ExtractPreAdjustmentCalibrationParams(
|
||||
object data)
|
||||
{
|
||||
Dictionary<string, UInt32> result =
|
||||
new Dictionary<string, UInt32>();
|
||||
|
||||
if (data == null)
|
||||
return result;
|
||||
|
||||
if (data is Dictionary<string, UInt32> directDictionary)
|
||||
return directDictionary;
|
||||
|
||||
if (data is Dictionary<string, object> objectDictionary)
|
||||
{
|
||||
foreach (var item in objectDictionary)
|
||||
{
|
||||
if (UInt32.TryParse(
|
||||
item.Value?.ToString(),
|
||||
out UInt32 value))
|
||||
{
|
||||
result[item.Key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads password from UniDataStorageReader using PCB ID with retry support.
|
||||
@ -1288,7 +1416,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
///
|
||||
/// GetPasswordWithRetryAsync()
|
||||
/// -> RetryWorker.RunWithRetryAsync()
|
||||
/// -> GetPasswordAsync()
|
||||
/// -> ReadMeterLoginPasswordAsync()
|
||||
/// -> UniDataStorageReader
|
||||
///
|
||||
/// Returns:
|
||||
@ -1310,7 +1438,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
r => r.Success,
|
||||
msg => log.Info(msg),
|
||||
(msg, result) => log.InfoFormat("{0}: {1}", msg, result),
|
||||
$"GetPasswordAsync pcb {pcbId}",
|
||||
$"ReadMeterLoginPasswordAsync pcb {pcbId}",
|
||||
maxAttempts: 5,
|
||||
delayMs: 5,
|
||||
timeoutMs: 30000);
|
||||
@ -1362,7 +1490,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
/// -> RetryWorker.RunWithRetryAsync()
|
||||
/// -> ConnectAsync()
|
||||
/// -> GetPcbIdAsync()
|
||||
/// -> GetPasswordAsync()
|
||||
/// -> ReadMeterLoginPasswordAsync()
|
||||
/// -> SetPasswordAsync()
|
||||
/// -> LoginAsync()
|
||||
///
|
||||
@ -1393,7 +1521,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
RetryWorker.EnsureSuccess(finalResult.PcbResult, $"GetPcbIdAsync slot {slotId}");
|
||||
|
||||
finalResult.PasswordResult = await GetPasswordWithRetryAsync(finalResult.PcbResult.Result.PcbId, token);
|
||||
RetryWorker.EnsureSuccess(finalResult.PasswordResult, $"GetPasswordAsync slot {slotId}");
|
||||
RetryWorker.EnsureSuccess(finalResult.PasswordResult, $"ReadMeterLoginPasswordAsync slot {slotId}");
|
||||
|
||||
finalResult.SetPasswordResult = await SetPasswordWithRetryAsync(slotId, finalResult.PasswordResult.Result.Password, token);
|
||||
RetryWorker.EnsureSuccess(finalResult.SetPasswordResult, $"SetPasswordAsync slot {slotId}");
|
||||
@ -1442,7 +1570,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
Name,
|
||||
operation);
|
||||
|
||||
PreAdjustmentInitializationResult result = gciExternalInterface.Preadjustment_Initialization(pp, mc);
|
||||
PreAdjustmentInitializationResult result = _gciEngine.gciExternalInterface.Preadjustment_Initialization(pp, mc);
|
||||
|
||||
log.InfoFormat(
|
||||
"{0}: {1} Finish. {2}",
|
||||
@ -1486,7 +1614,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
log.InfoFormat("{0}: {1} Start.", Name, operation);
|
||||
|
||||
PreadjustmentDetectResult result =
|
||||
await gciExternalInterface
|
||||
await _gciEngine.gciExternalInterface
|
||||
.PreAdjustment_DetectAsync(selectedSlots, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@ -1512,6 +1640,36 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
}
|
||||
|
||||
public PreadjustmentDetectResult PreAdjustment_DetectDirect(
|
||||
IEnumerable<GciPublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_DetectDirect);
|
||||
|
||||
try
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
|
||||
log.InfoFormat("{0}: {1} Start.", Name, operation);
|
||||
|
||||
PreadjustmentDetectResult result = _gciEngine.gciExternalInterface.PreAdjustment_DetectDirect(selectedSlots, token);
|
||||
|
||||
log.InfoFormat("{0}: {1} Finish. {2}", Name, operation, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"{Name}: {operation} failed.", ex);
|
||||
|
||||
return new PreadjustmentDetectResult
|
||||
{
|
||||
Success = false,
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== PreAdjustment PREPARATION bridge ==================================
|
||||
@ -1533,7 +1691,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
slot);
|
||||
|
||||
PreAdjustmentProcessResult result =
|
||||
await gciExternalInterface
|
||||
await _gciEngine.gciExternalInterface
|
||||
.PreAdjustment_PreparationAsync(
|
||||
slot,
|
||||
token)
|
||||
@ -1563,6 +1721,35 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_PreparationDirect()
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_PreparationDirect);
|
||||
|
||||
try
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
|
||||
log.InfoFormat("{0}: {1} Start.", Name, operation);
|
||||
|
||||
PreAdjustmentProcessResult result = _gciEngine.gciExternalInterface.PreAdjustment_PreparationDirect();
|
||||
|
||||
log.InfoFormat("{0}: {1} Finish. {2}", Name, operation, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"{Name}: {operation} failed.", ex);
|
||||
|
||||
return new PreAdjustmentProcessResult
|
||||
{
|
||||
Success = false,
|
||||
ProcessName = "Preparation",
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== PreAdjustment AMPLITUDE TEST bridge ==================================
|
||||
@ -1584,7 +1771,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
slot);
|
||||
|
||||
PreAdjustmentProcessResult result =
|
||||
await gciExternalInterface
|
||||
await _gciEngine.gciExternalInterface
|
||||
.PreAdjustment_AmplitudeTestAsync(
|
||||
slot,
|
||||
token)
|
||||
@ -1614,6 +1801,35 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTestDirect()
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_AmplitudeTestDirect);
|
||||
|
||||
try
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
|
||||
log.InfoFormat("{0}: {1} Start.", Name, operation);
|
||||
|
||||
PreAdjustmentProcessResult result = _gciEngine.gciExternalInterface.PreAdjustment_AmplitudeTestDirect();
|
||||
|
||||
log.InfoFormat("{0}: {1} Finish. {2}", Name, operation, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"{Name}: {operation} failed.", ex);
|
||||
|
||||
return new PreAdjustmentProcessResult
|
||||
{
|
||||
Success = false,
|
||||
ProcessName = "AmplitudeTest",
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== PreAdjustment TEMPERATURE CALIBRATION bridge ==================================
|
||||
@ -1635,7 +1851,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
slot);
|
||||
|
||||
PreAdjustmentProcessResult result =
|
||||
await gciExternalInterface
|
||||
await _gciEngine.gciExternalInterface
|
||||
.PreAdjustment_TemperatureCalibrationAsync(
|
||||
slot,
|
||||
token)
|
||||
@ -1665,6 +1881,62 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
}
|
||||
|
||||
public bool PreAdjustment_PushTemperature(
|
||||
double temperature)
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_PushTemperature);
|
||||
|
||||
try
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
|
||||
log.InfoFormat(
|
||||
"{0}: {1}. Temperature={2}",
|
||||
Name,
|
||||
operation,
|
||||
temperature);
|
||||
|
||||
return _gciEngine.gciExternalInterface.PreAdjustment_PushTemperature(temperature);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error(
|
||||
string.Format("{0}: {1} failed.", Name, operation),
|
||||
ex);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect()
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_TemperatureCalibrationDirect);
|
||||
|
||||
try
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
|
||||
log.InfoFormat("{0}: {1} Start.", Name, operation);
|
||||
|
||||
PreAdjustmentProcessResult result = _gciEngine.gciExternalInterface.PreAdjustment_TemperatureCalibrationDirect();
|
||||
|
||||
log.InfoFormat("{0}: {1} Finish. {2}", Name, operation, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"{Name}: {operation} failed.", ex);
|
||||
|
||||
return new PreAdjustmentProcessResult
|
||||
{
|
||||
Success = false,
|
||||
ProcessName = "TemperatureCalibration",
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== PreAdjustment OFFSET TEST bridge ==================================
|
||||
@ -1686,7 +1958,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
slot);
|
||||
|
||||
PreAdjustmentProcessResult result =
|
||||
await gciExternalInterface
|
||||
await _gciEngine.gciExternalInterface
|
||||
.PreAdjustment_OffsetTestAsync(
|
||||
slot,
|
||||
token)
|
||||
@ -1716,6 +1988,35 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_OffsetTestDirect()
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_OffsetTestDirect);
|
||||
|
||||
try
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
|
||||
log.InfoFormat("{0}: {1} Start.", Name, operation);
|
||||
|
||||
PreAdjustmentProcessResult result = _gciEngine.gciExternalInterface.PreAdjustment_OffsetTestDirect();
|
||||
|
||||
log.InfoFormat("{0}: {1} Finish. {2}", Name, operation, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"{Name}: {operation} failed.", ex);
|
||||
|
||||
return new PreAdjustmentProcessResult
|
||||
{
|
||||
Success = false,
|
||||
ProcessName = "OffsetTest",
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================================== PreAdjustment COMPLETION bridge ==================================
|
||||
@ -1737,7 +2038,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
slot);
|
||||
|
||||
PreAdjustmentProcessResult result =
|
||||
await gciExternalInterface
|
||||
await _gciEngine.gciExternalInterface
|
||||
.PreAdjustment_CompletionAsync(
|
||||
slot,
|
||||
token)
|
||||
@ -1767,12 +2068,41 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
}
|
||||
}
|
||||
|
||||
public PreAdjustmentProcessResult PreAdjustment_CompletionDirect()
|
||||
{
|
||||
const string operation = nameof(PreAdjustment_CompletionDirect);
|
||||
|
||||
try
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
|
||||
log.InfoFormat("{0}: {1} Start.", Name, operation);
|
||||
|
||||
PreAdjustmentProcessResult result = _gciEngine.gciExternalInterface.PreAdjustment_CompletionDirect();
|
||||
|
||||
log.InfoFormat("{0}: {1} Finish. {2}", Name, operation, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"{Name}: {operation} failed.", ex);
|
||||
|
||||
return new PreAdjustmentProcessResult
|
||||
{
|
||||
Success = false,
|
||||
ProcessName = "Completion",
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ======================================= Helpers =======================================
|
||||
private UDSRPublicModels.DataQuery CreatePasswordQuery(string pcbId)
|
||||
private GciUDSRPublicModels.DataQuery CreatePasswordQuery(string pcbId)
|
||||
{
|
||||
var query = new UDSRPublicModels.DataQuery();
|
||||
var query = new GciUDSRPublicModels.DataQuery();
|
||||
query.QueryParams.Add(pcbId);
|
||||
return query;
|
||||
}
|
||||
@ -1807,7 +2137,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
public List<string> GetAllRegisterNames()
|
||||
{
|
||||
EnsureExternalInterface();
|
||||
return gciExternalInterface.GetAllRegisterNames();
|
||||
return _gciEngine.gciExternalInterface.GetAllRegisterNames();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,18 +31,18 @@
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.showGciBridgeGUIButton = new System.Windows.Forms.Button();
|
||||
this.showGciGuiButton = new System.Windows.Forms.Button();
|
||||
this.readerNameLabel = new System.Windows.Forms.Label();
|
||||
this.readerNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.writerNameLabel = new System.Windows.Forms.Label();
|
||||
this.writerNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.externalTypeNameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.externalTypeNameLabel = new System.Windows.Forms.Label();
|
||||
this.enableGuiCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.enableExternalCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.showGuiOnInitializeCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.externalTypeNameLabel = new System.Windows.Forms.Label();
|
||||
this.externalTypeNameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.showGciBridgeGUIButton = new System.Windows.Forms.Button();
|
||||
this.showGciGuiButton = new System.Windows.Forms.Button();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
@ -72,6 +72,37 @@
|
||||
this.nameTextBox.Size = new System.Drawing.Size(290, 20);
|
||||
this.nameTextBox.TabIndex = 2;
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.showGciBridgeGUIButton);
|
||||
this.groupBox1.Controls.Add(this.showGciGuiButton);
|
||||
this.groupBox1.Location = new System.Drawing.Point(31, 241);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(573, 60);
|
||||
this.groupBox1.TabIndex = 12;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Diagnostic GUI";
|
||||
//
|
||||
// showGciBridgeGUIButton
|
||||
//
|
||||
this.showGciBridgeGUIButton.Location = new System.Drawing.Point(311, 19);
|
||||
this.showGciBridgeGUIButton.Name = "showGciBridgeGUIButton";
|
||||
this.showGciBridgeGUIButton.Size = new System.Drawing.Size(134, 28);
|
||||
this.showGciBridgeGUIButton.TabIndex = 2;
|
||||
this.showGciBridgeGUIButton.Text = "Show GciBridge GUI";
|
||||
this.showGciBridgeGUIButton.UseVisualStyleBackColor = true;
|
||||
this.showGciBridgeGUIButton.Click += new System.EventHandler(this.showGciBridgeGUIButton_Click);
|
||||
//
|
||||
// showGciGuiButton
|
||||
//
|
||||
this.showGciGuiButton.Location = new System.Drawing.Point(451, 19);
|
||||
this.showGciGuiButton.Name = "showGciGuiButton";
|
||||
this.showGciGuiButton.Size = new System.Drawing.Size(107, 28);
|
||||
this.showGciGuiButton.TabIndex = 1;
|
||||
this.showGciGuiButton.Text = "Show GCI GUI";
|
||||
this.showGciGuiButton.UseVisualStyleBackColor = true;
|
||||
this.showGciGuiButton.Click += new System.EventHandler(this.showGuiButton_Click);
|
||||
//
|
||||
// readerNameLabel
|
||||
//
|
||||
this.readerNameLabel.AutoSize = true;
|
||||
@ -108,6 +139,23 @@
|
||||
this.writerNameComboBox.Size = new System.Drawing.Size(465, 21);
|
||||
this.writerNameComboBox.TabIndex = 6;
|
||||
//
|
||||
// externalTypeNameTextBox
|
||||
//
|
||||
this.externalTypeNameTextBox.Enabled = false;
|
||||
this.externalTypeNameTextBox.Location = new System.Drawing.Point(139, 202);
|
||||
this.externalTypeNameTextBox.Name = "externalTypeNameTextBox";
|
||||
this.externalTypeNameTextBox.Size = new System.Drawing.Size(290, 20);
|
||||
this.externalTypeNameTextBox.TabIndex = 11;
|
||||
//
|
||||
// externalTypeNameLabel
|
||||
//
|
||||
this.externalTypeNameLabel.AutoSize = true;
|
||||
this.externalTypeNameLabel.Location = new System.Drawing.Point(28, 205);
|
||||
this.externalTypeNameLabel.Name = "externalTypeNameLabel";
|
||||
this.externalTypeNameLabel.Size = new System.Drawing.Size(105, 13);
|
||||
this.externalTypeNameLabel.TabIndex = 10;
|
||||
this.externalTypeNameLabel.Text = "External type / name";
|
||||
//
|
||||
// enableGuiCheckBox
|
||||
//
|
||||
this.enableGuiCheckBox.AutoSize = true;
|
||||
@ -141,54 +189,6 @@
|
||||
this.showGuiOnInitializeCheckBox.Text = "Show GUI on initialize";
|
||||
this.showGuiOnInitializeCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// externalTypeNameLabel
|
||||
//
|
||||
this.externalTypeNameLabel.AutoSize = true;
|
||||
this.externalTypeNameLabel.Location = new System.Drawing.Point(28, 205);
|
||||
this.externalTypeNameLabel.Name = "externalTypeNameLabel";
|
||||
this.externalTypeNameLabel.Size = new System.Drawing.Size(105, 13);
|
||||
this.externalTypeNameLabel.TabIndex = 10;
|
||||
this.externalTypeNameLabel.Text = "External type / name";
|
||||
//
|
||||
// externalTypeNameTextBox
|
||||
//
|
||||
this.externalTypeNameTextBox.Enabled = false;
|
||||
this.externalTypeNameTextBox.Location = new System.Drawing.Point(139, 202);
|
||||
this.externalTypeNameTextBox.Name = "externalTypeNameTextBox";
|
||||
this.externalTypeNameTextBox.Size = new System.Drawing.Size(290, 20);
|
||||
this.externalTypeNameTextBox.TabIndex = 11;
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.showGciBridgeGUIButton);
|
||||
this.groupBox1.Controls.Add(this.showGciGuiButton);
|
||||
this.groupBox1.Location = new System.Drawing.Point(31, 241);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(573, 60);
|
||||
this.groupBox1.TabIndex = 12;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Diagnostic GUI";
|
||||
//
|
||||
// showGciBridgeGUIButton
|
||||
//
|
||||
this.showGciBridgeGUIButton.Location = new System.Drawing.Point(311, 19);
|
||||
this.showGciBridgeGUIButton.Name = "showGciBridgeGUIButton";
|
||||
this.showGciBridgeGUIButton.Size = new System.Drawing.Size(134, 28);
|
||||
this.showGciBridgeGUIButton.TabIndex = 2;
|
||||
this.showGciBridgeGUIButton.Text = "Show GciBridge GUI";
|
||||
this.showGciBridgeGUIButton.UseVisualStyleBackColor = true;
|
||||
this.showGciBridgeGUIButton.Click += new System.EventHandler(this.showGciBridgeGUIButton_Click);
|
||||
//
|
||||
// showGciGuiButton
|
||||
//
|
||||
this.showGciGuiButton.Location = new System.Drawing.Point(451, 19);
|
||||
this.showGciGuiButton.Name = "showGciGuiButton";
|
||||
this.showGciGuiButton.Size = new System.Drawing.Size(107, 28);
|
||||
this.showGciGuiButton.TabIndex = 1;
|
||||
this.showGciGuiButton.Text = "Show GCI GUI";
|
||||
this.showGciGuiButton.UseVisualStyleBackColor = true;
|
||||
this.showGciGuiButton.Click += new System.EventHandler(this.showGuiButton_Click);
|
||||
//
|
||||
// GciBridgeCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
@ -220,17 +220,17 @@
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Button showGciGuiButton;
|
||||
private System.Windows.Forms.Button showGciBridgeGUIButton;
|
||||
private System.Windows.Forms.Label readerNameLabel;
|
||||
private System.Windows.Forms.ComboBox readerNameComboBox;
|
||||
private System.Windows.Forms.Label writerNameLabel;
|
||||
private System.Windows.Forms.ComboBox writerNameComboBox;
|
||||
private System.Windows.Forms.TextBox externalTypeNameTextBox;
|
||||
private System.Windows.Forms.Label externalTypeNameLabel;
|
||||
private System.Windows.Forms.CheckBox enableGuiCheckBox;
|
||||
private System.Windows.Forms.CheckBox enableExternalCheckBox;
|
||||
private System.Windows.Forms.CheckBox showGuiOnInitializeCheckBox;
|
||||
private System.Windows.Forms.Label externalTypeNameLabel;
|
||||
private System.Windows.Forms.TextBox externalTypeNameTextBox;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Button showGciGuiButton;
|
||||
private System.Windows.Forms.Button showGciBridgeGUIButton;
|
||||
}
|
||||
}
|
||||
@ -95,6 +95,36 @@ namespace TBF.Rig.BridgeComponents.GciBridge.Interfaces
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents result of pre-adjustment calibration
|
||||
/// parameter lookup.
|
||||
///
|
||||
/// Parameters are returned as key/value pairs:
|
||||
///
|
||||
/// Key:
|
||||
/// Calibration parameter name
|
||||
///
|
||||
/// Value:
|
||||
/// Calibration parameter value
|
||||
/// </summary>
|
||||
public class UdsPreAdjustmentCalibrationParamsResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int MeterSize { get; set; }
|
||||
public Dictionary<string, UInt32> CalibrationParams { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (CalibrationParams == null || CalibrationParams.Count == 0)
|
||||
{
|
||||
return $"Success={Success}, MeterSize={MeterSize}, Message={Message}";
|
||||
}
|
||||
|
||||
return $"Success={Success}, MeterSize={MeterSize}, Params={CalibrationParams.Count}, Message={Message}";
|
||||
}
|
||||
}
|
||||
|
||||
public class GciFullLoginResult
|
||||
{
|
||||
public int SlotId { get; set; }
|
||||
|
||||
481
TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterGridManager.cs
Normal file
481
TBF/Rig/BridgeComponents/GciBridge/UI/Debug/MeterGridManager.cs
Normal file
@ -0,0 +1,481 @@
|
||||
using Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using PublicModels = GenesisCordonelInterface.API.PublicModels;
|
||||
|
||||
namespace TBF.Rig.BridgeComponents.GciBridge.UI.Grid
|
||||
{
|
||||
public class MeterGridManager
|
||||
{
|
||||
private readonly DataGridView grid;
|
||||
|
||||
public MeterGridManager(DataGridView grid)
|
||||
{
|
||||
this.grid = grid ?? throw new ArgumentNullException(nameof(grid));
|
||||
EnableDoubleBuffering(grid);
|
||||
}
|
||||
|
||||
public void Init(List<string> comPorts)
|
||||
{
|
||||
grid.SuspendLayout();
|
||||
|
||||
try
|
||||
{
|
||||
grid.AutoGenerateColumns = false;
|
||||
grid.Columns.Clear();
|
||||
|
||||
grid.AllowUserToAddRows = false;
|
||||
grid.AllowUserToDeleteRows = false;
|
||||
grid.RowHeadersVisible = true;
|
||||
|
||||
CreateColumns(comPorts);
|
||||
ConfigureReadOnlyColumns();
|
||||
ConfigureSelection();
|
||||
}
|
||||
finally
|
||||
{
|
||||
grid.ResumeLayout();
|
||||
}
|
||||
|
||||
grid.Focus();
|
||||
grid.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
|
||||
}
|
||||
|
||||
private void CreateColumns(List<string> comPorts)
|
||||
{
|
||||
var configs = MeterGridConfigProvider
|
||||
.GetDefault()
|
||||
.OrderBy(x => x.DisplayIndex);
|
||||
|
||||
foreach (var config in configs)
|
||||
{
|
||||
DataGridViewColumn column;
|
||||
|
||||
switch (config.ColumnType)
|
||||
{
|
||||
case MeterGridConfigProvider.MeterGridColumnType.CheckBox:
|
||||
column = new DataGridViewCheckBoxColumn();
|
||||
break;
|
||||
|
||||
default:
|
||||
column = new DataGridViewTextBoxColumn();
|
||||
break;
|
||||
}
|
||||
|
||||
column.Name = config.Name;
|
||||
column.HeaderText = config.HeaderText;
|
||||
column.Width = config.Width;
|
||||
column.ReadOnly = config.ReadOnly;
|
||||
column.DisplayIndex = config.DisplayIndex;
|
||||
|
||||
grid.Columns.Add(column);
|
||||
}
|
||||
|
||||
grid.Columns.Add(CreateComPortColumn("RequestPort", "RequestPort", comPorts));
|
||||
grid.Columns.Add(CreateRequestPortTypeColumn());
|
||||
grid.Columns.Add(CreateComPortColumn("StreamingPort", "StreamingPort", comPorts));
|
||||
|
||||
grid.Columns.Add(CreateButtonColumn("DetectRequest", "DetectRequest", "..."));
|
||||
grid.Columns.Add(CreateButtonColumn("DetectStreaming", "DetectStreaming", "..."));
|
||||
}
|
||||
|
||||
private void ConfigureReadOnlyColumns()
|
||||
{
|
||||
foreach (DataGridViewColumn col in grid.Columns)
|
||||
{
|
||||
col.ReadOnly =
|
||||
col.Name != "Selected" &&
|
||||
col.Name != "RequestPort" &&
|
||||
col.Name != "RequestPortType" &&
|
||||
col.Name != "StreamingPort" &&
|
||||
col.Name != "DetectRequest" &&
|
||||
col.Name != "DetectStreaming";
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureSelection()
|
||||
{
|
||||
grid.MultiSelect = true;
|
||||
grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||
|
||||
grid.CellContentClick -= Grid_CellContentClick;
|
||||
grid.CellContentClick += Grid_CellContentClick;
|
||||
|
||||
grid.CurrentCellDirtyStateChanged -= Grid_CurrentCellDirtyStateChanged;
|
||||
grid.CurrentCellDirtyStateChanged += Grid_CurrentCellDirtyStateChanged;
|
||||
}
|
||||
|
||||
public void UpdateComPortItems(List<string> comPorts)
|
||||
{
|
||||
UpdateComPortColumnItems("RequestPort", comPorts);
|
||||
UpdateComPortColumnItems("StreamingPort", comPorts);
|
||||
}
|
||||
|
||||
public void Update(List<PublicModels.MeterBatchDebugStatus> meters)
|
||||
{
|
||||
grid.SuspendLayout();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var meter in meters)
|
||||
{
|
||||
var row = FindOrCreateRow(meter.Slot);
|
||||
|
||||
SetCell(row, "Slot", meter.Slot);
|
||||
SetCell(row, "Selected", meter.Selected);
|
||||
SetCell(row, "PcbId", meter.PcbId);
|
||||
SetCell(row, "IsConnected", meter.IsConnected);
|
||||
SetCell(row, "IsLoggedOn", meter.IsLoggedOn);
|
||||
SetCell(row, "RequestPort", meter.RequestPort);
|
||||
SetCell(row, "RequestPortType", NormalizeRequestPortType(meter.RequestPortType));
|
||||
SetCell(row, "StreamingPort", meter.StreamingPort);
|
||||
SetCell(row, "FwVersion", meter.FwVersion);
|
||||
SetCell(row, "InterfaceVersion", meter.InterfaceVersion);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
grid.ResumeLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSlots(List<PublicModels.GciSlotInfo> slots)
|
||||
{
|
||||
grid.SuspendLayout();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var slot in slots)
|
||||
{
|
||||
var row = FindOrCreateRow(slot.SlotId);
|
||||
|
||||
SetCell(row, "Slot", slot.SlotId);
|
||||
SetCell(row, "PcbId", slot.PcbId);
|
||||
SetCell(row, "RequestPort", slot.RequestPort == null ? "" : slot.RequestPort.PortName);
|
||||
SetCell(row, "RequestPortType", MapRequestPortTypeBack(slot.RequestPort == null ? null : slot.RequestPort.Type));
|
||||
SetCell(row, "StreamingPort", slot.StreamingPort == null ? "" : slot.StreamingPort.PortName);
|
||||
SetCell(row, "IsConnected", false);
|
||||
SetCell(row, "IsLoggedOn", false);
|
||||
SetCell(row, "FwVersion", "");
|
||||
SetCell(row, "InterfaceVersion", "");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
grid.ResumeLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEmptySlotRow()
|
||||
{
|
||||
AddSlotRow(GetNextSlotId());
|
||||
}
|
||||
|
||||
public void AddSlotRow()
|
||||
{
|
||||
AddSlotRow(GetNextSlotId());
|
||||
}
|
||||
|
||||
public void AddSlotRow(int slotId)
|
||||
{
|
||||
if (ContainsSlot(slotId))
|
||||
throw new Exception($"Slot {slotId} already exists.");
|
||||
|
||||
int idx = grid.Rows.Add();
|
||||
var row = grid.Rows[idx];
|
||||
|
||||
SetCell(row, "Slot", slotId);
|
||||
SetCell(row, "Selected", false);
|
||||
SetCell(row, "RequestPort", "");
|
||||
SetCell(row, "RequestPortType", "IRDA");
|
||||
SetCell(row, "StreamingPort", "");
|
||||
SetCell(row, "PcbId", "");
|
||||
SetCell(row, "IsConnected", false);
|
||||
SetCell(row, "IsLoggedOn", false);
|
||||
SetCell(row, "FwVersion", "");
|
||||
SetCell(row, "InterfaceVersion", "");
|
||||
}
|
||||
|
||||
public List<PublicModels.MeterBatchDebugStatus> GetGridData()
|
||||
{
|
||||
var list = new List<PublicModels.MeterBatchDebugStatus>();
|
||||
|
||||
foreach (DataGridViewRow row in grid.Rows)
|
||||
{
|
||||
if (row.IsNewRow)
|
||||
continue;
|
||||
|
||||
if (row.Cells["Slot"].Value == null)
|
||||
continue;
|
||||
|
||||
list.Add(new PublicModels.MeterBatchDebugStatus
|
||||
{
|
||||
Slot = Convert.ToInt32(row.Cells["Slot"].Value),
|
||||
Selected = GetBool(row, "Selected"),
|
||||
PcbId = GetString(row, "PcbId"),
|
||||
IsConnected = GetBool(row, "IsConnected"),
|
||||
IsLoggedOn = GetBool(row, "IsLoggedOn"),
|
||||
RequestPort = GetString(row, "RequestPort"),
|
||||
RequestPortType = NormalizeRequestPortType(GetString(row, "RequestPortType")),
|
||||
StreamingPort = GetString(row, "StreamingPort"),
|
||||
FwVersion = GetString(row, "FwVersion"),
|
||||
InterfaceVersion = GetString(row, "InterfaceVersion")
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<PublicModels.MeterBatchDebugStatus> GetSelectedGridData()
|
||||
{
|
||||
return GetGridData()
|
||||
.Where(x => x.Selected)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public int GetSlotFromRow(int rowIndex)
|
||||
{
|
||||
if (rowIndex < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(rowIndex));
|
||||
|
||||
return Convert.ToInt32(grid.Rows[rowIndex].Cells["Slot"].Value);
|
||||
}
|
||||
|
||||
public string GetColumnName(int columnIndex)
|
||||
{
|
||||
return grid.Columns[columnIndex].Name;
|
||||
}
|
||||
|
||||
public void ClearSlots()
|
||||
{
|
||||
grid.Rows.Clear();
|
||||
}
|
||||
|
||||
public int GetNextSlotId()
|
||||
{
|
||||
var existingSlots = grid.Rows
|
||||
.Cast<DataGridViewRow>()
|
||||
.Where(r => !r.IsNewRow)
|
||||
.Where(r => r.Cells["Slot"].Value != null)
|
||||
.Select(r => Convert.ToInt32(r.Cells["Slot"].Value))
|
||||
.ToList();
|
||||
|
||||
if (existingSlots.Count == 0)
|
||||
return 1;
|
||||
|
||||
return existingSlots.Max() + 1;
|
||||
}
|
||||
|
||||
private bool ContainsSlot(int slotId)
|
||||
{
|
||||
return grid.Rows
|
||||
.Cast<DataGridViewRow>()
|
||||
.Any(r =>
|
||||
!r.IsNewRow &&
|
||||
r.Cells["Slot"].Value != null &&
|
||||
Convert.ToInt32(r.Cells["Slot"].Value) == slotId);
|
||||
}
|
||||
|
||||
private DataGridViewRow FindOrCreateRow(int slot)
|
||||
{
|
||||
foreach (DataGridViewRow row in grid.Rows)
|
||||
{
|
||||
if (!row.IsNewRow &&
|
||||
row.Cells["Slot"].Value != null &&
|
||||
Convert.ToInt32(row.Cells["Slot"].Value) == slot)
|
||||
{
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
int idx = grid.Rows.Add();
|
||||
var newRow = grid.Rows[idx];
|
||||
newRow.Cells["Slot"].Value = slot;
|
||||
return newRow;
|
||||
}
|
||||
|
||||
private void SetCell(DataGridViewRow row, string colName, object value)
|
||||
{
|
||||
if (!grid.Columns.Contains(colName))
|
||||
return;
|
||||
|
||||
if (value == null)
|
||||
value = "";
|
||||
|
||||
if (colName == "RequestPortType")
|
||||
value = NormalizeRequestPortType(Convert.ToString(value));
|
||||
|
||||
var cell = row.Cells[colName];
|
||||
|
||||
if (!Equals(cell.Value, value))
|
||||
cell.Value = value;
|
||||
}
|
||||
|
||||
private string GetString(DataGridViewRow row, string colName)
|
||||
{
|
||||
if (!grid.Columns.Contains(colName))
|
||||
return "";
|
||||
|
||||
return Convert.ToString(row.Cells[colName].Value);
|
||||
}
|
||||
|
||||
private bool GetBool(DataGridViewRow row, string colName)
|
||||
{
|
||||
if (!grid.Columns.Contains(colName))
|
||||
return false;
|
||||
|
||||
if (row.Cells[colName].Value == null)
|
||||
return false;
|
||||
|
||||
return Convert.ToBoolean(row.Cells[colName].Value);
|
||||
}
|
||||
|
||||
private DataGridViewComboBoxColumn CreateComPortColumn(
|
||||
string name,
|
||||
string headerText,
|
||||
List<string> comPorts)
|
||||
{
|
||||
return new DataGridViewComboBoxColumn
|
||||
{
|
||||
Name = name,
|
||||
HeaderText = headerText,
|
||||
DataSource = new List<string>(comPorts ?? new List<string>()),
|
||||
FlatStyle = FlatStyle.Flat,
|
||||
DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
|
||||
};
|
||||
}
|
||||
|
||||
private DataGridViewComboBoxColumn CreateRequestPortTypeColumn()
|
||||
{
|
||||
return new DataGridViewComboBoxColumn
|
||||
{
|
||||
Name = "RequestPortType",
|
||||
HeaderText = "RequestPortType",
|
||||
DataSource = new List<string> { "", "IRDA", "UART", "RFID" },
|
||||
FlatStyle = FlatStyle.Flat,
|
||||
DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
|
||||
};
|
||||
}
|
||||
|
||||
private DataGridViewButtonColumn CreateButtonColumn(
|
||||
string name,
|
||||
string headerText,
|
||||
string text)
|
||||
{
|
||||
return new DataGridViewButtonColumn
|
||||
{
|
||||
Name = name,
|
||||
HeaderText = headerText,
|
||||
Text = text,
|
||||
UseColumnTextForButtonValue = true
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateComPortColumnItems(string columnName, List<string> comPorts)
|
||||
{
|
||||
var col = grid.Columns[columnName] as DataGridViewComboBoxColumn;
|
||||
if (col == null)
|
||||
return;
|
||||
|
||||
col.DataSource = null;
|
||||
col.DataSource = new List<string>(comPorts ?? new List<string>());
|
||||
}
|
||||
|
||||
private string NormalizeRequestPortType(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return "";
|
||||
|
||||
string normalized = value.Trim();
|
||||
|
||||
if (normalized.Equals("RFID", StringComparison.OrdinalIgnoreCase) ||
|
||||
normalized.IndexOf("RfidSerialPort", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
return "RFID";
|
||||
|
||||
if (normalized.Equals("UART", StringComparison.OrdinalIgnoreCase) ||
|
||||
normalized.IndexOf("UartSerialPort", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
return "UART";
|
||||
|
||||
if (normalized.Equals("IRDA", StringComparison.OrdinalIgnoreCase) ||
|
||||
normalized.Equals("IrDA", StringComparison.OrdinalIgnoreCase) ||
|
||||
normalized.IndexOf("IrdaSerialPort", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
return "IRDA";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private void EnableDoubleBuffering(DataGridView dgv)
|
||||
{
|
||||
typeof(DataGridView)
|
||||
.GetProperty(
|
||||
"DoubleBuffered",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?.SetValue(dgv, true, null);
|
||||
}
|
||||
|
||||
private void Grid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (grid.IsCurrentCellDirty)
|
||||
{
|
||||
grid.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
if (e.RowIndex < 0)
|
||||
return;
|
||||
|
||||
if (grid.Columns[e.ColumnIndex].Name != "Selected")
|
||||
return;
|
||||
|
||||
bool clickedValue = Convert.ToBoolean(
|
||||
grid.Rows[e.RowIndex].Cells["Selected"].Value);
|
||||
|
||||
foreach (DataGridViewRow row in grid.SelectedRows)
|
||||
{
|
||||
if (row.Index == e.RowIndex)
|
||||
continue;
|
||||
|
||||
row.Cells["Selected"].Value = clickedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -316,7 +316,7 @@
|
||||
//
|
||||
this.splitWorkArea.Panel2.Controls.Add(this.rtbMainLog);
|
||||
this.splitWorkArea.Size = new System.Drawing.Size(700, 320);
|
||||
this.splitWorkArea.SplitterDistance = 233;
|
||||
this.splitWorkArea.SplitterDistance = 320;
|
||||
this.splitWorkArea.SplitterWidth = 6;
|
||||
this.splitWorkArea.TabIndex = 0;
|
||||
//
|
||||
@ -326,7 +326,7 @@
|
||||
this.pnlGciViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pnlGciViewHost.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlGciViewHost.Name = "pnlGciViewHost";
|
||||
this.pnlGciViewHost.Size = new System.Drawing.Size(233, 320);
|
||||
this.pnlGciViewHost.Size = new System.Drawing.Size(320, 320);
|
||||
this.pnlGciViewHost.TabIndex = 0;
|
||||
//
|
||||
// rtbMainLog
|
||||
@ -336,7 +336,7 @@
|
||||
this.rtbMainLog.Location = new System.Drawing.Point(0, 0);
|
||||
this.rtbMainLog.Name = "rtbMainLog";
|
||||
this.rtbMainLog.ReadOnly = true;
|
||||
this.rtbMainLog.Size = new System.Drawing.Size(461, 320);
|
||||
this.rtbMainLog.Size = new System.Drawing.Size(374, 320);
|
||||
this.rtbMainLog.TabIndex = 0;
|
||||
this.rtbMainLog.Text = "";
|
||||
//
|
||||
|
||||
@ -55,7 +55,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI
|
||||
_mainForm = mainform;
|
||||
_bridge = bridge;
|
||||
_gciApi = bridge.gciExternalInterface;
|
||||
_laatzenApi = _bridge.gciExternalInterface._innerMeterAPI;
|
||||
_laatzenApi = bridge._gciEngine.gciExternalInterface._innerMeterAPI;
|
||||
InitializeComponent();
|
||||
InitializeDebugPanels();
|
||||
//InitializeWorkerDebugPanel();
|
||||
|
||||
@ -90,7 +90,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
int slot = item.Key;
|
||||
string pcbId = item.Value;
|
||||
|
||||
//var result = await _bridge.GetPasswordAsync(pcbId, token);
|
||||
//var result = await _bridge.ReadMeterLoginPasswordAsync(pcbId, token);
|
||||
var result = await _bridge.GetPasswordWithRetryAsync(pcbId, token);
|
||||
|
||||
LogResult($"UDSR/GetPassword slot {slot}, PCB={pcbId}", result);
|
||||
|
||||
@ -24,6 +24,11 @@
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.grpSlots = new System.Windows.Forms.GroupBox();
|
||||
this.pushTestBenchTempButton = new System.Windows.Forms.Button();
|
||||
this.pushedTestBenchTempTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label8 = new System.Windows.Forms.Label();
|
||||
this.cb_Metersize = new System.Windows.Forms.ComboBox();
|
||||
this.l_SettingsPreparationMetersize = new System.Windows.Forms.Label();
|
||||
this.label7 = new System.Windows.Forms.Label();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
@ -40,13 +45,14 @@
|
||||
this.amplitudeTestActionButton = new System.Windows.Forms.Button();
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
this.txtLog = new System.Windows.Forms.TextBox();
|
||||
this.cb_Metersize = new System.Windows.Forms.ComboBox();
|
||||
this.l_SettingsPreparationMetersize = new System.Windows.Forms.Label();
|
||||
this.grpSlots.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// grpSlots
|
||||
//
|
||||
this.grpSlots.Controls.Add(this.pushTestBenchTempButton);
|
||||
this.grpSlots.Controls.Add(this.pushedTestBenchTempTextBox);
|
||||
this.grpSlots.Controls.Add(this.label8);
|
||||
this.grpSlots.Controls.Add(this.cb_Metersize);
|
||||
this.grpSlots.Controls.Add(this.l_SettingsPreparationMetersize);
|
||||
this.grpSlots.Controls.Add(this.label7);
|
||||
@ -71,6 +77,50 @@
|
||||
this.grpSlots.Text = "Slots by selection in the table";
|
||||
this.grpSlots.Enter += new System.EventHandler(this.grpSlots_Enter);
|
||||
//
|
||||
// pushTestBenchTempButton
|
||||
//
|
||||
this.pushTestBenchTempButton.Location = new System.Drawing.Point(593, 186);
|
||||
this.pushTestBenchTempButton.Name = "pushTestBenchTempButton";
|
||||
this.pushTestBenchTempButton.Size = new System.Drawing.Size(81, 21);
|
||||
this.pushTestBenchTempButton.TabIndex = 121;
|
||||
this.pushTestBenchTempButton.Text = "Push temp";
|
||||
this.pushTestBenchTempButton.Click += new System.EventHandler(this.pushTestBenchTempButton_Click);
|
||||
//
|
||||
// pushedTestBenchTempTextBox
|
||||
//
|
||||
this.pushedTestBenchTempTextBox.Location = new System.Drawing.Point(550, 186);
|
||||
this.pushedTestBenchTempTextBox.Name = "pushedTestBenchTempTextBox";
|
||||
this.pushedTestBenchTempTextBox.Size = new System.Drawing.Size(37, 20);
|
||||
this.pushedTestBenchTempTextBox.TabIndex = 120;
|
||||
//
|
||||
// label8
|
||||
//
|
||||
this.label8.AutoSize = true;
|
||||
this.label8.Location = new System.Drawing.Point(440, 189);
|
||||
this.label8.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(105, 13);
|
||||
this.label8.TabIndex = 118;
|
||||
this.label8.Text = "Pushed temperature:";
|
||||
//
|
||||
// cb_Metersize
|
||||
//
|
||||
this.cb_Metersize.FormattingEnabled = true;
|
||||
this.cb_Metersize.Location = new System.Drawing.Point(74, 30);
|
||||
this.cb_Metersize.Name = "cb_Metersize";
|
||||
this.cb_Metersize.Size = new System.Drawing.Size(73, 21);
|
||||
this.cb_Metersize.TabIndex = 117;
|
||||
//
|
||||
// l_SettingsPreparationMetersize
|
||||
//
|
||||
this.l_SettingsPreparationMetersize.AutoSize = true;
|
||||
this.l_SettingsPreparationMetersize.Location = new System.Drawing.Point(14, 36);
|
||||
this.l_SettingsPreparationMetersize.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.l_SettingsPreparationMetersize.Name = "l_SettingsPreparationMetersize";
|
||||
this.l_SettingsPreparationMetersize.Size = new System.Drawing.Size(55, 13);
|
||||
this.l_SettingsPreparationMetersize.TabIndex = 116;
|
||||
this.l_SettingsPreparationMetersize.Text = "Metersize:";
|
||||
//
|
||||
// label7
|
||||
//
|
||||
this.label7.AutoSize = true;
|
||||
@ -157,6 +207,7 @@
|
||||
this.completionActionButton.Size = new System.Drawing.Size(150, 28);
|
||||
this.completionActionButton.TabIndex = 3;
|
||||
this.completionActionButton.Text = "Completition";
|
||||
this.completionActionButton.Click += new System.EventHandler(this.completionActionButton_Click);
|
||||
//
|
||||
// offsetTestActionButton
|
||||
//
|
||||
@ -165,6 +216,7 @@
|
||||
this.offsetTestActionButton.Size = new System.Drawing.Size(150, 28);
|
||||
this.offsetTestActionButton.TabIndex = 5;
|
||||
this.offsetTestActionButton.Text = "Offset test";
|
||||
this.offsetTestActionButton.Click += new System.EventHandler(this.offsetTestActionButton_Click);
|
||||
//
|
||||
// preparationActionButton
|
||||
//
|
||||
@ -191,7 +243,7 @@
|
||||
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);
|
||||
this.temperatureCalibrationActionButton.Click += new System.EventHandler(this.temperatureCalibrationActionButton_Click);
|
||||
//
|
||||
// amplitudeTestActionButton
|
||||
//
|
||||
@ -200,6 +252,7 @@
|
||||
this.amplitudeTestActionButton.Size = new System.Drawing.Size(150, 28);
|
||||
this.amplitudeTestActionButton.TabIndex = 18;
|
||||
this.amplitudeTestActionButton.Text = "Amplitude test";
|
||||
this.amplitudeTestActionButton.Click += new System.EventHandler(this.amplitudeTestActionButton_Click);
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
@ -225,24 +278,6 @@
|
||||
this.txtLog.TabIndex = 5;
|
||||
this.txtLog.WordWrap = false;
|
||||
//
|
||||
// cb_Metersize
|
||||
//
|
||||
this.cb_Metersize.FormattingEnabled = true;
|
||||
this.cb_Metersize.Location = new System.Drawing.Point(74, 30);
|
||||
this.cb_Metersize.Name = "cb_Metersize";
|
||||
this.cb_Metersize.Size = new System.Drawing.Size(73, 21);
|
||||
this.cb_Metersize.TabIndex = 117;
|
||||
//
|
||||
// l_SettingsPreparationMetersize
|
||||
//
|
||||
this.l_SettingsPreparationMetersize.AutoSize = true;
|
||||
this.l_SettingsPreparationMetersize.Location = new System.Drawing.Point(14, 36);
|
||||
this.l_SettingsPreparationMetersize.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.l_SettingsPreparationMetersize.Name = "l_SettingsPreparationMetersize";
|
||||
this.l_SettingsPreparationMetersize.Size = new System.Drawing.Size(55, 13);
|
||||
this.l_SettingsPreparationMetersize.TabIndex = 116;
|
||||
this.l_SettingsPreparationMetersize.Text = "Metersize:";
|
||||
//
|
||||
// PreadjustmentActionsView
|
||||
//
|
||||
this.BackColor = System.Drawing.SystemColors.Control;
|
||||
@ -271,5 +306,8 @@
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.ComboBox cb_Metersize;
|
||||
private System.Windows.Forms.Label l_SettingsPreparationMetersize;
|
||||
private System.Windows.Forms.Button pushTestBenchTempButton;
|
||||
private System.Windows.Forms.TextBox pushedTestBenchTempTextBox;
|
||||
private System.Windows.Forms.Label label8;
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,17 @@
|
||||
using CordonelPreadjustmentUi;
|
||||
using Common;
|
||||
using CordonelPreadjustmentUi;
|
||||
using CordonelPreadjustmentUi.Processes.Itinerary;
|
||||
using GenesisCordonelInterface.API;
|
||||
using GenesisCordonelInterface.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using TBF.UiBridge;
|
||||
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
|
||||
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
|
||||
using Xylem.Common.Ui.CordonelPreadjustmentUi;
|
||||
@ -17,6 +21,8 @@ using GciPublicModels = GenesisCordonelInterface.API.PublicModels;
|
||||
|
||||
namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
{
|
||||
|
||||
|
||||
public partial class PreadjustmentActionsView : UserControl
|
||||
{
|
||||
private readonly GciBridge _bridge;
|
||||
@ -25,6 +31,22 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
private readonly Action _addSlotAction;
|
||||
private readonly Action _saveAction;
|
||||
|
||||
public event EventHandler<EventArgsMeterSuccsessfull> OnAbort;
|
||||
|
||||
private readonly System.Windows.Forms.Timer _tempRequestTimer = new System.Windows.Forms.Timer();
|
||||
private bool _tempButtonHighlight;
|
||||
|
||||
private enum PreadjustmentExecutionMode
|
||||
{
|
||||
AsyncSlotWorker,
|
||||
DirectToProcessTasks
|
||||
}
|
||||
|
||||
private PreadjustmentExecutionMode _preadjustmentExecutionMode = PreadjustmentExecutionMode.DirectToProcessTasks;
|
||||
|
||||
private bool UseDirectProcess =>
|
||||
_preadjustmentExecutionMode == PreadjustmentExecutionMode.DirectToProcessTasks;
|
||||
|
||||
public PreadjustmentActionsView(
|
||||
MainView mainview,
|
||||
GciBridge bridge,
|
||||
@ -41,17 +63,36 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
|
||||
LoadRegisterComboBoxes();
|
||||
|
||||
InitGciHandlers();
|
||||
|
||||
//
|
||||
|
||||
cb_Metersize.Items.Clear();
|
||||
foreach (MeterSize size in (MeterSize[])Enum.GetValues(typeof(MeterSize)))
|
||||
{
|
||||
cb_Metersize.Items.Add(size);
|
||||
}
|
||||
var setM = MeterSize.DN50;
|
||||
if (_mainView._gciApi._innerMeterAPI._settings.MeterSize != null)
|
||||
{
|
||||
setM = _mainView._gciApi._innerMeterAPI._settings.MeterSize;
|
||||
}
|
||||
cb_Metersize.SelectedItem = setM;
|
||||
|
||||
//
|
||||
|
||||
_tempRequestTimer.Interval = 500;
|
||||
|
||||
_tempRequestTimer.Tick += (s, e) =>
|
||||
{
|
||||
_tempButtonHighlight = !_tempButtonHighlight;
|
||||
|
||||
pushTestBenchTempButton.BackColor =
|
||||
_tempButtonHighlight
|
||||
? Color.Red
|
||||
: SystemColors.Control;
|
||||
};
|
||||
}
|
||||
|
||||
private void InitGciHandlers()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void AddSlot()
|
||||
@ -92,7 +133,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
|
||||
private void btnCancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
_cts?.Cancel();
|
||||
OnAbort?.Invoke(null, new EventArgsMeterSuccsessfull(new List<int>()));//stop Laatzen
|
||||
_cts?.Cancel();//stop StaraTura
|
||||
Log("Cancel requested.");
|
||||
}
|
||||
|
||||
@ -147,21 +189,26 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
btnCancel.Enabled = busy;
|
||||
}
|
||||
|
||||
private void LogResult(string methodName, object result)
|
||||
/*private void LogResult(string methodName, object result)
|
||||
{
|
||||
Log(methodName + " result:");
|
||||
Log(result == null ? "<null>" : result.ToString());
|
||||
}
|
||||
}*/
|
||||
|
||||
private void Log(string message)
|
||||
private void Log(string msg)
|
||||
{
|
||||
txtLog.AppendText(
|
||||
DateTime.Now.ToString("HH:mm:ss.fff") +
|
||||
" " +
|
||||
message +
|
||||
msg +
|
||||
Environment.NewLine);
|
||||
}
|
||||
|
||||
private void Log(string msg, int? slot = null, string source = "APP", string PcbID = "")
|
||||
{
|
||||
txtLog.AppendText($"{DateTime.Now.ToString("HH:mm:ss.fff")} {source} {msg} ({PcbID}){Environment.NewLine}");
|
||||
}
|
||||
|
||||
private void LoadRegisterComboBoxes()
|
||||
{
|
||||
|
||||
@ -186,7 +233,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessProgress pp = CreatePreparationProgress();
|
||||
ProcessProgress pp = CreateProcessProgress();
|
||||
List<MeterStateControl> mc = CreateMeterControls(selectedSlots);
|
||||
|
||||
var result = _bridge.Preadjustment_Initialization(pp, mc);
|
||||
@ -221,11 +268,22 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
return;
|
||||
}
|
||||
|
||||
PreadjustmentDetectResult result =
|
||||
await _bridge.PreAdjustment_DetectAsync(selectedSlots, token);
|
||||
PreadjustmentDetectResult result;
|
||||
|
||||
Log(
|
||||
result.Success
|
||||
if (UseDirectProcess)
|
||||
{
|
||||
result = await Task.Run(() =>
|
||||
_bridge.PreAdjustment_DetectDirect(selectedSlots, token),
|
||||
token);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await _bridge.PreAdjustment_DetectAsync(
|
||||
selectedSlots,
|
||||
token);
|
||||
}
|
||||
|
||||
Log(result.Success
|
||||
? "Detect completed. " + result
|
||||
: "Detect failed. " + result);
|
||||
|
||||
@ -239,8 +297,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
{
|
||||
ExecuteAsync(async token =>
|
||||
{
|
||||
await ExecutePreadjustmentForSelectedSlotsAsync(
|
||||
await ExecutePreadjustmentActionAsync(
|
||||
_bridge.PreAdjustment_PreparationAsync,
|
||||
_bridge.PreAdjustment_PreparationDirect,
|
||||
"Preparation",
|
||||
token);
|
||||
});
|
||||
@ -252,8 +311,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
{
|
||||
ExecuteAsync(async token =>
|
||||
{
|
||||
await ExecutePreadjustmentForSelectedSlotsAsync(
|
||||
await ExecutePreadjustmentActionAsync(
|
||||
_bridge.PreAdjustment_AmplitudeTestAsync,
|
||||
_bridge.PreAdjustment_AmplitudeTestDirect,
|
||||
"Amplitude Test",
|
||||
token);
|
||||
});
|
||||
@ -265,8 +325,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
{
|
||||
ExecuteAsync(async token =>
|
||||
{
|
||||
await ExecutePreadjustmentForSelectedSlotsAsync(
|
||||
await ExecutePreadjustmentActionAsync(
|
||||
_bridge.PreAdjustment_TemperatureCalibrationAsync,
|
||||
_bridge.PreAdjustment_TemperatureCalibrationDirect,
|
||||
"Temperature Calibration",
|
||||
token);
|
||||
});
|
||||
@ -278,8 +339,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
{
|
||||
ExecuteAsync(async token =>
|
||||
{
|
||||
await ExecutePreadjustmentForSelectedSlotsAsync(
|
||||
await ExecutePreadjustmentActionAsync(
|
||||
_bridge.PreAdjustment_OffsetTestAsync,
|
||||
_bridge.PreAdjustment_OffsetTestDirect,
|
||||
"Offset Test",
|
||||
token);
|
||||
});
|
||||
@ -291,27 +353,58 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
{
|
||||
ExecuteAsync(async token =>
|
||||
{
|
||||
await ExecutePreadjustmentForSelectedSlotsAsync(
|
||||
await ExecutePreadjustmentActionAsync(
|
||||
_bridge.PreAdjustment_CompletionAsync,
|
||||
_bridge.PreAdjustment_CompletionDirect,
|
||||
"Completion",
|
||||
token);
|
||||
});
|
||||
}
|
||||
|
||||
private ProcessProgress CreatePreparationProgress()
|
||||
private ProcessProgress CreateProcessProgress()
|
||||
{
|
||||
return new ProcessProgress
|
||||
ProcessProgress pp = new ProcessProgress
|
||||
{
|
||||
Setting = new PreAdjustmentSettingsContainer
|
||||
{
|
||||
|
||||
TempOnly = false,
|
||||
Culture = Thread.CurrentThread.CurrentCulture,
|
||||
MeterSize = (MeterSize)cb_Metersize.SelectedItem
|
||||
Culture = new CultureInfo("en-US"),
|
||||
MeterSize = (MeterSize)cb_Metersize.SelectedItem,
|
||||
OffsetTestSettlingTime = 0
|
||||
},
|
||||
|
||||
IsAutomaticMode = false
|
||||
IsAutomaticMode = false,
|
||||
};
|
||||
|
||||
pp.OnRequestTempretureSelection += RequestTempretureSelection;
|
||||
pp.OnDebugMessageChanged += DebugMessageChanged;
|
||||
|
||||
OnAbort += (o, args) =>
|
||||
{
|
||||
pp.StopSequence = true;
|
||||
pp.CancellationSource.Cancel();
|
||||
};
|
||||
|
||||
return pp;
|
||||
|
||||
}
|
||||
|
||||
private void DebugMessageChanged(object sender, EventArgsDebug e)
|
||||
{
|
||||
BeginInvoke(new Action(() =>
|
||||
{
|
||||
Log(e.Value, e.Slot, e.Source, e.PcbId);
|
||||
}));
|
||||
}
|
||||
|
||||
private void RequestTempretureSelection(object sender, EventArgs e)
|
||||
{
|
||||
BeginInvoke(new Action(() =>
|
||||
{
|
||||
Log("Temperature requesting, please set actual value");
|
||||
|
||||
_tempRequestTimer.Start();
|
||||
}));
|
||||
}
|
||||
|
||||
private List<MeterStateControl> CreateMeterControls(IEnumerable<GciPublicModels.MeterBatchDebugStatus> slots)
|
||||
@ -332,79 +425,13 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
return controls;
|
||||
}
|
||||
|
||||
private PreAdjustmentSettingsContainer CreatePreAdjustmentSettings(IEnumerable<GciPublicModels.MeterBatchDebugStatus> slots)
|
||||
|
||||
private void pushTestBenchTempButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var settings =
|
||||
new PreAdjustmentSettingsContainer();
|
||||
_bridge.PreAdjustment_PushTemperature(Convert.ToDouble(pushedTestBenchTempTextBox.Text));
|
||||
|
||||
settings.Meters =
|
||||
slots.Select(s => s.Slot).ToList();
|
||||
|
||||
settings.TempMeters =
|
||||
new List<int>();
|
||||
|
||||
settings.NumberOfPaths = 2;
|
||||
settings.TempOnly = false;
|
||||
settings.Culture =
|
||||
Thread.CurrentThread.CurrentCulture;
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void writeRegisterButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
/*ExecuteAsync(async token =>
|
||||
{
|
||||
string registerName = Convert.ToString(writeRegisterNameComboBox.Text).Trim();
|
||||
string valueText = writeRegisterValueTextBox.Text.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(registerName))
|
||||
throw new Exception("Write register name is empty.");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
var tasks = GetSelectedSlots()
|
||||
.Select(async slot =>
|
||||
{
|
||||
//var result = await _bridge.WriteRegisterAsync(slot.Slot, registerName, value, false, false, token);
|
||||
//var result = await _bridge.WriteRegisterWithRetryAsync(slot.Slot, registerName, value, false, false, token);
|
||||
|
||||
var result = Xylem.Common.Ui.CordonelPreadjustmentUi. Processes.WriteRegisterSafe(meter, "Calibration factor1", Register.Genesisflow.CalFactor1, setting.CalFactor1);
|
||||
Processes
|
||||
|
||||
return new
|
||||
{
|
||||
Slot = slot.Slot,
|
||||
Result = result
|
||||
};
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var results = await Task.WhenAll(tasks);
|
||||
|
||||
foreach (var item in results.OrderBy(x => x.Slot))
|
||||
{
|
||||
LogResult(
|
||||
$"WriteRegisterAsync slot {item.Slot}, register {registerName}, value {value}",
|
||||
item.Result);
|
||||
}
|
||||
|
||||
RefreshGrid();
|
||||
});*/
|
||||
_tempRequestTimer.Stop();
|
||||
pushTestBenchTempButton.BackColor = SystemColors.Control;
|
||||
}
|
||||
|
||||
private async Task ExecutePreadjustmentForSelectedSlotsAsync(
|
||||
@ -421,9 +448,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
return;
|
||||
}
|
||||
|
||||
var pp =
|
||||
CreatePreparationProgress();
|
||||
|
||||
foreach (var selectedSlot in selectedSlots)
|
||||
{
|
||||
PreAdjustmentProcessResult result =
|
||||
@ -441,5 +465,31 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
|
||||
RefreshGrid();
|
||||
}
|
||||
|
||||
private async Task ExecutePreadjustmentActionAsync(
|
||||
Func<int, CancellationToken, Task<PreAdjustmentProcessResult>> asyncAction,
|
||||
Func<PreAdjustmentProcessResult> directAction,
|
||||
string processName,
|
||||
CancellationToken token)
|
||||
{
|
||||
if (UseDirectProcess)
|
||||
{
|
||||
PreAdjustmentProcessResult result =
|
||||
await Task.Run(() => directAction(), token);
|
||||
|
||||
Log(result.Success
|
||||
? $"{processName} completed. {result}"
|
||||
: $"{processName} failed. {result}");
|
||||
|
||||
RefreshGrid();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await ExecutePreadjustmentForSelectedSlotsAsync(
|
||||
asyncAction,
|
||||
processName,
|
||||
token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,31 +21,53 @@
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.grpStorage = new System.Windows.Forms.GroupBox();
|
||||
this.lblPcbId = new System.Windows.Forms.Label();
|
||||
this.txtPcbId = new System.Windows.Forms.TextBox();
|
||||
this.btnGetPasswordByPcb = new System.Windows.Forms.Button();
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
this.txtLog = new System.Windows.Forms.TextBox();
|
||||
this.lblPcbId = new System.Windows.Forms.Label();
|
||||
this.txtPcbId = new System.Windows.Forms.TextBox();
|
||||
this.getCalibrationParamsButton = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.calibrationParamsTextBox = new System.Windows.Forms.TextBox();
|
||||
this.grpStorage.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// grpStorage
|
||||
//
|
||||
this.grpStorage.Controls.Add(this.calibrationParamsTextBox);
|
||||
this.grpStorage.Controls.Add(this.label1);
|
||||
this.grpStorage.Controls.Add(this.getCalibrationParamsButton);
|
||||
this.grpStorage.Controls.Add(this.lblPcbId);
|
||||
this.grpStorage.Controls.Add(this.txtPcbId);
|
||||
this.grpStorage.Controls.Add(this.btnGetPasswordByPcb);
|
||||
this.grpStorage.Location = new System.Drawing.Point(10, 37);
|
||||
this.grpStorage.Name = "grpStorage";
|
||||
this.grpStorage.Size = new System.Drawing.Size(200, 261);
|
||||
this.grpStorage.Size = new System.Drawing.Size(215, 261);
|
||||
this.grpStorage.TabIndex = 0;
|
||||
this.grpStorage.TabStop = false;
|
||||
this.grpStorage.Text = "UniDataStorageReader for GCI";
|
||||
//
|
||||
// lblPcbId
|
||||
//
|
||||
this.lblPcbId.AutoSize = true;
|
||||
this.lblPcbId.Location = new System.Drawing.Point(10, 25);
|
||||
this.lblPcbId.Name = "lblPcbId";
|
||||
this.lblPcbId.Size = new System.Drawing.Size(45, 13);
|
||||
this.lblPcbId.TabIndex = 0;
|
||||
this.lblPcbId.Text = "PCB ID:";
|
||||
//
|
||||
// txtPcbId
|
||||
//
|
||||
this.txtPcbId.Location = new System.Drawing.Point(65, 22);
|
||||
this.txtPcbId.Name = "txtPcbId";
|
||||
this.txtPcbId.Size = new System.Drawing.Size(120, 20);
|
||||
this.txtPcbId.TabIndex = 1;
|
||||
//
|
||||
// btnGetPasswordByPcb
|
||||
//
|
||||
this.btnGetPasswordByPcb.Location = new System.Drawing.Point(10, 55);
|
||||
this.btnGetPasswordByPcb.Location = new System.Drawing.Point(13, 48);
|
||||
this.btnGetPasswordByPcb.Name = "btnGetPasswordByPcb";
|
||||
this.btnGetPasswordByPcb.Size = new System.Drawing.Size(175, 28);
|
||||
this.btnGetPasswordByPcb.Size = new System.Drawing.Size(196, 28);
|
||||
this.btnGetPasswordByPcb.TabIndex = 2;
|
||||
this.btnGetPasswordByPcb.Text = "Get password (by PCB)";
|
||||
this.btnGetPasswordByPcb.UseVisualStyleBackColor = true;
|
||||
@ -64,30 +86,40 @@
|
||||
//
|
||||
// txtLog
|
||||
//
|
||||
this.txtLog.Location = new System.Drawing.Point(220, 10);
|
||||
this.txtLog.Location = new System.Drawing.Point(231, 10);
|
||||
this.txtLog.Multiline = true;
|
||||
this.txtLog.Name = "txtLog";
|
||||
this.txtLog.ReadOnly = true;
|
||||
this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.txtLog.Size = new System.Drawing.Size(500, 340);
|
||||
this.txtLog.Size = new System.Drawing.Size(489, 340);
|
||||
this.txtLog.TabIndex = 4;
|
||||
this.txtLog.WordWrap = false;
|
||||
//
|
||||
// lblPcbId
|
||||
// getCalibrationParamsButton
|
||||
//
|
||||
this.lblPcbId.AutoSize = true;
|
||||
this.lblPcbId.Location = new System.Drawing.Point(10, 25);
|
||||
this.lblPcbId.Name = "lblPcbId";
|
||||
this.lblPcbId.Size = new System.Drawing.Size(45, 13);
|
||||
this.lblPcbId.TabIndex = 0;
|
||||
this.lblPcbId.Text = "PCB ID:";
|
||||
this.getCalibrationParamsButton.Location = new System.Drawing.Point(13, 139);
|
||||
this.getCalibrationParamsButton.Name = "getCalibrationParamsButton";
|
||||
this.getCalibrationParamsButton.Size = new System.Drawing.Size(196, 34);
|
||||
this.getCalibrationParamsButton.TabIndex = 3;
|
||||
this.getCalibrationParamsButton.Text = "Get CalibrationParams (by MeterSize)";
|
||||
this.getCalibrationParamsButton.UseVisualStyleBackColor = true;
|
||||
this.getCalibrationParamsButton.Click += new System.EventHandler(this.getCalibrationParamsButton_Click);
|
||||
//
|
||||
// txtPcbId
|
||||
// label1
|
||||
//
|
||||
this.txtPcbId.Location = new System.Drawing.Point(65, 22);
|
||||
this.txtPcbId.Name = "txtPcbId";
|
||||
this.txtPcbId.Size = new System.Drawing.Size(120, 20);
|
||||
this.txtPcbId.TabIndex = 1;
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(10, 116);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(54, 13);
|
||||
this.label1.TabIndex = 4;
|
||||
this.label1.Text = "MeterSize";
|
||||
//
|
||||
// calibrationParamsTextBox
|
||||
//
|
||||
this.calibrationParamsTextBox.Location = new System.Drawing.Point(65, 113);
|
||||
this.calibrationParamsTextBox.Name = "calibrationParamsTextBox";
|
||||
this.calibrationParamsTextBox.Size = new System.Drawing.Size(120, 20);
|
||||
this.calibrationParamsTextBox.TabIndex = 5;
|
||||
//
|
||||
// UniDataSorageActionsView
|
||||
//
|
||||
@ -105,5 +137,8 @@
|
||||
|
||||
private System.Windows.Forms.Label lblPcbId;
|
||||
private System.Windows.Forms.TextBox txtPcbId;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Button getCalibrationParamsButton;
|
||||
private System.Windows.Forms.TextBox calibrationParamsTextBox;
|
||||
}
|
||||
}
|
||||
@ -30,7 +30,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
|
||||
var result = await _bridge.GetPasswordAsync(pcbId, token);
|
||||
|
||||
LogResult("GetPasswordAsync PCB=" + pcbId, result);
|
||||
LogResult("ReadMeterLoginPasswordAsync PCB=" + pcbId, result);
|
||||
});
|
||||
}
|
||||
|
||||
@ -100,5 +100,31 @@ namespace TBF.Rig.BridgeComponents.GciBridge.UI.StaraTuraAPI_GciBridge
|
||||
message +
|
||||
Environment.NewLine);
|
||||
}
|
||||
|
||||
private void getCalibrationParamsButton_Click(
|
||||
object sender,
|
||||
EventArgs e)
|
||||
{
|
||||
ExecuteAsync(async token =>
|
||||
{
|
||||
if (!int.TryParse(
|
||||
calibrationParamsTextBox.Text.Trim(),
|
||||
out int meterSize))
|
||||
{
|
||||
throw new Exception(
|
||||
"Meter size is invalid.");
|
||||
}
|
||||
|
||||
var result =
|
||||
await _bridge.GetPreAdjustmentCalibrationParamsAsync(
|
||||
meterSize,
|
||||
token);
|
||||
|
||||
LogResult(
|
||||
"GetPreAdjustmentCalibrationParamsAsync MeterSize=" +
|
||||
meterSize,
|
||||
result);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user