From fa4bd166a09121e249fa17ff4fdb7e5fc9ee9c4e Mon Sep 17 00:00:00 2001 From: Stoyan Zlatev Date: Wed, 20 Nov 2024 11:20:09 +0100 Subject: [PATCH] sentinel apps versions crc and calibration checked --- .../CordonelDbContext.Queries.cs | 147 ++++++++++++++ .../CordonelDbContext.cs | 44 +++- .../LaaProduction.Data.Cordonel.csproj | 4 +- .../Models/CordonelAppVeriosnCrc.cs | 39 ++++ .../Models/CordonelMetrologyValues.cs | 123 ++++++++++++ .../Models/EOLProgressModel.cs | 52 ++--- .../Models/GenesisFlowModel.cs | 147 -------------- .../Sentinel/Sentinel.cs | 190 ++++++++++++++++-- 8 files changed, 555 insertions(+), 191 deletions(-) create mode 100644 LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.Queries.cs create mode 100644 LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelAppVeriosnCrc.cs create mode 100644 LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelMetrologyValues.cs delete mode 100644 LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/GenesisFlowModel.cs diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.Queries.cs b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.Queries.cs new file mode 100644 index 00000000..83df6127 --- /dev/null +++ b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.Queries.cs @@ -0,0 +1,147 @@ +namespace LaaProduction.Data.Cordonel +{ + public partial class CordonelDbContext + { + /// + /// Contains placeholder for the pcbId variable name at positon: 0 + /// + private const string LATEST_APPS_VERSIONS_CRC = @" +--------------------------------------------------------------------------------------------------- +-- Declarations +--------------------------------------------------------------------------------------------------- +DECLARE @pcbIdVarchar AS VARCHAR(20) = @{0}; +DECLARE @progressId AS INT; +DECLARE @frequency AS INT; +DECLARE @meterSize AS INT; +--------------------------------------------------------------------------------------------------- +-- Find and set latest progress id +--------------------------------------------------------------------------------------------------- +SELECT @progressId = MAX(Id) + FROM CordonelProgress + WHERE PcbId = @pcbIdVarchar +--------------------------------------------------------------------------------------------------- +-- Find and set meter size and frequency +--------------------------------------------------------------------------------------------------- +SELECT @frequency = (SELECT TOP 1 CASE WHEN idn.Charcode = 'A' + THEN 868 + WHEN idn.Charcode = 'B' + THEN 433 + ELSE 0 END + FROM AlleIdentNrVakoMerkmale AS idn + WHERE idn.IdentNr = aap.IdentNr + AND idn.Stelle = 43 + ORDER BY idn.Stelle) + , @meterSize = (SELECT TOP 1 cms.Dn_InternalId + FROM AlleIdentNrVakoMerkmale AS idn + JOIN CordonelMeterSizes AS cms + ON idn.Charcode = cms.Dn_VakoID + WHERE idn.IdentNr = aap.IdentNr + AND idn.Stelle = 4 + ORDER BY idn.Stelle) + FROM MapPcbIdToSerialNumber AS map + JOIN AuftragPositionSerienNr AS aps + ON map.MapPcbIdToSerialNumber_SerialNumber = aps.SerienNr + JOIN AlleAuftragPositionen AS aap + ON aps.AuftragNr = aap.AuftragNr + AND aps.PositionNr = aap.PositionNr + WHERE map.MapPcbIdToSerialNumber_PcbId = @pcbIdVarchar +--------------------------------------------------------------------------------------------------- +-- Select all apps with their versions and crc +--------------------------------------------------------------------------------------------------- +SELECT DISTINCT + apps.PcbId AS AppsPcbId + , apps.AppId AS AppsAppId + , apps.Version AS AppsAppVersion + , history.PcbId AS HistoryPcbId + , history.HistoryAppVersion + , history.HistoryAppCrc + , files.FlexnetAppId + , files.FlexnetVersion + , files.MetrologyVersion + , files.CoreRevisionMin + , files.CoreRevisionMax + , files.FilesAppId + , files.FilesAppVersion + , files.FilesAppCrc + , files.ClusterFileId + , files.FileName + , files.FileContent + FROM (SELECT _progress.PcbId + , RIGHT(CONVERT(VARCHAR(10), CONVERT(BINARY(1), _apps.AppId, 2), 2), 2) AS AppId + , CASE WHEN LEN(_apps.Version) >= 4 + THEN RIGHT('0' + REPLACE(_apps.Version, '.', ''), 4) + ELSE NULL END AS Version + FROM CordonelProgress AS _progress + JOIN CordonelAppVersion AS _apps + ON _progress.Id = _apps.ProgressId + WHERE _progress.Id = @progressId + AND _apps.Version IS NOT NULL) + AS apps + LEFT JOIN(SELECT _history_.PcbId + , RIGHT(_history_.HistoryAppVersion, 2) + LEFT(_history_.HistoryAppVersion, 2) AS HistoryAppVersion + , RIGHT(_history_.HistoryAppCrc, 2) + LEFT(_history_.HistoryAppCrc, 2) AS HistoryAppCrc + FROM (SELECT _history.PcbId + , LEFT(REPLACE(_history.Version, '-', ''), 4) AS HistoryAppVersion + , LEFT(REPLACE(_history.Crc, '-', ''), 4) AS HistoryAppCrc + FROM (SELECT _left.PcbId + , _left.Value AS Version + , _right.Value AS Crc + , ROW_NUMBER() OVER (PARTITION BY _left.Value ORDER BY _right.Value, _right.date DESC) AS RN + FROM GenesisMeterRegisterHistory AS _left + JOIN GenesisMeterRegisterHistory AS _right + ON _left.PcbId = _right.PcbId + AND _left.ID + 1 = _right.ID + WHERE _left.PcbId = @pcbIdVarchar + AND _left.Address = '00-01' + AND _right.Address = '00-0D') + AS _history + WHERE _history.RN = 1) + AS _history_) + AS history + ON apps.Version = history.HistoryAppVersion + LEFT JOIN(SELECT _files.FlexnetAppId + , _files.Version AS FlexnetVersion + , _files.MetrologyVersion + , _files.CoreRevisionMin + , _files.CoreRevisionMax + , _files.AppId AS FilesAppId + , RIGHT(_files.AppVersion, 2) + LEFT(_files.AppVersion, 2) AS FilesAppVersion + , RIGHT(_files.FileCrc, 2) + LEFT(_files.FileCrc, 2) AS FilesAppCrc + , _files.ClusterFileId + , _files.FileName + , _files.FileContent + FROM (SELECT DISTINCT + cluster.FileId AS ClusterFileId + , fw.FlexnetAppId + , fw.Version + , fw.CoreRevisionMin + , fw.CoreRevisionMax + , fw.MetrologyVersion + , SUBSTRING(CONVERT(VARCHAR(MAX), __files.FileContent, 2), 81, 2) AS AppId + , SUBSTRING(CONVERT(VARCHAR(MAX), __files.FileContent, 2), 13, 4) AS AppVersion + , SUBSTRING(CONVERT(VARCHAR(MAX), __files.FileContent, 2), 9, 4) AS FileCrc + , __files.FileName + , CASE WHEN __files.FileName LIKE '%.txt' + THEN CONVERT(VARCHAR(MAX), __files.FileContent, 0) + ELSE CONVERT(VARCHAR(MAX), __files.FileContent, 2) + END AS FileContent + FROM Cordonel_CurrentFw AS fw + JOIN FileClusterStore AS cluster + ON cluster.FileId = fw.FileClusterStoreId + JOIN FileMapToCluster AS filemap + ON cluster.FileId = filemap.FileMapToCluster_FileClusterId + LEFT JOIN [File] AS __files + ON filemap.FileMapToCluster_FileId = __files.FileId + WHERE fw.Metersize = @meterSize + AND fw.RadioFrequencyMhz = @frequency + AND fw.CurrentForProd = 1 + AND fw.IsReleased = 1) + AS _files) + AS files + ON apps.AppId = files.FilesAppId + WHERE apps.Version IS NOT NULL + ORDER BY apps.AppId + +"; + } +} diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.cs b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.cs index 066f0676..d03263cb 100644 --- a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.cs +++ b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/CordonelDbContext.cs @@ -7,12 +7,16 @@ using LaaProduction.Data.Cordonel.Repositories; using System; + using System.Collections.Generic; - public class CordonelDbContext + public partial class CordonelDbContext { + private readonly Action errorsCallback; + public CordonelDbContext(String connectionString, Action errorsCallback = null) { - this.SqlConnection = new SqlConnection(connectionString, errorsCallback); + this.errorsCallback = errorsCallback; + this.SqlConnection = new SqlConnection(connectionString, this.OnSqlErrors); this.EOLProgress = new EOLProgressRepository(this); this.ProductionOrders = new ProductionOrdersRepository(this); this.Requirements = new RequirementsRepository(this); @@ -20,6 +24,11 @@ this.StandardRequirements = new StandardRequirementsRepository(this); } + public void OnSqlErrors(string error) + { + errorsCallback?.Invoke(error); + } + public CordonelDbContext(SqlConnection sqlConnection, Action errorsCallback = null) { this.SqlConnection = sqlConnection; @@ -79,7 +88,32 @@ return appsDictionary; } - public GenesisFlowModel GetLatestGenesisFlowValues(Object pcbid) + public IEnumerable GetLatestAppsWithVersions(int pcbId) + => this.SqlConnection + .CreateCommand(string.Format(LATEST_APPS_VERSIONS_CRC, nameof(pcbId))) + .SetParameter(nameof(pcbId), pcbId) + .ExecuteReader(reader => new CordonelAppVeriosnCrc + { + AppsPcbId = reader.GetValue(0), + AppsAppId = reader.GetValue(1), + AppsAppVersion = reader.GetValue(2), + HistoryPcbId = reader.GetValue(3), + HistoryAppVersion = reader.GetValue(4), + HistoryAppCrc = reader.GetValue(5), + FlexnetAppId = reader.GetValue(6), + FlexnetVersion = reader.GetValue(7), + MetrologyVersion = reader.GetValue(8), + CoreRevisionMin = reader.GetValue(9), + CoreRevisionMax = reader.GetValue(10), + FilesAppId = reader.GetValue(11), + FilesAppVersion = reader.GetValue(12), + FilesAppCrc = reader.GetValue(13), + ClusterFileId = reader.GetValue(14), + FileName = reader.GetValue(15), + FileContent = reader.GetValue(16), + }); + + public CordonelMetrologyValues GetLatestGenesisFlowValues(Object pcbid) => this.SqlConnection .CreateCommand($@" SELECT TOP 1 @@ -106,10 +140,10 @@ WHERE PcbId = @{nameof(pcbid)} ORDER BY date DESC") .SetParameter(nameof(pcbid), pcbid?.ToString()) - .FirstOrDefault(reader => new GenesisFlowModel + .FirstOrDefault(reader => new CordonelMetrologyValues { Id = reader.GetValue(0), - PcbId = reader.GetValue(1), + PcbId = reader.GetValue(1), CalFactor1 = reader.GetValue(2), CalFactor2 = reader.GetValue(3), CalFactor3 = reader.GetValue(4), diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/LaaProduction.Data.Cordonel.csproj b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/LaaProduction.Data.Cordonel.csproj index c083dbf6..c49a66f1 100644 --- a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/LaaProduction.Data.Cordonel.csproj +++ b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/LaaProduction.Data.Cordonel.csproj @@ -49,6 +49,7 @@ + @@ -60,6 +61,7 @@ + @@ -73,7 +75,7 @@ - + diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelAppVeriosnCrc.cs b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelAppVeriosnCrc.cs new file mode 100644 index 00000000..fc8e723d --- /dev/null +++ b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelAppVeriosnCrc.cs @@ -0,0 +1,39 @@ +namespace LaaProduction.Data.Cordonel.Models +{ + public class CordonelAppVeriosnCrc + { + public int AppsPcbId { get; set; } + + public string AppsAppId { get; set; } + + public string AppsAppVersion { get; set; } + + public int HistoryPcbId { get; set; } + + public string HistoryAppVersion { get; set; } + + public string HistoryAppCrc { get; set; } + + public string FlexnetAppId { get; set; } + + public string FlexnetVersion { get; set; } + + public int MetrologyVersion { get; set; } + + public int CoreRevisionMin { get; set; } + + public int CoreRevisionMax { get; set; } + + public string FilesAppId { get; set; } + + public string FilesAppVersion { get; set; } + + public string FilesAppCrc { get; set; } + + public int ClusterFileId { get; set; } + + public string FileName { get; set; } + + public string FileContent { get; set; } + } +} diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelMetrologyValues.cs b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelMetrologyValues.cs new file mode 100644 index 00000000..b7c8ebc1 --- /dev/null +++ b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/CordonelMetrologyValues.cs @@ -0,0 +1,123 @@ +namespace LaaProduction.Data.Cordonel.Models +{ + using LaaPackages.Features.Cordonel; + + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + using System.Reflection; + + public class CordonelMetrologyValues + { + public Int32 Id { get; set; } + + public Int32 PcbId { get; set; } + + public Int32 CalFactor1 { get; set; } + + public Int32 CalFactor2 { get; set; } + + public Int32 CalFactor3 { get; set; } + + public Int32 ZeroOffset1 { get; set; } + + public Int32 ZeroOffset2 { get; set; } + + public Int32 ZeroOffset3 { get; set; } + + public Int32 FirstHitUpdatePeriod { get; set; } + + public Int32 FirstHitShift { get; set; } + + public Int32 FirstHitPercent1 { get; set; } + + public Int32 FirstHitPercent2 { get; set; } + + public Int32 FirstHitPercent3 { get; set; } + + public Int32 ToFTempOffset1 { get; set; } + + public Int32 ToFTempOffset2 { get; set; } + + public Int32 ToFTempOffset3 { get; set; } + + public Int32 MeterSize { get; set; } + + public DateTime Date { get; set; } + + public Boolean Successful { get; set; } + + // TODO: is right compared + public IEnumerable> CompareWithErrors(CordonelAppsDictionary appsDictionary, bool checkCalibration, bool checkZeroFlow) + { + if (!this.Successful) + { + yield return new KeyValuePair(this.PcbId.ToString(), "Genesis flow is not successful."); + } + + var genesisFlow = appsDictionary[Apps.GENESISFLOW]; + + if (checkCalibration) + { + var calFactor1 = genesisFlow[GENESISFLOW.CalFactor1].GetValue(); + var calFactor2 = genesisFlow[GENESISFLOW.CalFactor2].GetValue(); + var calFactor3 = genesisFlow[GENESISFLOW.CalFactor3].GetValue(); + var firstHitUpdatePeriod = genesisFlow[GENESISFLOW.FirstHitUpdatePeriod].GetValue(); + var firstHitShift = genesisFlow[GENESISFLOW.FirstHitShift].GetValue(); + var firstHitPercent1 = genesisFlow[GENESISFLOW.FirstHitPercent1].GetValue(); + var firstHitPercent2 = genesisFlow[GENESISFLOW.FirstHitPercent2].GetValue(); + var firstHitPercent3 = genesisFlow[GENESISFLOW.FirstHitPercent3].GetValue(); + var toFTempOffset1 = genesisFlow[GENESISFLOW.ToFTempOffset1].GetValue(); + var toFTempOffset2 = genesisFlow[GENESISFLOW.ToFTempOffset2].GetValue(); + var toFTempOffset3 = genesisFlow[GENESISFLOW.ToFTempOffset3].GetValue(); + + yield return this.ErrorIf(x => x.CalFactor1 != calFactor1); + yield return this.ErrorIf(x => x.CalFactor2 != calFactor2); + yield return this.ErrorIf(x => x.CalFactor3 != calFactor3); + yield return this.ErrorIf(x => x.FirstHitUpdatePeriod != firstHitUpdatePeriod); + yield return this.ErrorIf(x => x.FirstHitShift != firstHitShift); + yield return this.ErrorIf(x => x.FirstHitPercent1 != firstHitPercent1); + yield return this.ErrorIf(x => x.FirstHitPercent2 != firstHitPercent2); + yield return this.ErrorIf(x => x.FirstHitPercent3 != firstHitPercent3); + yield return this.ErrorIf(x => x.ToFTempOffset1 != toFTempOffset1); + yield return this.ErrorIf(x => x.ToFTempOffset2 != toFTempOffset2); + yield return this.ErrorIf(x => x.ToFTempOffset3 != toFTempOffset3); + } + + if (checkZeroFlow) + { + var zeroOffset1 = genesisFlow[GENESISFLOW.ZeroOffset1].GetValue(); + var zeroOffset2 = genesisFlow[GENESISFLOW.ZeroOffset2].GetValue(); + var zeroOffset3 = genesisFlow[GENESISFLOW.ZeroOffset3].GetValue(); + + yield return this.ErrorIf(x => x.ZeroOffset1 != zeroOffset1); + yield return this.ErrorIf(x => x.ZeroOffset2 != zeroOffset2); + yield return this.ErrorIf(x => x.ZeroOffset3 != zeroOffset3); + } + } + + private KeyValuePair ErrorIf(Expression> expression) + { + var succeeded = expression.Compile().Invoke(this); + + if (!succeeded) + { + var binaryExpression = expression.Body as BinaryExpression; + var leftMember = binaryExpression?.Left as MemberExpression; + var leftPropertyInfo = leftMember?.Member as PropertyInfo; + var name = leftPropertyInfo.Name; + var valueL = leftPropertyInfo.GetValue(this); + var valueR = Expression + .Lambda(binaryExpression?.Right) + ?.Compile() + ?.DynamicInvoke(); + + return new KeyValuePair(this.PcbId.ToString(), $"Calibration result compared to register value: {name} - {valueL} != {valueR}."); + } + else + { + return new KeyValuePair(); + } + } + } +} diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/EOLProgressModel.cs b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/EOLProgressModel.cs index 1f9502c2..29e60a74 100644 --- a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/EOLProgressModel.cs +++ b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/EOLProgressModel.cs @@ -9,89 +9,89 @@ /// /// Automatically generated at first request of EOLProgress, cannot be changed. /// - public Int32 Id { get; set; } + public Int32 Id { get; set; } // ✗ /// /// PcbId supplied with request, cannot be changed. /// - public Int32 PcbId { get; set; } + public Int32 PcbId { get; set; } // ✗ /// /// DateTime at initial request, automatically generated , cannot be changed. /// [NotNull] - public DateTime? StartDate { get; set; } + public DateTime? StartDate { get; set; } // ✗ /// /// Requirement ID if standard requirement should be used, else leave as is (null). /// [NotNull] - public Int32? StandardRequirementId { get; set; } + public Int32? StandardRequirementId { get; set; } // ✓ /// - /// Version if standard requirement should be used, else leave as is (null). + /// Version if standard requirement should be used, else leave as is (null). /// [NotNull] - public Int32? StandardRequirementVersion { get; set; } + public Int32? StandardRequirementVersion { get; set; } // ✓ /// - /// Requirement ID if special requirement should be used, else leave as is (null). + /// Requirement ID if special requirement should be used, else leave as is (null). /// - public Int32? SpecialRequirementId { get; set; } + public Int32? SpecialRequirementId { get; set; } // ✓ /// - /// Version if special requirement should be used, else leave as is (null). + /// Version if special requirement should be used, else leave as is (null). /// - public Int32? SpecialRequirementVersion { get; set; } + public Int32? SpecialRequirementVersion { get; set; } // ✓ /// - /// Requirement could be loaded for this device. + /// Requirement could be loaded for this device. /// [NotNull] [NotFailed] - public EOLStatus RequirementRequestChecked { get; set; } + public EOLStatus RequirementRequestChecked { get; set; } // ✓ /// /// Requirement PcbId equals PcbId of EOLProgress and Cordonel. /// [NotNull] [NotFailed] - public EOLStatus RequirementPcbIdChecked { get; set; } + public EOLStatus RequirementPcbIdChecked { get; set; } // ✓ /// /// Requirement order equals Cordonel order. /// [NotNull] [NotFailed] - public EOLStatus RequirementOrderChecked { get; set; } + public EOLStatus RequirementOrderChecked { get; set; } // ✓ /// /// Requirement region equals Cordonel region. /// [NotNull] [NotFailed] - public EOLStatus RequirementRegionChecked { get; set; } + public EOLStatus RequirementRegionChecked { get; set; } // ✓ /// /// Detected meter size, should never be null or empty /// will only be set if requirement MeterSIze is equal to Cordonel MeterSize. /// [NotNull] - public String ProductionStatusMeterSize { get; set; } + public String ProductionStatusMeterSize { get; set; } // ✓ /// /// Installed LUT CRC, should never be null or empty /// will only be set if requirement LUT CRC is equal to Cordonel LUT CRC. /// [NotNull] - public String ProductionStatusLutCrc { get; set; } + public String ProductionStatusLutCrc { get; set; } // ✓ /// /// Installed FW, should never be null or empty, /// will only be set if requirement FW is equal to Cordonel FW. /// [NotNull] - public String ProductionStatusFwVersion { get; set; } + public String ProductionStatusFwVersion { get; set; } // ✓ /// /// Drained battery load at EOL, should never be null @@ -124,14 +124,14 @@ /// [NotNull] [NotFailed] - public EOLStatus ProductionStatusZeroFlowChecked { get; set; } + public EOLStatus ProductionStatusZeroFlowChecked { get; set; } // ✓ /// /// Calibration process executed and parameter set /// [NotNull] [NotFailed] - public EOLStatus ProductionStatusCalibrationChecked { get; set; } + public EOLStatus ProductionStatusCalibrationChecked { get; set; } // ✓ /// /// Final configuration written with Vako, CSD ... parameters. @@ -189,34 +189,34 @@ /// [NotNull] [NotFailed] - public EOLStatus AttachmentsChecked { get; set; } + public EOLStatus AttachmentsChecked { get; set; } // ✗ /// /// Completion date of EOL process, should never be null /// [NotNull] - public DateTime? EOLCompleteDate { get; set; } + public DateTime? EOLCompleteDate { get; set; } // ✗ /// /// Name and version of EOL process, should never be null /// [NotNull] - public String EOLSoftwareNameAndVersion { get; set; } + public String EOLSoftwareNameAndVersion { get; set; } // ✗ /// /// SAP export done, added by sentinel, never set by EOL process /// - public EOLStatus SAPExportDone { get; set; } + public EOLStatus SAPExportDone { get; set; } // ✗ /// /// Sentinel completed check, added by sentinel, never set by EOL process /// - public EOLStatus SentinelCompleted { get; set; } + public EOLStatus SentinelCompleted { get; set; } // ✗ /// /// Sentinel execution and completion date, added by sentinel, never set by EOL process /// - public DateTime? SentinelCompletedDate { get; set; } + public DateTime? SentinelCompletedDate { get; set; } // ✗ public static implicit operator EOLProgressModel(int pcbId) => new EOLProgressModel { PcbId = pcbId }; } diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/GenesisFlowModel.cs b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/GenesisFlowModel.cs deleted file mode 100644 index b4478774..00000000 --- a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Models/GenesisFlowModel.cs +++ /dev/null @@ -1,147 +0,0 @@ -namespace LaaProduction.Data.Cordonel.Models -{ - using LaaPackages.Features.Cordonel; - - using System; - using System.Collections.Generic; - using System.Linq.Expressions; - using System.Reflection; - - public class GenesisFlowModel - { - public Int32 Id { get; set; } - - public String PcbId { get; set; } - - public Int32 CalFactor1 { get; set; } - - public Int32 CalFactor2 { get; set; } - - public Int32 CalFactor3 { get; set; } - - public Int32 ZeroOffset1 { get; set; } - - public Int32 ZeroOffset2 { get; set; } - - public Int32 ZeroOffset3 { get; set; } - - public Int32 FirstHitUpdatePeriod { get; set; } - - public Int32 FirstHitShift { get; set; } - - public Int32 FirstHitPercent1 { get; set; } - - public Int32 FirstHitPercent2 { get; set; } - - public Int32 FirstHitPercent3 { get; set; } - - public Int32 ToFTempOffset1 { get; set; } - - public Int32 ToFTempOffset2 { get; set; } - - public Int32 ToFTempOffset3 { get; set; } - - public Int32 MeterSize { get; set; } - - public DateTime Date { get; set; } - - public Boolean Successful { get; set; } - - public IEnumerable> IsEquals(CordonelAppsDictionary appsDictionary) - { - if (!this.Successful) - { - yield return new KeyValuePair(this.PcbId, "Genesis flow is not successful."); - } - - var genesisFlow = appsDictionary[Apps.GENESISFLOW]; - var calFactor1 = genesisFlow[GENESISFLOW.CalFactor1].GetValue(); - var calFactor2 = genesisFlow[GENESISFLOW.CalFactor2].GetValue(); - var calFactor3 = genesisFlow[GENESISFLOW.CalFactor3].GetValue(); - var zeroOffset1 = genesisFlow[GENESISFLOW.ZeroOffset1].GetValue(); - var zeroOffset2 = genesisFlow[GENESISFLOW.ZeroOffset2].GetValue(); - var zeroOffset3 = genesisFlow[GENESISFLOW.ZeroOffset3].GetValue(); - var firstHitUpdatePeriod = genesisFlow[GENESISFLOW.FirstHitUpdatePeriod].GetValue(); - var firstHitShift = genesisFlow[GENESISFLOW.FirstHitShift].GetValue(); - var firstHitPercent1 = genesisFlow[GENESISFLOW.FirstHitPercent1].GetValue(); - var firstHitPercent2 = genesisFlow[GENESISFLOW.FirstHitPercent2].GetValue(); - var firstHitPercent3 = genesisFlow[GENESISFLOW.FirstHitPercent3].GetValue(); - var toFTempOffset1 = genesisFlow[GENESISFLOW.ToFTempOffset1].GetValue(); - var toFTempOffset2 = genesisFlow[GENESISFLOW.ToFTempOffset2].GetValue(); - var toFTempOffset3 = genesisFlow[GENESISFLOW.ToFTempOffset3].GetValue(); - - yield return this.ErrorIf(x => x.CalFactor1 != calFactor1); - yield return this.ErrorIf(x => x.CalFactor2 != calFactor2); - yield return this.ErrorIf(x => x.CalFactor3 != calFactor3); - yield return this.ErrorIf(x => x.ZeroOffset1 != zeroOffset1); - yield return this.ErrorIf(x => x.ZeroOffset2 != zeroOffset2); - yield return this.ErrorIf(x => x.ZeroOffset3 != zeroOffset3); - yield return this.ErrorIf(x => x.FirstHitUpdatePeriod != firstHitUpdatePeriod); - yield return this.ErrorIf(x => x.FirstHitShift != firstHitShift); - yield return this.ErrorIf(x => x.FirstHitPercent1 != firstHitPercent1); - yield return this.ErrorIf(x => x.FirstHitPercent2 != firstHitPercent2); - yield return this.ErrorIf(x => x.FirstHitPercent3 != firstHitPercent3); - yield return this.ErrorIf(x => x.ToFTempOffset1 != toFTempOffset1); - yield return this.ErrorIf(x => x.ToFTempOffset2 != toFTempOffset2); - yield return this.ErrorIf(x => x.ToFTempOffset3 != toFTempOffset3); - } - - public IEnumerable> IsZeroFlowEquals(CordonelAppsDictionary appsDictionary) - { - if (!this.Successful) - { - yield return new KeyValuePair(this.PcbId, "Genesis flow is not successful."); - } - - var genesisFlow = appsDictionary[Apps.GENESISFLOW]; - var zeroOffset1 = genesisFlow[GENESISFLOW.ZeroOffset1].GetValue(); - var zeroOffset2 = genesisFlow[GENESISFLOW.ZeroOffset2].GetValue(); - var zeroOffset3 = genesisFlow[GENESISFLOW.ZeroOffset3].GetValue(); - - yield return this.ErrorIf(x => x.ZeroOffset1 != zeroOffset1); - yield return this.ErrorIf(x => x.ZeroOffset2 != zeroOffset2); - yield return this.ErrorIf(x => x.ZeroOffset3 != zeroOffset3); - } - - public IEnumerable> IsCalibrationEquals(CordonelAppsDictionary appsDictionary) - { - if (!this.Successful) - { - yield return new KeyValuePair(this.PcbId, "Genesis flow is not successful."); - } - - var genesisFlow = appsDictionary[Apps.GENESISFLOW]; - var calFactor1 = genesisFlow[GENESISFLOW.CalFactor1].GetValue(); - var calFactor2 = genesisFlow[GENESISFLOW.CalFactor2].GetValue(); - var calFactor3 = genesisFlow[GENESISFLOW.CalFactor3].GetValue(); - - yield return this.ErrorIf(x => x.CalFactor1 != calFactor1); - yield return this.ErrorIf(x => x.CalFactor2 != calFactor2); - yield return this.ErrorIf(x => x.CalFactor3 != calFactor3); - } - - private KeyValuePair ErrorIf(Expression> expression) - { - var succeeded = expression.Compile().Invoke(this); - - if (!succeeded) - { - var binaryExpression = expression.Body as BinaryExpression; - var leftMember = binaryExpression?.Left as MemberExpression; - var leftPropertyInfo = leftMember?.Member as PropertyInfo; - var name = leftPropertyInfo.Name; - var valueL = leftPropertyInfo.GetValue(this); - var valueR = Expression - .Lambda(binaryExpression?.Right) - ?.Compile() - ?.DynamicInvoke(); - - return new KeyValuePair(this.PcbId, $"Calibration result compared to register value: {name} - {valueL} != {valueR}."); - } - else - { - return new KeyValuePair(); - } - } - } -} diff --git a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Sentinel/Sentinel.cs b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Sentinel/Sentinel.cs index 5f464611..e17c5a84 100644 --- a/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Sentinel/Sentinel.cs +++ b/LaaProductionWeb/Data/LaaProduction.Data.Cordonel/Sentinel/Sentinel.cs @@ -32,19 +32,27 @@ try { + // Data loading this.TryGetUniqueProductionData(pcbId, out var productionData); this.TryGetEOLProgressModel(pcbId, out var eolProgress); this.TryGetCordonelRequirements(pcbId, out var requirements); this.TryGetCordonelAppsAndRegisterValues(pcbId, out var apps); + this.TryGetCordonelAppsAndFWVersionValues(pcbId, out var appsVersionsCrcs); + this.TryGetCordonelMetrologyValues(pcbId, out var metrologyValues); + + // Data comparison this.TryCompareRequirementsIdAndVersion(eolProgress, requirements, eolProgress); - this.TryCompareAllPcbIds(pcbId, productionData, requirements, apps, eolProgress); + this.TryCompareAllPcbIds(pcbId, productionData, requirements, apps, eolProgress, metrologyValues); this.TryCompareProductionOrderNumber(productionData, requirements, eolProgress); this.TryCompareRegionSizeKey(productionData, requirements, eolProgress); - this.TryCompareMeterSize(productionData, requirements, eolProgress, apps); + this.TryCompareMeterSize(productionData, requirements, eolProgress, apps, metrologyValues); this.TryCompareLUTCRCVersion(requirements, eolProgress, apps); + this.TryCompareAppsAndFWVersion(requirements, eolProgress, apps, appsVersionsCrcs); + this.TryCompareMetrologyValues(requirements, eolProgress, apps, metrologyValues); } catch (SentinelException e) { + sentinelResult.Succeeded = false; sentinelResult[e.Key] = e.Message; sentinelResult[nameof(e.Source)] = e.Source; sentinelResult[nameof(e.StackTrace)] = e.StackTrace; @@ -53,7 +61,7 @@ return sentinelResult; } - internal void TryCompareAllPcbIds(int pcbId, CordonelProductionData productionData, CordonelRequirements requirements, CordonelAppsDictionary apps, EOLProgressModel eolProgress) + internal void TryCompareAllPcbIds(int pcbId, CordonelProductionData productionData, CordonelRequirements requirements, CordonelAppsDictionary apps, EOLProgressModel eolProgress, CordonelMetrologyValues metrologyValues) { if (eolProgress.RequirementPcbIdChecked == EOLStatus.NA) { @@ -83,6 +91,16 @@ , nameof(SYSTEM.PCBSerialNumber) , registerPcbId)); } + else if (pcbId != metrologyValues.PcbId) + { + throw new SentinelException(nameof(productionData.PcbId), string.Format(errorFormat + , "parameter" + , nameof(pcbId) + , pcbId + , nameof(CordonelMetrologyValues) + , nameof(CordonelMetrologyValues.PcbId) + , metrologyValues.PcbId)); + } else if (requirements.PcbId != null) { if (pcbId != requirements.PcbId) @@ -118,6 +136,103 @@ } } + internal void TryCompareAppsAndFWVersion(CordonelRequirements requirements, EOLProgressModel eolProgress, CordonelAppsDictionary apps, CordonelAppVeriosnCrc[] appsVersionsCrcs) + { + var errorFormat = "{0}.{1}({2}) != {3}.{4}({5})"; + + if (string.IsNullOrWhiteSpace(requirements.FwVersion)) + { + throw new SentinelException(nameof(requirements.FwVersion), $"{nameof(CordonelRequirements)}.{nameof(CordonelRequirements.FwVersion)} ist erforderlich"); + } + else if (requirements.FwVersion != eolProgress.ProductionStatusFwVersion) + { + throw new SentinelException(nameof(requirements.FwVersion), string.Format(errorFormat + , nameof(CordonelRequirements) + , nameof(CordonelRequirements.FwVersion) + , requirements.FwVersion + , nameof(EOLProgressModel) + , nameof(EOLProgressModel.ProductionStatusFwVersion) + , eolProgress.ProductionStatusFwVersion)); + } + + var requirementFlexnetVersion = requirements + .FwVersion + .Replace(".", string.Empty) + .Substring(1); + var currentFlexnetVersion = default(string); + var firstIteration = true; + + foreach (var appVersionCrc in appsVersionsCrcs) + { + if (firstIteration) + { + if (appVersionCrc.AppsPcbId != appVersionCrc.HistoryPcbId) + { + throw new SentinelException(nameof(appVersionCrc.AppsPcbId), string.Format(errorFormat + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.AppsPcbId) + , appVersionCrc.AppsPcbId + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.HistoryPcbId) + , appVersionCrc.HistoryPcbId)); + } + else if (appVersionCrc.AppsAppId != appVersionCrc.FilesAppId) + { + throw new SentinelException(nameof(appVersionCrc.AppsAppId), string.Format(errorFormat + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.AppsAppId) + , appVersionCrc.AppsAppId + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.FilesAppId) + , appVersionCrc.FilesAppId)); + } + + firstIteration = !firstIteration; + } + + if (appVersionCrc.AppsAppId == byte.MaxValue.ToString("X2")) + { + // TODO: compare min max and metrology + } + else if (appVersionCrc.AppsAppVersion != appVersionCrc.HistoryAppVersion) + { + throw new SentinelException(nameof(appVersionCrc.AppsAppVersion), string.Format(errorFormat + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.AppsAppVersion) + , appVersionCrc.AppsAppVersion + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.HistoryAppVersion) + , appVersionCrc.HistoryAppVersion)); + } + else if (appVersionCrc.AppsAppVersion != appVersionCrc.FilesAppVersion) + { + throw new SentinelException(nameof(appVersionCrc.AppsAppVersion), string.Format(errorFormat + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.AppsAppVersion) + , appVersionCrc.AppsAppVersion + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.FilesAppVersion) + , appVersionCrc.FilesAppVersion)); + } + + if (appVersionCrc.AppsAppId == Apps.FLEXNETVERSION.ToString("X2")) + { + currentFlexnetVersion = appVersionCrc.HistoryAppVersion; + } + } + + if (requirementFlexnetVersion != currentFlexnetVersion) + { + throw new SentinelException(nameof(Apps.FLEXNETVERSION), string.Format(errorFormat + , nameof(CordonelRequirements) + , nameof(CordonelRequirements.FwVersion) + , requirementFlexnetVersion + , nameof(CordonelAppVeriosnCrc) + , nameof(CordonelAppVeriosnCrc.HistoryAppVersion) + , currentFlexnetVersion)); + } + } + internal void TryCompareLUTCRCVersion(CordonelRequirements requirements, EOLProgressModel eolProgress, CordonelAppsDictionary apps) { var errorFormat = "{0}.{1}({2}) != {3}.{4}({5})"; @@ -146,7 +261,7 @@ } } - internal void TryCompareMeterSize(CordonelProductionData productionData, CordonelRequirements requirements, EOLProgressModel eolProgress, CordonelAppsDictionary apps) + internal void TryCompareMeterSize(CordonelProductionData productionData, CordonelRequirements requirements, EOLProgressModel eolProgress, CordonelAppsDictionary apps, CordonelMetrologyValues metrologyValues) { var errorFormat = "{0}.{1}({2}) != {3}.{4}({5})"; var appMeterSizeValue = apps[Apps.GENESISFLOW][GENESISFLOW.MeterSize].GetValue(); @@ -171,6 +286,26 @@ , nameof(CordonelRequirements.MeterSize) , requirements.MeterSize)); } + else if (productionData.MeterSizeValue != appMeterSizeValue) + { + throw new SentinelException(nameof(productionData.PcbId), string.Format(errorFormat + , nameof(CordonelProductionData) + , nameof(CordonelProductionData.MeterSizeValue) + , productionData.MeterSizeValue + , nameof(Apps.GENESISFLOW) + , nameof(GENESISFLOW.MeterSize) + , appMeterSizeValue)); + } + else if (productionData.MeterSizeValue != metrologyValues.MeterSize) + { + throw new SentinelException(nameof(productionData.PcbId), string.Format(errorFormat + , nameof(CordonelProductionData) + , nameof(CordonelProductionData.MeterSizeValue) + , productionData.MeterSizeValue + , nameof(CordonelMetrologyValues) + , nameof(CordonelMetrologyValues.MeterSize) + , metrologyValues.MeterSize)); + } else if (requirements.MeterSize != eolProgress.ProductionStatusMeterSize) { throw new SentinelException(nameof(productionData.PcbId), string.Format(errorFormat @@ -181,15 +316,24 @@ , nameof(EOLProgressModel.ProductionStatusMeterSize) , eolProgress.ProductionStatusMeterSize)); } - else if (productionData.MeterSizeValue != appMeterSizeValue) + } + + private void TryCompareMetrologyValues(CordonelRequirements requirements, EOLProgressModel eolProgress, CordonelAppsDictionary apps, CordonelMetrologyValues metrologyValues) + { + if (requirements.SkipCalibration == true) { - throw new SentinelException(nameof(productionData.PcbId), string.Format(errorFormat - , nameof(CordonelProductionData) - , nameof(CordonelProductionData.MeterSizeValue) - , productionData.MeterSizeValue - , nameof(Apps.GENESISFLOW) - , nameof(GENESISFLOW.MeterSize) - , appMeterSizeValue)); + return; + } + + var checkCalibration = eolProgress.ProductionStatusCalibrationChecked == EOLStatus.OK; + var checkZeroFlow = eolProgress.ProductionStatusZeroFlowChecked == EOLStatus.OK; + + foreach (var kvp in metrologyValues.CompareWithErrors(apps, checkCalibration, checkZeroFlow)) + { + if (!string.IsNullOrWhiteSpace(kvp.Key)) + { + throw new SentinelException(kvp.Key, kvp.Value); + } } } @@ -318,6 +462,28 @@ } } + internal void TryGetCordonelAppsAndFWVersionValues(int pcbId, out CordonelAppVeriosnCrc[] appsVersionsCrc) + { + appsVersionsCrc = this.cordonelDbContext + .GetLatestAppsWithVersions(pcbId) + .ToArray(); + + if (appsVersionsCrc.Length <= 0) + { + throw new SentinelException(nameof(CordonelAppVeriosnCrc), "Keine ergebnisse gefunden"); + } + } + + internal void TryGetCordonelMetrologyValues(int pcbId, out CordonelMetrologyValues metrologyValues) + { + metrologyValues = this.cordonelDbContext.GetLatestGenesisFlowValues(pcbId); + + if (metrologyValues is null) + { + throw new SentinelException(nameof(CordonelMetrologyValues), "Keine ergebnisse gefunden"); + } + } + internal void TryGetCordonelRequirements(int pcbId, out CordonelRequirements requirements) { requirements = this.cordonelDbContext