diff --git a/GenesisCordonelInterface/API/Enums.cs b/GenesisCordonelInterface/API/Enums.cs new file mode 100644 index 000000000..7ac46fc4c --- /dev/null +++ b/GenesisCordonelInterface/API/Enums.cs @@ -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 + } + } +} diff --git a/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs b/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs index 33556bc07..a0695c71e 100644 --- a/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs +++ b/GenesisCordonelInterface/API/InterfaceOutsideToGCI.cs @@ -1,5 +1,9 @@ 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; @@ -36,12 +40,31 @@ namespace GenesisCordonelInterface.API /// public event Action> MeterBatchStatusChanged; + private readonly IMeterLoginPasswordReader loginPasswordsReader; + + private readonly IPreAdjustmentCalibrationParamsReader calibrationParamsReader; + /// /// Initializes a new instance of the public GCI facade. /// public InterfaceOutsideToGCI() { - _innerMeterAPI = new InterfaceGCIToLaatzen(); + + } + + /// + /// Initializes a new instance of the public GCI facade. + /// + 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)); } // Laatzen ToolBox actions @@ -50,7 +73,7 @@ namespace GenesisCordonelInterface.API public PortDetectionResult DetectStreamingPort(int slot) { - var result = _innerMeterAPI.DetectStreamingPort(slot); + var result = _innerMeterAPI?.DetectStreamingPort(slot); //RaiseMeterBatchStatusChanged(); return result; } @@ -59,14 +82,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 +98,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 +507,7 @@ namespace GenesisCordonelInterface.API return result; } + #endregion #region ================================== DEBUG STATUS ================================== @@ -497,7 +521,7 @@ namespace GenesisCordonelInterface.API /// public List GetWorkerDebugStatuses() { - return _innerMeterAPI.GetWorkerDebugStatuses(); + return _innerMeterAPI?.GetWorkerDebugStatuses(); } /// @@ -509,7 +533,7 @@ namespace GenesisCordonelInterface.API /// public List GetMeterBatchDebugStatuses() { - return _innerMeterAPI.GetMeterBatchDebugStatuses(); + return _innerMeterAPI?.GetMeterBatchDebugStatuses(); } /// @@ -538,7 +562,7 @@ namespace GenesisCordonelInterface.API /// Selection state. public void SetSlotSelected(int slot, bool selected) { - _innerMeterAPI.SetSlotSelected(slot, selected); + _innerMeterAPI?.SetSlotSelected(slot, selected); RaiseMeterBatchStatusChanged(); } @@ -551,7 +575,7 @@ namespace GenesisCordonelInterface.API /// public bool IsSlotSelected(int slot) { - return _innerMeterAPI.IsSlotSelected(slot); + return (bool)(_innerMeterAPI?.IsSlotSelected(slot)); } /// @@ -562,7 +586,7 @@ namespace GenesisCordonelInterface.API /// public List GetSelectedSlots() { - return _innerMeterAPI.GetSelectedSlots(); + return _innerMeterAPI?.GetSelectedSlots(); } #endregion @@ -577,7 +601,7 @@ namespace GenesisCordonelInterface.API /// public List GetAllRegisterNames() { - return _innerMeterAPI.GetAllRegisterNames(); + return _innerMeterAPI?.GetAllRegisterNames(); } #endregion @@ -589,7 +613,7 @@ namespace GenesisCordonelInterface.API ProcessProgress pp, List mc) { - return _innerMeterAPI.Preadjustment_Initialization(pp, mc); + return _innerMeterAPI?.Preadjustment_Initialization(pp, mc); } public Task PreAdjustment_DetectAsync( @@ -641,5 +665,62 @@ namespace GenesisCordonelInterface.API } #endregion + + #region ================================== UNI DATA STORAGE READER ================================== + + //LoginPasswords reading + + /// + /// Reads meter login password from configured GCI data storage. + /// + /// + /// Data query containing PCB ID or another configured lookup value. + /// + /// + /// Cancellation token used to cancel the asynchronous operation. + /// + /// + /// Password if found; otherwise null. + /// + public Task ReadMeterLoginPasswordAsync( + DataQuery query, + CancellationToken token = default) + { + return loginPasswordsReader.ReadMeterLoginPasswordAsync( + query, + token); + } + + //CalibrationParams reading + + /// + /// Reads pre-adjustment calibration parameters + /// from configured GCI data storage. + /// + /// + /// Data query containing meter size or another configured lookup value. + /// + /// + /// Cancellation token used to cancel the asynchronous operation. + /// + /// + /// Dictionary: + /// + /// Key: + /// Calibration parameter name + /// + /// Value: + /// Calibration parameter value + /// + public Task> ReadPreAdjustmentCalibrationParamsAsync( + DataQuery query, + CancellationToken token = default) + { + return calibrationParamsReader.ReadCalibrationParamsAsync( + query, + token); + } + + #endregion } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/DataStorage/Config/GciConfig.cs b/GenesisCordonelInterface/Core/Config/GciConfig.cs similarity index 80% rename from GenesisCordonelInterface/Core/DataStorage/Config/GciConfig.cs rename to GenesisCordonelInterface/Core/Config/GciConfig.cs index c4cf686c0..b97a8c7c8 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Config/GciConfig.cs +++ b/GenesisCordonelInterface/Core/Config/GciConfig.cs @@ -1,4 +1,4 @@ -namespace GenesisCordonelInterface.Core.DataStorage.Config +namespace GenesisCordonelInterface.Core.Config { /// /// Root GCI configuration object loaded from gci_config.json. @@ -9,7 +9,7 @@ /// Example: /// /// { - /// "DataStorage": + /// "DataStorageSection": /// { /// ... /// } @@ -27,6 +27,6 @@ /// - PreAdjustmentCalibrationParams /// - future storage providers /// - public GciDataStorageConfig DataStorage { get; set; } + public DataStorage.Config.GciDataStorageConfig DataStorageSection { get; set; } } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/DataStorage/Config/GciConfigLoader.cs b/GenesisCordonelInterface/Core/Config/GciConfigLoader.cs similarity index 95% rename from GenesisCordonelInterface/Core/DataStorage/Config/GciConfigLoader.cs rename to GenesisCordonelInterface/Core/Config/GciConfigLoader.cs index b88db0d3b..78b635f81 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Config/GciConfigLoader.cs +++ b/GenesisCordonelInterface/Core/Config/GciConfigLoader.cs @@ -4,7 +4,7 @@ using GenesisCordonelInterface.Core.DataStorage.Reading.Common; using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models; using Newtonsoft.Json; -namespace GenesisCordonelInterface.Core.DataStorage.Config +namespace GenesisCordonelInterface.Core.Config { /// /// Loads GCI configuration from gci_config.json. @@ -114,15 +114,15 @@ namespace GenesisCordonelInterface.Core.DataStorage.Config GciConfig config, string baseDirectory) { - if (config.DataStorage == null) + if (config.DataStorageSection == null) return; NormalizePath( - config.DataStorage.MeterLoginPasswords, + config.DataStorageSection.MeterLoginPasswords, baseDirectory); NormalizePath( - config.DataStorage.PreAdjustmentCalibrationParams, + config.DataStorageSection.PreAdjustmentCalibrationParams, baseDirectory); } diff --git a/GenesisCordonelInterface/Config/gci_config.json b/GenesisCordonelInterface/Core/Config/gci_config.json similarity index 56% rename from GenesisCordonelInterface/Config/gci_config.json rename to GenesisCordonelInterface/Core/Config/gci_config.json index 617517733..febe63041 100644 --- a/GenesisCordonelInterface/Config/gci_config.json +++ b/GenesisCordonelInterface/Core/Config/gci_config.json @@ -1,7 +1,7 @@ { "_Comment": "GCI DataStorage configuration", - "DataStorage": { + "DataStorageSection": { "MeterLoginPasswords": { @@ -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" } } } diff --git a/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DataStorageConfig.cs b/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DataStorageConfig.cs index 2bc89bc64..16b68b17e 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DataStorageConfig.cs +++ b/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DataStorageConfig.cs @@ -46,5 +46,17 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models /// WHERE [PcbId]=QUERYPARAM /// public string QueryTemplate { get; set; } + + public DataStorageConfig( + string name, + DataStorageType type, + string dataSource, + string queryTemplate) + { + Name = name; + Type = type; + DataSource = dataSource; + QueryTemplate = queryTemplate; + } } } diff --git a/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DatabaseSearchResult.cs b/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DatabaseSearchResult.cs index 2f69501ee..b52f2186b 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DatabaseSearchResult.cs +++ b/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Models/DatabaseSearchResult.cs @@ -2,17 +2,52 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models { - public class DatabaseSearchResult + /// + /// Represents result returned by database-based + /// data storage readers. + /// + /// Supports both: + /// + /// - Single-row lookups + /// (e.g. MeterLoginPasswords) + /// + /// - Multi-row queries + /// (e.g. PreAdjustmentCalibrationParams) + /// + internal class DatabaseSearchResult { + /// + /// Indicates whether at least one record + /// was found. + /// public bool Found { get; set; } + /// + /// Executed SQL query text. + /// Mainly intended for diagnostics + /// and troubleshooting. + /// public string Query { get; set; } - public Dictionary Values { get; set; } + /// + /// First returned row represented as + /// column/value pairs. + /// + /// Preserved for backward compatibility + /// with existing readers expecting + /// a single database record. + /// + public Dictionary Values { get; } + = new Dictionary(); - public DatabaseSearchResult() - { - Values = new Dictionary(); - } + /// + /// All returned rows represented as + /// a collection of column/value dictionaries. + /// + /// Intended for queries returning + /// multiple records. + /// + public List> Rows { get; } + = new List>(); } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Providers/DatabaseDataStorageReader.cs b/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Providers/DatabaseDataStorageReader.cs index acf2ccee3..e313f76ec 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Providers/DatabaseDataStorageReader.cs +++ b/GenesisCordonelInterface/Core/DataStorage/Reading/Common/Providers/DatabaseDataStorageReader.cs @@ -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 /// public class DatabaseDataStorageReader : IDataStorageReader { /// - /// Data storage configuration containing connection string and query template. + /// Data storage configuration containing + /// connection string and query template. /// private readonly DataStorageConfig config; /// - /// Creates SQL Server data storage reader using provided configuration. + /// Creates SQL Server data storage reader + /// using provided configuration. /// /// - /// Data storage configuration loaded from gci_config.json. + /// Data storage configuration loaded + /// from gci_config.json. /// - public DatabaseDataStorageReader(DataStorageConfig config) + public DatabaseDataStorageReader( + DataStorageConfig config) { - this.config = config ?? throw new ArgumentNullException(nameof(config)); + this.config = + config ?? throw new ArgumentNullException(nameof(config)); } /// - /// 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. /// /// /// Query object containing lookup parameter. /// /// - /// DatabaseSearchResult containing returned SQL columns and values. + /// DatabaseSearchResult containing returned + /// database records. + /// + /// Values contains the first returned row. + /// + /// Rows contains the complete result set. /// 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 - { - Query = sqlText - }; + 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 row = + new Dictionary(); + + for (int i = 0; i < reader.FieldCount; i++) + { + 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); } - result.Found = true; - - for (int i = 0; i < reader.FieldCount; i++) + if (result.Rows.Count == 0) { - object value = reader.GetValue(i); - result.Values[reader.GetName(i)] = - value == DBNull.Value ? null : value; + result.Found = false; } return result; @@ -92,7 +169,8 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers } /// - /// Tests whether SQL Server connection can be opened. + /// Tests whether SQL Server connection + /// can be opened. /// /// /// Enables detailed diagnostic output. @@ -100,45 +178,70 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers /// /// Diagnostic result of SQL connection test. /// - 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; } /// - /// Tests whether configured SQL query can be prepared and executed. + /// Tests whether configured SQL query + /// can be prepared and executed. /// /// /// Enables detailed diagnostic output. @@ -146,16 +249,22 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers /// /// Diagnostic result of query execution test. /// - 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; } /// - /// Converts configured QueryTemplate to executable SQL text. + /// Converts configured QueryTemplate + /// to executable SQL text. /// /// - /// SQL query template containing QUERYPARAM placeholder. + /// SQL query template containing + /// QUERYPARAM placeholder. /// /// - /// SQL text with QUERYPARAM replaced by @value parameter. + /// SQL text with QUERYPARAM replaced + /// by @value parameter. /// - 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"); } /// /// Extracts first query parameter value. /// - /// - /// Data query containing query parameters. - /// - /// - /// First query parameter value. - /// - 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 /// /// Adds lookup parameter to SQL command. /// - /// - /// SQL command. - /// - /// - /// Query parameter value. - /// - 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; } /// - /// Adds diagnostic line when diagnostics are enabled. + /// Adds diagnostic line when diagnostics + /// are enabled. /// - /// - /// Diagnostic result object. - /// - /// - /// Indicates whether diagnostics are enabled. - /// - /// - /// Diagnostic message. - /// private static void Log( ReaderDiagnosticResult result, bool enableDiagnostics, diff --git a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/IMeterLoginPasswordReader.cs b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/IMeterLoginPasswordReader.cs index 28baa793b..1d52ea09d 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/IMeterLoginPasswordReader.cs +++ b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/IMeterLoginPasswordReader.cs @@ -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 /// /// Password if found; otherwise null. /// - string GetPassword(string queryParam); + string GetPassword(DataQuery query); /// /// Reads meter login password asynchronously. @@ -43,8 +44,8 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.Meter /// /// Password if found; otherwise null. /// - Task GetPasswordAsync( - string queryParam, + Task ReadMeterLoginPasswordAsync( + DataQuery query, CancellationToken token = default); } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/MeterLoginPasswordReader.cs b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/MeterLoginPasswordReader.cs index 2a7943b8f..e34b07580 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/MeterLoginPasswordReader.cs +++ b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/MeterLoginPasswords/MeterLoginPasswordReader.cs @@ -7,85 +7,120 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; -/// -/// Reads meter login password from configured GCI data storage. -/// -public class MeterLoginPasswordReader : IMeterLoginPasswordReader +namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords { /// - /// Universal data storage reader selected by configuration. - /// Can represent database, CSV, JSON or REST reader. + /// Reads meter login password from configured GCI data storage. /// - private readonly IDataStorageReader reader; - - /// - /// Ensures that only one password lookup is executed at a time. - /// - private readonly SemaphoreSlim readLock = new SemaphoreSlim(1, 1); - - /// - /// Creates password reader using provided data storage configuration. - /// - /// Data storage configuration loaded from gci_config.json. - public MeterLoginPasswordReader(DataStorageConfig config) + public class MeterLoginPasswordReader : IMeterLoginPasswordReader { - reader = DataStorageReaderFactory.Create(config); - } + /// + /// Universal data storage reader selected by configuration. + /// Can represent database, CSV, JSON or REST reader. + /// + private readonly IDataStorageReader reader; - /// - /// Asynchronously reads meter login password by query parameter. - /// - /// PCB ID or another configured lookup value. - /// Cancellation token. - /// Password if found; otherwise null. - public async Task GetPasswordAsync( - string queryParam, - CancellationToken token = default) - { - if (string.IsNullOrWhiteSpace(queryParam)) - throw new ArgumentException("Query parameter must not be empty.", nameof(queryParam)); + /// + /// Ensures that only one password lookup is executed at a time. + /// + private readonly SemaphoreSlim readLock = new SemaphoreSlim(1, 1); - await readLock.WaitAsync(token); - - try + /// + /// Creates password reader using provided data storage configuration. + /// + /// Data storage configuration loaded from gci_config.json. + public MeterLoginPasswordReader(DataStorageConfig config) { - return await Task.Run( - () => GetPassword(queryParam), - token); - } - finally - { - readLock.Release(); - } - } - - /// - /// Reads meter login password by query parameter. - /// - /// PCB ID or another configured lookup value. - /// Password if found; otherwise null. - public string GetPassword(string queryParam) - { - if (string.IsNullOrWhiteSpace(queryParam)) - throw new ArgumentException("Query parameter must not be empty.", nameof(queryParam)); - - DataQuery query = new DataQuery(); - query.QueryParams.Add(queryParam); - - object result = reader.GetData(query); - - if (result is ReaderDiagnosticResult csvResult) - return csvResult.Data?.ToString(); - - if (result is DatabaseSearchResult dbResult) - { - if (!dbResult.Found || dbResult.Values == null || dbResult.Values.Count == 0) - return null; - - foreach (object value in dbResult.Values.Values) - return value?.ToString(); + reader = DataStorageReaderFactory.Create(config); } - return result?.ToString(); + /// + /// Asynchronously reads meter login password using + /// the provided data query. + /// + /// Thread-safe implementation may serialize + /// access to the underlying storage. + /// + /// + /// Data query containing lookup parameter values. + /// + /// + /// Cancellation token. + /// + /// + /// Password if found; otherwise null. + /// + public async Task ReadMeterLoginPasswordAsync( + DataQuery query, + CancellationToken token = default) + { + 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(query), + token); + } + finally + { + readLock.Release(); + } + } + + /// + /// Reads meter login password using + /// the provided data query. + /// + /// + /// Data query containing lookup parameter values. + /// + /// + /// Password if found; otherwise null. + /// + public string GetPassword( + DataQuery query) + { + if (query == null) + throw new ArgumentNullException(nameof(query)); + + if (query.QueryParams.Count == 0) + throw new ArgumentException( + "Query does not contain any parameter.", + nameof(query)); + + object result = + reader.GetData(query); + + if (result is ReaderDiagnosticResult diagnosticResult) + { + return diagnosticResult.Data?.ToString(); + } + + if (result is DatabaseSearchResult dbResult) + { + 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(); + } } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/IPreAdjustmentCalibrationParamsReader.cs b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/IPreAdjustmentCalibrationParamsReader.cs index 4063f4d4e..822aa4d8c 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/IPreAdjustmentCalibrationParamsReader.cs +++ b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/IPreAdjustmentCalibrationParamsReader.cs @@ -1,43 +1,61 @@ -using System.Collections.Generic; +using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models; +using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams { /// /// 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 /// - internal interface IPreAdjustmentCalibrationParamsReader + public interface IPreAdjustmentCalibrationParamsReader { /// - /// Reads all calibration parameters assigned - /// to a specific DN identifier. + /// Reads all pre-adjustment calibration parameters + /// using the provided data query synchronously. /// - /// - /// Internal DN identifier (meter size). + /// + /// Data query containing meter size as lookup parameter. /// /// - /// Dictionary: - /// - /// Key: - /// GENESISFLOW parameter name - /// - /// Value: - /// Stored parameter value + /// Dictionary where key is GENESISFLOW parameter name + /// and value is stored parameter value. /// - Task> ReadParamsAsync(int dnInternalId); + Dictionary GetCalibrationParams( + DataQuery query); + + /// + /// Reads all pre-adjustment calibration parameters + /// using the provided data query asynchronously. + /// + /// + /// Data query containing meter size as lookup parameter. + /// + /// + /// Cancellation token. + /// + /// + /// Dictionary where key is GENESISFLOW parameter name + /// and value is stored parameter value. + /// + Task> ReadCalibrationParamsAsync( + DataQuery query, + CancellationToken token = default); } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/PreAdjustmentCalibrationParamsReader.cs b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/PreAdjustmentCalibrationParamsReader.cs index 5e9ff3b7d..29ba742d2 100644 --- a/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/PreAdjustmentCalibrationParamsReader.cs +++ b/GenesisCordonelInterface/Core/DataStorage/Reading/Implementation/PreAdjustmentCalibrationParams/PreAdjustmentCalibrationParamsReader.cs @@ -1,87 +1,250 @@ -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 { /// /// 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 /// - internal class PreAdjustmentCalibrationParamsReader: IPreAdjustmentCalibrationParamsReader + public class PreAdjustmentCalibrationParamsReader + : IPreAdjustmentCalibrationParamsReader { - private readonly string _connectionString; + /// + /// Universal data storage reader selected by configuration. + /// Can represent database, CSV, JSON or REST reader. + /// + private readonly IDataStorageReader reader; /// - /// Initializes calibration parameter reader. + /// Ensures that only one calibration parameter lookup + /// is executed at a time. /// - /// - /// SQL database connection string. + private readonly SemaphoreSlim readLock = + new SemaphoreSlim(1, 1); + + /// + /// Creates calibration parameter reader using + /// provided data storage configuration. + /// + /// + /// Data storage configuration loaded from gci_config.json. /// 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); } - /// - public async Task> ReadParamsAsync(int dnInternalId) + /// + /// 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. + /// + /// + /// Data query containing lookup parameter values. + /// + /// + /// Cancellation token. + /// + /// + /// Dictionary: + /// + /// Key: + /// GENESISFLOW parameter name + /// + /// Value: + /// Stored parameter value + /// + public async Task> ReadCalibrationParamsAsync( + DataQuery query, + CancellationToken token = default) { - var result = new Dictionary(); + ValidateQuery(query); - const string query = @" - SELECT ParameterName, ParameterValue - FROM dbo.PreAdjustmentCalibrationParams - WHERE Dn_InternalId=@Dn_InternalId"; + await readLock.WaitAsync(token); - using (var connection = new SqlConnection(_connectionString)) - - using (var command = new SqlCommand(query, connection)) + try { - command.Parameters.AddWithValue( - "@Dn_InternalId", - dnInternalId); + return await Task.Run( + () => GetCalibrationParams(query), + token); + } + finally + { + readLock.Release(); + } + } - await connection.OpenAsync(); + /// + /// Reads all pre-adjustment calibration parameters + /// using the provided data query. + /// + /// The query is expected to contain meter size + /// as the first lookup parameter. + /// + /// + /// Data query containing lookup parameter values. + /// + /// + /// Dictionary: + /// + /// Key: + /// GENESISFLOW parameter name + /// + /// Value: + /// Stored parameter value + /// + public Dictionary GetCalibrationParams( + DataQuery query) + { + ValidateQuery(query); - using (var reader = - await command.ExecuteReaderAsync()) + object result = + reader.GetData(query); + + return ConvertResultToDictionary(result); + } + + /// + /// Validates that data query exists + /// and contains at least one lookup parameter. + /// + /// + /// Data query to validate. + /// + 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)); + } + } + + /// + /// Converts provider-specific result objects + /// returned by IDataStorageReader into a unified + /// dictionary representation. + /// + /// + /// Raw result returned by the configured storage reader. + /// + /// + /// Dictionary containing calibration parameter + /// name/value pairs. + /// + private Dictionary ConvertResultToDictionary( + object result) + { + Dictionary values = + new Dictionary(); + + if (result == null) + return values; + + if (result is DatabaseSearchResult dbResult) + { + if (!dbResult.Found) + return values; + + foreach (Dictionary row in dbResult.Rows) { - while (await reader.ReadAsync()) + if (!row.TryGetValue( + "ParameterName", + out object parameterNameObject)) { - var parameterName = reader["ParameterName"].ToString(); - - var parameterValue = reader["ParameterValue"].ToString(); - - if (!string.IsNullOrWhiteSpace(parameterName)) - { - result[parameterName] = parameterValue; - } + continue; } + + if (!row.TryGetValue( + "ParameterValue", + out object parameterValueObject)) + { + continue; + } + + string parameterName = + parameterNameObject?.ToString(); + + if (string.IsNullOrWhiteSpace(parameterName)) + continue; + + values[parameterName] = + parameterValueObject?.ToString(); + } + + return values; + } + + if (result is ReaderDiagnosticResult diagnosticResult) + { + if (diagnosticResult.Data is Dictionary dictionary) + return dictionary; + + if (diagnosticResult.Data is Dictionary objectDictionary) + { + foreach (var item in objectDictionary) + { + values[item.Key] = + item.Value?.ToString(); + } + + return values; } } - return result; + if (result is Dictionary directDictionary) + return directDictionary; + + if (result is Dictionary directObjectDictionary) + { + foreach (var item in directObjectDictionary) + { + values[item.Key] = + item.Value?.ToString(); + } + } + + return values; } } } \ No newline at end of file diff --git a/GenesisCordonelInterface/Core/Engine/Engine.cs b/GenesisCordonelInterface/Core/Engine/Engine.cs new file mode 100644 index 000000000..0e2bae171 --- /dev/null +++ b/GenesisCordonelInterface/Core/Engine/Engine.cs @@ -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; + + /// + /// Initializes a new instance of the public GCI facade. + /// + 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); + } + } +} diff --git a/GenesisCordonelInterface/GenesisCordonelInterface.csproj b/GenesisCordonelInterface/GenesisCordonelInterface.csproj index 670168a32..9a5c3ecaa 100644 --- a/GenesisCordonelInterface/GenesisCordonelInterface.csproj +++ b/GenesisCordonelInterface/GenesisCordonelInterface.csproj @@ -60,9 +60,10 @@ - - + + + @@ -80,6 +81,7 @@ + @@ -198,7 +200,8 @@ FrmGCIAPI.cs - + + Config\gci_config.json PreserveNewest diff --git a/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs b/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs index d27516c06..25b2ab1fe 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs @@ -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,13 @@ namespace TBF.Rig.BridgeComponents.GciBridge readonly GciBridgeCfg gciBridgeCfg; - readonly UdsReaderType reader; + //readonly UdsReaderType_LoginPasswords loginPasswordsDataStorageReader; + //readonly UdsReaderType_CalibrationParams calibrationParamsStorageReader; readonly UdsWriterType writer; + //GCI main init + GciEngine _gciEngine; + //diag GUI for GCI GciGUIType gciGUI; Form gciGuiHostForm; @@ -55,18 +67,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() @@ -82,9 +94,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge gciBridgeCfg = cfg as GciBridgeCfg; if (gciBridgeCfg == null) throw new Exception("Invalid GciBridgeCfg."); - if (!string.IsNullOrEmpty(gciBridgeCfg.ReaderName)) + /*if (!string.IsNullOrEmpty(gciBridgeCfg.ReaderName)) { - reader = TbfComponents.FindComponent(gciBridgeCfg.ReaderName, components) as UdsReaderType; + reader = TbfComponents.FindComponent(gciBridgeCfg.ReaderName, components) as UdsReaderType_LoginPasswords; if (reader == null) throw new Exception("Cannot find reader component '" + gciBridgeCfg.ReaderName + "'"); } @@ -92,7 +104,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge { writer = TbfComponents.FindComponent(gciBridgeCfg.WriterName, components) as UdsWriterType; if (writer == null) throw new Exception("Cannot find writer component '" + gciBridgeCfg.WriterName + "'"); - } + }*/ + + _gciEngine = new GciEngine(); Initialize(); } @@ -179,10 +193,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 +269,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 +308,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 +389,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 +465,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 +541,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 +614,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 +688,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 +805,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 +837,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 +908,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 +991,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 +1066,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 +1156,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 +1237,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() @@ -1239,13 +1254,13 @@ namespace TBF.Rig.BridgeComponents.GciBridge EnsureReader(); if (string.IsNullOrWhiteSpace(pcbId)) - throw new ArgumentException("PCB ID is empty.", nameof(pcbId)); + throw new ArgumentException("PCB ID is empty.", nameof(pcbId)); 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 +1276,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge } catch (Exception ex) { - log.Error("GetPasswordAsync failed.", ex); + log.Error("ReadMeterLoginPasswordAsync failed.", ex); return new UdsPasswordResult { @@ -1273,7 +1288,128 @@ namespace TBF.Rig.BridgeComponents.GciBridge } } + /// + /// 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 + /// + /// + /// Meter size used as query parameter. + /// + /// + /// Cancellation token. + /// + /// + /// Calibration parameter lookup result. + /// + public async Task 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 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 ExtractPreAdjustmentCalibrationParams( + object data) + { + Dictionary result = + new Dictionary(); + + if (data == null) + return result; + + if (data is Dictionary directDictionary) + return directDictionary; + + if (data is Dictionary objectDictionary) + { + foreach (var item in objectDictionary) + { + result[item.Key] = + item.Value?.ToString(); + } + + return result; + } + + return result; + } /// /// Reads password from UniDataStorageReader using PCB ID with retry support. @@ -1288,7 +1424,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge /// /// GetPasswordWithRetryAsync() /// -> RetryWorker.RunWithRetryAsync() - /// -> GetPasswordAsync() + /// -> ReadMeterLoginPasswordAsync() /// -> UniDataStorageReader /// /// Returns: @@ -1310,7 +1446,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 +1498,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge /// -> RetryWorker.RunWithRetryAsync() /// -> ConnectAsync() /// -> GetPcbIdAsync() - /// -> GetPasswordAsync() + /// -> ReadMeterLoginPasswordAsync() /// -> SetPasswordAsync() /// -> LoginAsync() /// @@ -1393,7 +1529,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 +1578,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 +1622,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); @@ -1533,7 +1669,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge slot); PreAdjustmentProcessResult result = - await gciExternalInterface + await _gciEngine.gciExternalInterface .PreAdjustment_PreparationAsync( slot, token) @@ -1584,7 +1720,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge slot); PreAdjustmentProcessResult result = - await gciExternalInterface + await _gciEngine.gciExternalInterface .PreAdjustment_AmplitudeTestAsync( slot, token) @@ -1635,7 +1771,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge slot); PreAdjustmentProcessResult result = - await gciExternalInterface + await _gciEngine.gciExternalInterface .PreAdjustment_TemperatureCalibrationAsync( slot, token) @@ -1680,7 +1816,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge operation, temperature); - return gciExternalInterface.PreAdjustment_PushTemperature(temperature); + return _gciEngine.gciExternalInterface.PreAdjustment_PushTemperature(temperature); } catch (Exception ex) { @@ -1713,7 +1849,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge slot); PreAdjustmentProcessResult result = - await gciExternalInterface + await _gciEngine.gciExternalInterface .PreAdjustment_OffsetTestAsync( slot, token) @@ -1764,7 +1900,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge slot); PreAdjustmentProcessResult result = - await gciExternalInterface + await _gciEngine.gciExternalInterface .PreAdjustment_CompletionAsync( slot, token) @@ -1797,9 +1933,9 @@ namespace TBF.Rig.BridgeComponents.GciBridge #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; } @@ -1834,7 +1970,7 @@ namespace TBF.Rig.BridgeComponents.GciBridge public List GetAllRegisterNames() { EnsureExternalInterface(); - return gciExternalInterface.GetAllRegisterNames(); + return _gciEngine.gciExternalInterface.GetAllRegisterNames(); } } } \ No newline at end of file diff --git a/TBF/Rig/BridgeComponents/GciBridge/Interfaces/PublicModels.cs b/TBF/Rig/BridgeComponents/GciBridge/Interfaces/PublicModels.cs index 2baa4c894..797ad39e7 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/Interfaces/PublicModels.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/Interfaces/PublicModels.cs @@ -95,6 +95,36 @@ namespace TBF.Rig.BridgeComponents.GciBridge.Interfaces } } + /// + /// Represents result of pre-adjustment calibration + /// parameter lookup. + /// + /// Parameters are returned as key/value pairs: + /// + /// Key: + /// Calibration parameter name + /// + /// Value: + /// Calibration parameter value + /// + public class UdsPreAdjustmentCalibrationParamsResult + { + public bool Success { get; set; } + public int MeterSize { get; set; } + public Dictionary 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; } diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/CombinedActionsView.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/CombinedActionsView.cs index 45f95bb5a..ce7e582fa 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/CombinedActionsView.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/CombinedActionsView.cs @@ -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); diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.Designer.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.Designer.cs index c893830fd..41c3ca1ee 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.Designer.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.Designer.cs @@ -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; } } \ No newline at end of file diff --git a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.cs b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.cs index da90e5da3..572435782 100644 --- a/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.cs +++ b/TBF/Rig/BridgeComponents/GciBridge/UI/StaraTuraAPI_GciBridge/UniDataSorageActionsView.cs @@ -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); + }); + } } } \ No newline at end of file