2018-01-26 13:19:03 +00:00
|
|
|
|
///
|
2019-03-06 12:11:01 +00:00
|
|
|
|
/// Copyright (c) 2018-2019 Sensus Slovensko a.s.
|
2018-01-26 13:19:03 +00:00
|
|
|
|
///
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2019-03-06 12:11:01 +00:00
|
|
|
|
using System.Linq;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
using log4net;
|
2018-01-29 14:40:10 +00:00
|
|
|
|
using NHibernate;
|
2019-03-06 12:11:01 +00:00
|
|
|
|
using NHibernate.Criterion;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
using Config.Entities;
|
2018-08-28 07:28:58 +00:00
|
|
|
|
using TracingDB.Entities;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
|
2018-08-28 08:12:39 +00:00
|
|
|
|
namespace TBF.BenchControl.Output.DB.ProductionTracing
|
2018-01-26 13:19:03 +00:00
|
|
|
|
{
|
|
|
|
|
|
public enum Retv
|
|
|
|
|
|
{
|
|
|
|
|
|
OK,
|
|
|
|
|
|
Error,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
class DateTimeComparer : IComparer<DateTime>
|
|
|
|
|
|
{
|
|
|
|
|
|
public int Compare(DateTime x, DateTime y)
|
|
|
|
|
|
{
|
|
|
|
|
|
return DateTime.Compare(x, y);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class Tracing : ComponentBase, IOperation, GenericDevices.IResultsWriter, GenericDevices.IStartInfoReader, Generic.IDevice
|
2018-01-26 13:19:03 +00:00
|
|
|
|
{
|
2018-08-28 08:12:39 +00:00
|
|
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(Tracing));
|
2018-08-28 08:48:39 +00:00
|
|
|
|
public override string ToString() { return string.Format("Tracing({0})", Cfg.ToString(1)); }
|
2018-01-26 13:19:03 +00:00
|
|
|
|
|
2018-01-30 10:14:12 +00:00
|
|
|
|
public const string WorkstepName = "Test_bench";
|
|
|
|
|
|
|
2018-08-28 08:48:39 +00:00
|
|
|
|
MonitoringCfg tracingCfg;
|
|
|
|
|
|
string workplace { get { return tracingCfg.Workplace; } }
|
2018-01-29 14:40:10 +00:00
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
|
2019-03-22 10:20:28 +00:00
|
|
|
|
enum OpState
|
2018-01-26 13:19:03 +00:00
|
|
|
|
{
|
|
|
|
|
|
None,
|
2019-03-22 10:20:28 +00:00
|
|
|
|
CheckPreviousRecordsScheduled,
|
|
|
|
|
|
CheckPreviousRecordsRunning,
|
|
|
|
|
|
SaveTracingRecordsScheduled,
|
|
|
|
|
|
SaveTracingRecordsRunning,
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
2019-03-06 12:11:01 +00:00
|
|
|
|
///
|
2019-03-22 10:20:28 +00:00
|
|
|
|
OpState currentOpState;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
bool opCompleted;
|
|
|
|
|
|
bool anyError;
|
|
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Watermeters to check at the beginning of the cycle
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
Results.Entities.WaterMeter[] waterMeters;
|
|
|
|
|
|
|
2018-01-26 13:19:03 +00:00
|
|
|
|
/// <summary>
|
2019-03-06 12:11:01 +00:00
|
|
|
|
/// Data (tracing records) to write at the end of cycle
|
2018-01-26 13:19:03 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
Results.Entities.Batch batch;
|
|
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
|
2019-06-04 13:32:36 +00:00
|
|
|
|
ISessionFactory sessionFactory; /// Factory to create database sessions that is initialized in the constructor
|
2018-01-29 14:40:10 +00:00
|
|
|
|
IList<Process> processes;
|
2018-01-30 10:14:12 +00:00
|
|
|
|
Dictionary<int, Process> processDictionary;
|
|
|
|
|
|
Dictionary<int, IList<Workstep>> workstepsDictionary;
|
2019-03-06 12:11:01 +00:00
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Previous workstep verification info
|
|
|
|
|
|
///
|
|
|
|
|
|
Process currentProcess; /// Currently used process
|
|
|
|
|
|
Workstep currentWorkstep; /// Currently used workstep of this test bench
|
|
|
|
|
|
Workstep verifiedWorkstep;
|
|
|
|
|
|
Part verifiedPart; /// Applicable when verifyReferencePart == false
|
|
|
|
|
|
bool verifyReferencePart;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
2018-08-28 08:12:39 +00:00
|
|
|
|
public Tracing() {}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
|
2018-08-28 08:12:39 +00:00
|
|
|
|
public Tracing(Generic.IComponentCfg cfg)
|
2018-01-26 13:19:03 +00:00
|
|
|
|
: base(cfg)
|
|
|
|
|
|
{
|
2018-08-28 08:48:39 +00:00
|
|
|
|
tracingCfg = cfg as MonitoringCfg;
|
2019-06-04 13:32:36 +00:00
|
|
|
|
if (tracingCfg == null) throw new ArgumentException("tracingCfg");
|
2019-03-22 10:20:28 +00:00
|
|
|
|
currentOpState = OpState.None;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
log.Debug(this.ToString());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-03-22 10:20:28 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// IDevice interface implementation
|
|
|
|
|
|
///
|
2018-01-26 13:19:03 +00:00
|
|
|
|
public void Initialize()
|
|
|
|
|
|
{
|
2018-08-28 08:48:39 +00:00
|
|
|
|
if (tracingCfg.DebugLevel == DebugMode.Simulate) return;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
|
|
|
|
|
|
///
|
2018-01-30 10:14:12 +00:00
|
|
|
|
/// Session factory is used to create database sessions
|
2018-01-26 13:19:03 +00:00
|
|
|
|
///
|
2019-03-06 12:11:01 +00:00
|
|
|
|
sessionFactory = FluentNHibernate.Cfg.Fluently.Configure()
|
|
|
|
|
|
.Database(FluentNHibernate.Cfg.Db.MySQLConfiguration.Standard.ConnectionString(tracingCfg.ConnStr))
|
|
|
|
|
|
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<TracingDB.Entities.Process>())
|
|
|
|
|
|
.ExposeConfiguration(TracingDB.DB.BuildSchema)
|
|
|
|
|
|
.BuildSessionFactory();
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Register this test bench in the tracing DB for approx. 2 weeks
|
|
|
|
|
|
///
|
|
|
|
|
|
ISession session = sessionFactory.OpenSession();
|
|
|
|
|
|
|
|
|
|
|
|
TracingDB.DB.RegisterWorkplace(session,
|
|
|
|
|
|
workplace,
|
|
|
|
|
|
Users.GlobalData.GetCurrentUserName(),
|
|
|
|
|
|
"1.2.3.4",
|
|
|
|
|
|
"<multiple>",
|
|
|
|
|
|
WorkstepName,
|
|
|
|
|
|
DateTime.Now + new TimeSpan(15, 0, 0, 0));
|
|
|
|
|
|
session.Flush();
|
|
|
|
|
|
session.Close();
|
2019-06-04 13:32:36 +00:00
|
|
|
|
TracingDB.DB.SessionFactory = sessionFactory;
|
2019-03-06 12:11:01 +00:00
|
|
|
|
if (session != null) session.Dispose();
|
|
|
|
|
|
|
|
|
|
|
|
currentProcess = null;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
2019-03-06 12:11:01 +00:00
|
|
|
|
///
|
|
|
|
|
|
public void RunDeviceBefore() { }
|
|
|
|
|
|
public void RunDeviceAfter() { }
|
|
|
|
|
|
///
|
2018-08-28 08:48:39 +00:00
|
|
|
|
public void StopDevice()
|
|
|
|
|
|
{
|
2018-10-15 12:42:17 +00:00
|
|
|
|
if (tracingCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
|
|
|
2018-08-28 08:48:39 +00:00
|
|
|
|
using (ISession session = sessionFactory.OpenSession())
|
|
|
|
|
|
{
|
|
|
|
|
|
TracingDB.DB.UnregisterWorkplace(session, workplace);
|
|
|
|
|
|
session.Flush();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public void StopDevice2() {}
|
|
|
|
|
|
|
2018-01-30 10:14:12 +00:00
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Reads information on start of a cycle, Events: Event.InfoRead
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="waterMeters">Results of water meters</param>
|
|
|
|
|
|
/// <returns>Reference to the operation</returns>
|
|
|
|
|
|
public IOperation ReadStartInfoOp(Results.Entities.WaterMeter[] waterMeters)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!tracingCfg.CheckPreviousRecords)
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2019-03-22 10:20:28 +00:00
|
|
|
|
else if ((currentOpState == OpState.CheckPreviousRecordsRunning) || (currentOpState == OpState.SaveTracingRecordsRunning))
|
2019-03-06 12:11:01 +00:00
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("Sequence error");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
this.waterMeters = waterMeters;
|
2019-03-22 10:20:28 +00:00
|
|
|
|
currentOpState = OpState.CheckPreviousRecordsScheduled;
|
2019-03-06 12:11:01 +00:00
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Writes the test cycle results into a file, Events: Event.ResultsWritten
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="procedure">Procedure to print the results of</param>
|
|
|
|
|
|
/// <param name="unsortedResults">Results to write into the file</param>
|
|
|
|
|
|
/// <returns>Reference to the operation</returns>
|
|
|
|
|
|
public IOperation WriteResultsOp(Results.Entities.Batch batch)
|
|
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
if (!tracingCfg.SaveTracingRecords)
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2019-03-22 10:20:28 +00:00
|
|
|
|
else if ((currentOpState == OpState.CheckPreviousRecordsRunning) || (currentOpState == OpState.SaveTracingRecordsRunning))
|
2019-03-06 12:11:01 +00:00
|
|
|
|
{
|
2018-01-26 13:19:03 +00:00
|
|
|
|
throw new Exception("Sequence error");
|
2019-03-06 12:11:01 +00:00
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
else
|
2019-03-06 12:11:01 +00:00
|
|
|
|
{
|
|
|
|
|
|
this.batch = batch;
|
2019-03-22 10:20:28 +00:00
|
|
|
|
currentOpState = OpState.SaveTracingRecordsScheduled;
|
2019-03-06 12:11:01 +00:00
|
|
|
|
return this;
|
|
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
|
2018-01-26 13:19:03 +00:00
|
|
|
|
/// <summary>Start this operation</summary>
|
|
|
|
|
|
public void Start()
|
|
|
|
|
|
{
|
2019-03-22 10:20:28 +00:00
|
|
|
|
if (currentOpState == OpState.CheckPreviousRecordsScheduled)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentOpState = OpState.CheckPreviousRecordsRunning;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (currentOpState == OpState.SaveTracingRecordsScheduled)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentOpState = OpState.SaveTracingRecordsRunning;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-01-26 13:19:03 +00:00
|
|
|
|
opCompleted = false;
|
|
|
|
|
|
anyError = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>Run this operation</summary>
|
|
|
|
|
|
/// <returns>Event.ResultsWritten or Event.Error</returns>
|
|
|
|
|
|
public Event Run()
|
|
|
|
|
|
{
|
2019-03-22 10:20:28 +00:00
|
|
|
|
if (currentOpState == OpState.CheckPreviousRecordsRunning)
|
2018-01-30 10:14:12 +00:00
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
if (tracingCfg.DebugLevel == DebugMode.Simulate)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Event.InfoRead;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!opCompleted)
|
|
|
|
|
|
{
|
2019-03-22 10:20:28 +00:00
|
|
|
|
log.WarnFormat("{0} : Run() : currentOp = {1}", Name, currentOpState);
|
2019-03-06 12:11:01 +00:00
|
|
|
|
opCompleted = true;
|
|
|
|
|
|
if (CheckPreviousRecords(waterMeters) != Retv.OK) anyError = true;
|
|
|
|
|
|
return anyError ? Event.InfoNotRead : Event.InfoRead;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return anyError ? Event.InfoNotRead : Event.InfoRead;
|
|
|
|
|
|
}
|
2018-01-30 10:14:12 +00:00
|
|
|
|
}
|
2019-03-22 10:20:28 +00:00
|
|
|
|
else if (currentOpState == OpState.SaveTracingRecordsRunning)
|
2018-01-26 13:19:03 +00:00
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
if (tracingCfg.DebugLevel == DebugMode.Simulate || batch.WaterMeters.Count == 0)
|
2018-01-26 13:19:03 +00:00
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
return Event.ResultsWritten;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!opCompleted)
|
|
|
|
|
|
{
|
2019-03-22 10:20:28 +00:00
|
|
|
|
log.WarnFormat("{0} : Run() : currentOp = {1}", Name, currentOpState);
|
2019-03-06 12:11:01 +00:00
|
|
|
|
opCompleted = true;
|
|
|
|
|
|
if (SaveTracingRecords(batch) != Retv.OK) anyError = true;
|
|
|
|
|
|
return anyError ? Event.ResultsNotWritten : Event.ResultsWritten;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
2019-03-06 12:11:01 +00:00
|
|
|
|
{
|
|
|
|
|
|
return anyError ? Event.ResultsNotWritten : Event.ResultsWritten;
|
|
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return Event.None;
|
|
|
|
|
|
}
|
2019-03-06 12:11:01 +00:00
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>Stop this operation</summary>
|
|
|
|
|
|
public void Stop()
|
|
|
|
|
|
{
|
2019-03-22 10:20:28 +00:00
|
|
|
|
currentOpState = OpState.None;
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
Retv CheckPreviousRecords(Results.Entities.WaterMeter[] waterMeters)
|
|
|
|
|
|
{
|
|
|
|
|
|
Retv retVal = Retv.Error;
|
|
|
|
|
|
|
|
|
|
|
|
using (ISession session = sessionFactory.OpenSession())
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < waterMeters.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Results.Entities.WaterMeter wm = waterMeters[i];
|
|
|
|
|
|
|
2019-06-19 09:26:39 +00:00
|
|
|
|
if ((wm != null) && !wm.Disabled)
|
2019-03-06 12:11:01 +00:00
|
|
|
|
{
|
|
|
|
|
|
CheckPreviousRecordOfSingleWM(session, wm);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
retVal = Retv.OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Retv CheckPreviousRecordOfSingleWM(ISession session, Results.Entities.WaterMeter wm)
|
|
|
|
|
|
{
|
2019-04-30 09:43:37 +00:00
|
|
|
|
if (string.IsNullOrEmpty(wm.SerialNr))
|
|
|
|
|
|
{
|
2019-05-16 11:34:46 +00:00
|
|
|
|
/// S/N is missing
|
2019-04-30 09:43:37 +00:00
|
|
|
|
wm.ProcessId = 0;
|
2019-06-19 09:26:39 +00:00
|
|
|
|
wm.LastRecordIsNok = false; /// OK, this is an RFID comm. error, not a production tracing error
|
2019-04-30 09:43:37 +00:00
|
|
|
|
return Retv.OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Get all already existing reference records with Code == wm.SerialNr, refRecords[0] will be the most recent one
|
|
|
|
|
|
///
|
|
|
|
|
|
ReferenceRecord refRecord = null;
|
|
|
|
|
|
Workstep workstep = null;
|
|
|
|
|
|
|
|
|
|
|
|
ProjectionList projections = Projections.ProjectionList();
|
|
|
|
|
|
projections.Add(Projections.Property(() => refRecord.Id)); /// rslt[0] = reference record ID
|
|
|
|
|
|
projections.Add(Projections.Property(() => workstep.Id)); /// rslt[1] = workstep ID
|
|
|
|
|
|
projections.Add(Projections.Property(() => refRecord.Process.Id)); /// rslt[2] = process ID
|
|
|
|
|
|
projections.Add(Projections.Property(() => refRecord.TimeStamp)); /// rslt[3] = reference record time stamp
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Get all reference records with Code == SerialNr from all worksteps different from 'Test_bench'
|
|
|
|
|
|
///
|
|
|
|
|
|
IList<object[]> results = session.QueryOver<ReferenceRecord>(() => refRecord)
|
|
|
|
|
|
.Where(rr => (rr.Code == wm.SerialNr))
|
|
|
|
|
|
.JoinQueryOver<Workstep>(rr => rr.Workstep, () => workstep)
|
|
|
|
|
|
.And(ws => (ws.Name != WorkstepName))
|
|
|
|
|
|
.Select(projections)
|
|
|
|
|
|
.List<object[]>();
|
|
|
|
|
|
|
|
|
|
|
|
if (results.Count == 0)
|
|
|
|
|
|
{
|
2019-05-16 11:34:46 +00:00
|
|
|
|
/// No records found
|
2019-03-06 12:11:01 +00:00
|
|
|
|
wm.ProcessId = 0;
|
2019-06-19 09:26:39 +00:00
|
|
|
|
wm.LastRecordIsNok = true; /// NOK
|
2019-05-23 07:34:03 +00:00
|
|
|
|
///
|
2019-03-06 12:11:01 +00:00
|
|
|
|
return Retv.OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Get processId of the last record
|
|
|
|
|
|
///
|
|
|
|
|
|
int processId = 0;
|
|
|
|
|
|
DateTime lastTimeStamp = DateTime.MinValue;
|
|
|
|
|
|
foreach (var rslt in results)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (DateTime.Compare((DateTime)rslt[3], lastTimeStamp) > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
lastTimeStamp = (DateTime)rslt[3];
|
|
|
|
|
|
processId = (int)rslt[2];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (processId == 0) return Retv.Error; /// This should never happen
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((currentProcess == null) || (currentProcess.Id != processId))
|
|
|
|
|
|
{
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Process changed ==> update currentProcess / currentWorkstep / verifiedWorkstep / verifiedPart / verifyReferencePart
|
|
|
|
|
|
///
|
|
|
|
|
|
var processes = session.QueryOver<Process>()
|
|
|
|
|
|
.Where(p => (p.Id == processId))
|
|
|
|
|
|
.List();
|
|
|
|
|
|
|
|
|
|
|
|
if (processes.Count != 1) return Retv.Error;
|
|
|
|
|
|
|
|
|
|
|
|
IList<Workstep> worksteps = session.QueryOver<Workstep>()
|
|
|
|
|
|
.Where(ws => (ws.Process == processes[0]))
|
|
|
|
|
|
.And( ws => (ws.Name == WorkstepName))
|
|
|
|
|
|
.List();
|
|
|
|
|
|
|
|
|
|
|
|
if (worksteps.Count != 1) return Retv.Error;
|
|
|
|
|
|
|
|
|
|
|
|
Workstep vWS;
|
|
|
|
|
|
Part vP;
|
|
|
|
|
|
bool vRP;
|
|
|
|
|
|
///
|
|
|
|
|
|
if (!TracingDB.DB.AnalyzeProcess(session, processes[0], worksteps[0], out vWS, out vRP, out vP))
|
|
|
|
|
|
{
|
|
|
|
|
|
return Retv.Error; /// Unable to
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentProcess = processes[0];
|
|
|
|
|
|
currentWorkstep = worksteps[0];
|
|
|
|
|
|
verifiedWorkstep = vWS;
|
|
|
|
|
|
verifiedPart = vP;
|
|
|
|
|
|
verifyReferencePart = vRP;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-05-16 11:34:46 +00:00
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
wm.ProcessId = currentProcess.Id;
|
2019-06-19 09:26:39 +00:00
|
|
|
|
wm.LastRecordIsNok = true; /// NOK (=default if no matching record found)
|
2019-03-06 12:11:01 +00:00
|
|
|
|
foreach (var rslt in results)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((verifiedWorkstep.Id == (int)rslt[1]) && (processId == (int)rslt[2]))
|
|
|
|
|
|
{
|
2019-05-16 11:34:46 +00:00
|
|
|
|
/// This record fits verification requirements
|
2019-06-19 09:26:39 +00:00
|
|
|
|
wm.LastRecordIsNok = false; /// OK
|
2019-03-06 12:11:01 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Retv.OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-01-30 10:14:12 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Write results of a batch of water meters to the DB
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="session">DB session</param>
|
|
|
|
|
|
/// <param name="batch">Batch entity</param>
|
2019-03-06 12:11:01 +00:00
|
|
|
|
Retv SaveTracingRecords(Results.Entities.Batch batch)
|
2018-01-26 13:19:03 +00:00
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
ITransaction transaction = null;
|
|
|
|
|
|
ISession session = null;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
session = sessionFactory.OpenSession();
|
|
|
|
|
|
transaction = session.BeginTransaction();
|
|
|
|
|
|
|
|
|
|
|
|
int writtenRecordsCount = 0;
|
|
|
|
|
|
foreach (var wMtr in batch.WaterMeters)
|
|
|
|
|
|
{
|
|
|
|
|
|
writtenRecordsCount += SaveSingleWM2DB(session, wMtr);
|
|
|
|
|
|
}
|
|
|
|
|
|
transaction.Commit();
|
|
|
|
|
|
session.Flush();
|
|
|
|
|
|
|
|
|
|
|
|
log.ErrorFormat("Batch {0}: {1} of {2} watermeters written to production tracing DB",
|
|
|
|
|
|
batch.BatchNr, writtenRecordsCount, batch.WaterMeters.Count);
|
|
|
|
|
|
|
|
|
|
|
|
return Retv.OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception exc)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (transaction != null && !transaction.WasCommitted) transaction.Rollback();
|
|
|
|
|
|
|
|
|
|
|
|
log.WarnFormat("Failed to write results of batch {0} to production tracing DB: {1}",
|
|
|
|
|
|
batch.BatchNr, exc.Message);
|
|
|
|
|
|
|
|
|
|
|
|
return Retv.Error;
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
if (session != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
session.Close();
|
|
|
|
|
|
session.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2018-01-30 10:14:12 +00:00
|
|
|
|
/// Write one meter results to the DB
|
2018-01-26 13:19:03 +00:00
|
|
|
|
/// </summary>
|
2018-01-30 10:14:12 +00:00
|
|
|
|
/// <param name="session">DB session</param>
|
|
|
|
|
|
/// <param name="wm">Watermeter entity</param>
|
|
|
|
|
|
/// <returns>Number of written reference record</returns>
|
|
|
|
|
|
int SaveSingleWM2DB(ISession session, Results.Entities.WaterMeter wm)
|
2018-01-26 13:19:03 +00:00
|
|
|
|
{
|
2019-04-30 09:43:37 +00:00
|
|
|
|
if (string.IsNullOrEmpty(wm.SerialNr) || (wm.ProcessId == 0))
|
2018-01-30 10:14:12 +00:00
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
/// Without PCB number there is no DB activity
|
|
|
|
|
|
return 0;
|
2018-01-30 10:14:12 +00:00
|
|
|
|
}
|
2019-03-06 12:11:01 +00:00
|
|
|
|
else if ((currentProcess != null) && (wm.ProcessId == currentProcess.Id))
|
2018-01-30 10:14:12 +00:00
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
/// Process is already loaded => save a reference record for this WM
|
|
|
|
|
|
session.SaveOrUpdate(new ReferenceRecord(currentProcess, currentWorkstep, wm.SerialNr, Users.GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
|
2018-01-30 10:14:12 +00:00
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2019-03-06 12:11:01 +00:00
|
|
|
|
else if (wm.ProcessId != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Process ID is already known, however process and workstep have to be loaded
|
|
|
|
|
|
IList<Process> processes = session.QueryOver<Process>()
|
|
|
|
|
|
.Where(x => (x.Id == wm.ProcessId))
|
|
|
|
|
|
.List();
|
|
|
|
|
|
if (processes.Count != 1) return 0;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var ws in processes[0].Worksteps)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ws.Name == WorkstepName)
|
|
|
|
|
|
{
|
|
|
|
|
|
session.SaveOrUpdate(new ReferenceRecord(processes[0], ws, wm.SerialNr, Users.GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0; /// No workste with 'WorkstepName' found
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Process ID is unknown => do everything from scratch
|
|
|
|
|
|
///
|
2018-01-30 10:14:12 +00:00
|
|
|
|
|
2019-03-06 12:11:01 +00:00
|
|
|
|
/// Get all already existing reference records with Code == wm.SerialNr, refRecords[0] will be the most recent one
|
|
|
|
|
|
IList<ReferenceRecord> refRecords;
|
|
|
|
|
|
int trialsCount = 0;
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
if (trialsCount > 0) ReadProcessesFromDB(session);
|
|
|
|
|
|
|
|
|
|
|
|
refRecords = session.QueryOver<ReferenceRecord>()
|
|
|
|
|
|
.Where(rr => (rr.Code == wm.SerialNr))
|
|
|
|
|
|
.OrderBy(rr => rr.TimeStamp).Desc
|
|
|
|
|
|
.List();
|
|
|
|
|
|
trialsCount++;
|
|
|
|
|
|
}
|
|
|
|
|
|
while (refRecords.Count == 0 && trialsCount <= 2);
|
|
|
|
|
|
|
|
|
|
|
|
/// Save a new reference record from this test bench if workstep "Test_bench" is defined in the obtained WM process
|
|
|
|
|
|
IList<Workstep> worksteps;
|
|
|
|
|
|
if ((refRecords.Count > 0) && workstepsDictionary.TryGetValue(refRecords[0].Process.Id, out worksteps) && (worksteps.Count == 1))
|
|
|
|
|
|
{
|
|
|
|
|
|
session.SaveOrUpdate(new ReferenceRecord(refRecords[0].Process, worksteps[0], wm.SerialNr, Users.GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|
2018-01-30 10:14:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Updates processes, processDictionary and workstepsDictionary
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="session">DB session</param>
|
|
|
|
|
|
void ReadProcessesFromDB(ISession session)
|
|
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
processes = session.QueryOver<Process>()
|
|
|
|
|
|
.List();
|
|
|
|
|
|
|
2018-01-30 10:14:12 +00:00
|
|
|
|
processDictionary = new Dictionary<int, Process>();
|
|
|
|
|
|
workstepsDictionary = new Dictionary<int, IList<Workstep>>();
|
2019-03-06 12:11:01 +00:00
|
|
|
|
///
|
2018-01-30 10:14:12 +00:00
|
|
|
|
foreach (var pr in processes)
|
|
|
|
|
|
{
|
2019-03-06 12:11:01 +00:00
|
|
|
|
IList<Workstep> worksteps = session.QueryOver<Workstep>()
|
|
|
|
|
|
.Where(ws => ((ws.Process == pr) && (ws.Name == WorkstepName)))
|
|
|
|
|
|
.List();
|
2018-01-30 10:14:12 +00:00
|
|
|
|
processDictionary.Add(pr.Id, pr);
|
|
|
|
|
|
workstepsDictionary.Add(pr.Id, worksteps);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-01-26 13:19:03 +00:00
|
|
|
|
}
|