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