274 lines
9.3 KiB
C#
274 lines
9.3 KiB
C#
///
|
|
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using log4net;
|
|
using NHibernate;
|
|
using Config.Entities;
|
|
using TracingDB.Entities;
|
|
|
|
namespace TBF.BenchControl.Output.DB.ProductionTracing
|
|
{
|
|
public enum Retv
|
|
{
|
|
OK,
|
|
Error,
|
|
}
|
|
|
|
public class Tracing : ComponentBase, IOperation, GenericDevices.IResultsWriter, Generic.IDevice
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(Tracing));
|
|
public override string ToString() { return string.Format("Tracing({0})", Cfg.ToString(1)); }
|
|
|
|
|
|
public const string WorkstepName = "Test_bench";
|
|
|
|
|
|
MonitoringCfg tracingCfg;
|
|
string workplace { get { return tracingCfg.Workplace; } }
|
|
|
|
enum CurrentOp
|
|
{
|
|
None,
|
|
SaveRecords,
|
|
}
|
|
|
|
CurrentOp currentOp;
|
|
bool opCompleted;
|
|
bool anyError;
|
|
|
|
/// <summary>
|
|
/// Results to print
|
|
/// </summary>
|
|
Results.Entities.Batch batch;
|
|
|
|
ISessionFactory sessionFactory; /// Factory to create database sessions initialized in the constructor
|
|
IList<Process> processes;
|
|
Dictionary<int, Process> processDictionary;
|
|
Dictionary<int, IList<Workstep>> workstepsDictionary;
|
|
|
|
|
|
public Tracing() {}
|
|
|
|
public Tracing(Generic.IComponentCfg cfg)
|
|
: base(cfg)
|
|
{
|
|
tracingCfg = cfg as MonitoringCfg;
|
|
currentOp = CurrentOp.None;
|
|
|
|
log.Debug(this.ToString());
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
if (tracingCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
///
|
|
/// Session factory is used to create database sessions
|
|
///
|
|
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();
|
|
|
|
using (ISession session = sessionFactory.OpenSession())
|
|
{
|
|
///
|
|
/// Read processes and worksteps from the database (this verifies DB connection as well)
|
|
///
|
|
log.WarnFormat("Reading processes/worksteps from production tracing DB started");
|
|
ReadProcessesFromDB(session);
|
|
log.WarnFormat("Reading processes/worksteps from production tracing DB completed");
|
|
|
|
///
|
|
/// Register the test bench workplace
|
|
///
|
|
TracingDB.DB.RegisterWorkplace(session,
|
|
workplace,
|
|
Users.GlobalData.GetCurrentUserName(),
|
|
"1.2.3.4",
|
|
"<multiple>",
|
|
WorkstepName,
|
|
DateTime.Now + new TimeSpan(15, 0, 0, 0)); /// Test Bench registered for approx. 2. weeks
|
|
session.Flush();
|
|
}
|
|
}
|
|
|
|
public void StopDevice()
|
|
{
|
|
if (tracingCfg.DebugLevel == DebugMode.Simulate) return;
|
|
|
|
using (ISession session = sessionFactory.OpenSession())
|
|
{
|
|
TracingDB.DB.UnregisterWorkplace(session, workplace);
|
|
session.Flush();
|
|
}
|
|
}
|
|
|
|
public void StopDevice2() {}
|
|
|
|
|
|
public void RunDeviceBefore() {}
|
|
public void RunDeviceAfter() {}
|
|
|
|
|
|
/// <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)
|
|
{
|
|
if (currentOp != CurrentOp.None)
|
|
throw new Exception("Sequence error");
|
|
else
|
|
currentOp = CurrentOp.SaveRecords;
|
|
|
|
this.batch = batch;
|
|
|
|
return this;
|
|
}
|
|
|
|
/// <summary>Start this operation</summary>
|
|
public void Start()
|
|
{
|
|
opCompleted = false;
|
|
anyError = false;
|
|
}
|
|
|
|
/// <summary>Run this operation</summary>
|
|
/// <returns>Event.ResultsWritten or Event.Error</returns>
|
|
public Event Run()
|
|
{
|
|
if (tracingCfg.DebugLevel == DebugMode.Simulate || batch.WaterMeters.Count == 0)
|
|
{
|
|
opCompleted = true;
|
|
return Event.ResultsWritten;
|
|
}
|
|
|
|
if (currentOp == CurrentOp.SaveRecords)
|
|
{
|
|
if (!opCompleted)
|
|
{
|
|
ITransaction transaction = null;
|
|
try
|
|
{
|
|
ISession session = sessionFactory.OpenSession();
|
|
transaction = session.BeginTransaction();
|
|
|
|
int wrCount = WriteResultsToDatabase(session, batch);
|
|
transaction.Commit();
|
|
session.Flush();
|
|
opCompleted = true;
|
|
|
|
log.ErrorFormat("Batch {0}: {1} of {2} watermeters written to production tracing DB",
|
|
batch.BatchNr, wrCount, batch.WaterMeters.Count);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
if (transaction != null && !transaction.WasCommitted) transaction.Rollback();
|
|
anyError = true;
|
|
|
|
log.WarnFormat("Failed to write results of batch {0} to production tracing DB: {1}",
|
|
batch.BatchNr, exc.Message);
|
|
}
|
|
}
|
|
|
|
if (anyError)
|
|
return Event.ResultsNotWritten;
|
|
else
|
|
return Event.ResultsWritten;
|
|
}
|
|
else
|
|
{
|
|
return Event.None;
|
|
}
|
|
}
|
|
|
|
/// <summary>Stop this operation</summary>
|
|
public void Stop()
|
|
{
|
|
currentOp = CurrentOp.None;
|
|
}
|
|
|
|
|
|
/// <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>
|
|
int WriteResultsToDatabase(ISession session, Results.Entities.Batch batch)
|
|
{
|
|
int wrCount = 0;
|
|
foreach (var wMtr in batch.WaterMeters)
|
|
{
|
|
wrCount += SaveSingleWM2DB(session, wMtr);
|
|
}
|
|
return wrCount;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Write one meter results to the DB
|
|
/// </summary>
|
|
/// <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)
|
|
{
|
|
if (string.IsNullOrEmpty(wm.SerialNr)) return 0; /// Without PCB number there is no DB activity
|
|
|
|
///
|
|
/// 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;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Updates processes, processDictionary and workstepsDictionary
|
|
/// </summary>
|
|
/// <param name="session">DB session</param>
|
|
void ReadProcessesFromDB(ISession session)
|
|
{
|
|
processes = session.QueryOver<Process>().List();
|
|
processDictionary = new Dictionary<int, Process>();
|
|
workstepsDictionary = new Dictionary<int, IList<Workstep>>();
|
|
foreach (var pr in processes)
|
|
{
|
|
IList<Workstep> worksteps = session.QueryOver<Workstep>().Where(ws => ((ws.Process == pr) && (ws.Name == WorkstepName))).List();
|
|
processDictionary.Add(pr.Id, pr);
|
|
workstepsDictionary.Add(pr.Id, worksteps);
|
|
}
|
|
}
|
|
}
|
|
}
|