Output.DB.ProductionTracing : Checking previous records at the beginning of the cycle.

This commit is contained in:
Milan Hanajik 2019-03-06 13:11:01 +01:00
parent 5f6c1fe70a
commit 263d990be4
11 changed files with 603 additions and 214 deletions

View File

@ -91,12 +91,15 @@ namespace Results.Entities
public virtual int ProdQ2CorrLR { get; set; } /// iPerl Q2 correction for the L-flow written to iPerl
#endif
#if ORACLE_DB
public virtual int Pruefindex { get; set; } /// Not mapped to DB !!! 0=unknown (saving to Oracle failed), >=1 ... pruefindex
public virtual int HydrPruefung { get; set; } /// Not mapped to DB !!!
public virtual int Pruefindex { get; set; } /// >= 1 ... pruefindex
public virtual int HydrPruefung { get; set; }
public virtual int WMTypeRevision { get; set; } /// Not mapped to DB !!!
public virtual object TestInfos { get; set; } /// SensusTestInfo[] array fetched at the beginning of the cycle, not mapped to DB !!!
#endif
public virtual WaterMeterData WaterMeterData { get; set; }
public virtual int ProcessId { get; set; } /// Not mapped to DB !!! Tracing DB Process ID
public virtual bool IsLastRecordOk { get; set; } /// Not mapped to DB !!! Previous record verification result
public virtual WaterMeterData WaterMeterData { get; set; }
public virtual Batch Batch { get; set; }
public virtual IList<MeterTestRslt> MeterTestRslts { get; set; }
@ -354,6 +357,8 @@ namespace Results.Entities
WMTypeRevision = 0;
TestInfos = null;
#endif
ProcessId = 0;
IsLastRecordOk = false;
}
@ -410,6 +415,9 @@ namespace Results.Entities
WMTypeRevision = src.WMTypeRevision;
TestInfos = src.TestInfos;
#endif
ProcessId = src.ProcessId;
IsLastRecordOk = src.IsLastRecordOk;
foreach (var mtr in MeterTestRslts)
{
MeterTestRslt srcMtr = src.GetMeterTestRslt(mtr.Name(), (Config.Entities.CompoundMeterId)mtr.CompoundMeterId);

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Sensus")]
[assembly: AssemblyProduct("Results")]
[assembly: AssemblyCopyright("Copyright © 2013 - 2018 Sensus Slovensko, a.s.")]
[assembly: AssemblyCopyright("Copyright © 2013 - 2019 Sensus Slovensko, a.s.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.18.1142.0")]
[assembly: AssemblyFileVersion("2.18.1142.0")]
[assembly: AssemblyVersion("2.18.1161.0")]
[assembly: AssemblyFileVersion("2.18.1161.0")]

View File

@ -19,6 +19,8 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
public string Workplace;
public string ConnStr;
public bool CheckPreviousRecords;
public bool SaveTracingRecords;
/// Private parameterless constructor invoked by all other (public) constructors
@ -27,7 +29,9 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
ParentName = string.Empty;
Workplace = "WR10";
ConnStr = "SERVER=10.42.128.16; DATABASE=st_wr_shared_config; UID=u9305784; PASSWORD=p89344390; CHARSET=utf8;";
}
CheckPreviousRecords = true;
SaveTracingRecords = true;
}
public MonitoringCfg(string name, IComponentFactory factory)
: this()
@ -38,7 +42,12 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
public string ToString(int i)
{
return string.Format("Name={0}, Workplace={1}", Name, Workplace);
return string.Format("Name={0}, Workplace={1}, CheckPreviousRecords={2}, SaveTracingRecords={3}, ConnStr={4}",
Name,
Workplace,
CheckPreviousRecords,
SaveTracingRecords,
ConnStr);
}
}
}

View File

@ -1,10 +1,12 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
/// Copyright (c) 2018-2019 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Linq;
using log4net;
using NHibernate;
using NHibernate.Criterion;
using Config.Entities;
using TracingDB.Entities;
@ -16,37 +18,61 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
Error,
}
public class Tracing : ComponentBase, IOperation, GenericDevices.IResultsWriter, Generic.IDevice
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
{
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,
CheckPreviousRecords,
SaveTracingRecords,
}
///
CurrentOp currentOp;
bool opCompleted;
bool anyError;
/// <summary>
/// Watermeters to check at the beginning of the cycle
/// </summary>
Results.Entities.WaterMeter[] waterMeters;
/// <summary>
/// Results to print
/// Data (tracing records) to write at the end of cycle
/// </summary>
Results.Entities.Batch batch;
ISessionFactory sessionFactory; /// Factory to create database sessions initialized in the constructor
ISessionFactory sessionFactory; /// Factory to create database sessions that is initialized in the constructor
IList<Process> processes;
Dictionary<int, Process> processDictionary;
Dictionary<int, IList<Workstep>> workstepsDictionary;
///
/// 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;
public Tracing() {}
@ -67,36 +93,33 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
///
/// 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();
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();
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");
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();
if (session != null) session.Dispose();
///
/// 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();
}
currentProcess = null;
}
///
public void RunDeviceBefore() { }
public void RunDeviceAfter() { }
///
public void StopDevice()
{
if (tracingCfg.DebugLevel == DebugMode.Simulate) return;
@ -107,13 +130,31 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
session.Flush();
}
}
public void StopDevice2() {}
public void RunDeviceBefore() {}
public void RunDeviceAfter() {}
/// <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;
}
else if (currentOp != CurrentOp.None)
{
throw new Exception("Sequence error");
}
else
{
this.waterMeters = waterMeters;
currentOp = CurrentOp.CheckPreviousRecords;
return this;
}
}
/// <summary>
/// Writes the test cycle results into a file, Events: Event.ResultsWritten
@ -123,16 +164,23 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
/// <returns>Reference to the operation</returns>
public IOperation WriteResultsOp(Results.Entities.Batch batch)
{
if (currentOp != CurrentOp.None)
if (!tracingCfg.SaveTracingRecords)
{
return null;
}
else if (currentOp != CurrentOp.None)
{
throw new Exception("Sequence error");
}
else
currentOp = CurrentOp.SaveRecords;
this.batch = batch;
return this;
{
this.batch = batch;
currentOp = CurrentOp.SaveTracingRecords;
return this;
}
}
/// <summary>Start this operation</summary>
public void Start()
{
@ -144,50 +192,47 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
/// <returns>Event.ResultsWritten or Event.Error</returns>
public Event Run()
{
if (tracingCfg.DebugLevel == DebugMode.Simulate || batch.WaterMeters.Count == 0)
if (currentOp == CurrentOp.CheckPreviousRecords)
{
opCompleted = true;
return Event.ResultsWritten;
}
if (currentOp == CurrentOp.SaveRecords)
{
if (!opCompleted)
if (tracingCfg.DebugLevel == DebugMode.Simulate)
{
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);
}
return Event.InfoRead;
}
else if (!opCompleted)
{
log.WarnFormat("{0} : Run() : currentOp = {1}", Name, currentOp);
opCompleted = true;
if (CheckPreviousRecords(waterMeters) != Retv.OK) anyError = true;
return anyError ? Event.InfoNotRead : Event.InfoRead;
}
if (anyError)
return Event.ResultsNotWritten;
else
{
return anyError ? Event.InfoNotRead : Event.InfoRead;
}
}
else if (currentOp == CurrentOp.SaveTracingRecords)
{
if (tracingCfg.DebugLevel == DebugMode.Simulate || batch.WaterMeters.Count == 0)
{
return Event.ResultsWritten;
}
else if (!opCompleted)
{
log.WarnFormat("{0} : Run() : currentOp = {1}", Name, currentOp);
opCompleted = true;
if (SaveTracingRecords(batch) != Retv.OK) anyError = true;
return anyError ? Event.ResultsNotWritten : Event.ResultsWritten;
}
else
{
return anyError ? Event.ResultsNotWritten : Event.ResultsWritten;
}
}
else
{
return Event.None;
}
}
}
/// <summary>Stop this operation</summary>
public void Stop()
@ -196,19 +241,170 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
}
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];
if ((wm != null) && !string.IsNullOrEmpty(wm.SerialNr))
{
CheckPreviousRecordOfSingleWM(session, wm);
}
}
retVal = Retv.OK;
}
return retVal;
}
Retv CheckPreviousRecordOfSingleWM(ISession session, Results.Entities.WaterMeter wm)
{
///
/// 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)
{
/// No records found => IsLastRecordOk = false
wm.ProcessId = 0;
wm.IsLastRecordOk = false;
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;
}
wm.ProcessId = currentProcess.Id;
wm.IsLastRecordOk = false;
foreach (var rslt in results)
{
if ((verifiedWorkstep.Id == (int)rslt[1]) && (processId == (int)rslt[2]))
{
wm.IsLastRecordOk = true;
break;
}
}
return Retv.OK;
}
/// <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)
Retv SaveTracingRecords(Results.Entities.Batch batch)
{
int wrCount = 0;
foreach (var wMtr in batch.WaterMeters)
{
wrCount += SaveSingleWM2DB(session, wMtr);
}
return wrCount;
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();
}
}
}
@ -220,36 +416,67 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
/// <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 (string.IsNullOrEmpty(wm.SerialNr))
{
if (trialsCount > 0) ReadProcessesFromDB(session);
refRecords = session.QueryOver<ReferenceRecord>()
.Where(rr => (rr.Code == wm.SerialNr))
.OrderBy(rr => rr.TimeStamp).Desc
.List();
trialsCount++;
/// Without PCB number there is no DB activity
return 0;
}
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))
else if ((currentProcess != null) && (wm.ProcessId == currentProcess.Id))
{
session.SaveOrUpdate(new ReferenceRecord(refRecords[0].Process, worksteps[0], wm.SerialNr, Users.GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
/// 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));
return 1;
}
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;
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
///
/// 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;
}
}
@ -259,12 +486,17 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
/// <param name="session">DB session</param>
void ReadProcessesFromDB(ISession session)
{
processes = session.QueryOver<Process>().List();
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();
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);
}

View File

@ -45,14 +45,18 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
nameTextBox.Text = config.Name;
workplaceTextBox.Text = config.Workplace;
connStrTextBox.Text = config.ConnStr;
}
checkPreviousRecordsCheckBox.Checked = config.CheckPreviousRecords;
saveTracingRecordsCheckBox.Checked = config.SaveTracingRecords;
}
public void Unlock()
{
nameTextBox.Enabled = true;
workplaceTextBox.Enabled = true;
connStrTextBox.Enabled = true;
}
checkPreviousRecordsCheckBox.Enabled = true;
saveTracingRecordsCheckBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
@ -68,11 +72,13 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
if (config.Name != nameTextBox.Text)
{
config.Name = nameTextBox.Text;
flags |= CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd;
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
}
flags |= UpdateDifferent(ref config.Workplace, workplaceTextBox.Text, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
flags |= UpdateDifferent(ref config.ConnStr, connStrTextBox.Text, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
flags |= UpdateDifferent(ref config.CheckPreviousRecords, checkPreviousRecordsCheckBox.Checked, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
flags |= UpdateDifferent(ref config.SaveTracingRecords, saveTracingRecordsCheckBox.Checked, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
return flags;
}

View File

@ -38,6 +38,8 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
this.workplaceLabel = new System.Windows.Forms.Label();
this.connStrTextBox = new System.Windows.Forms.TextBox();
this.connStrLabel = new System.Windows.Forms.Label();
this.saveTracingRecordsCheckBox = new System.Windows.Forms.CheckBox();
this.checkPreviousRecordsCheckBox = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// nameTextBox
@ -100,10 +102,34 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
this.connStrLabel.TabIndex = 21;
this.connStrLabel.Text = "Connection string";
//
// saveTracingRecordsCheckBox
//
this.saveTracingRecordsCheckBox.AutoSize = true;
this.saveTracingRecordsCheckBox.Enabled = false;
this.saveTracingRecordsCheckBox.Location = new System.Drawing.Point(110, 154);
this.saveTracingRecordsCheckBox.Name = "saveTracingRecordsCheckBox";
this.saveTracingRecordsCheckBox.Size = new System.Drawing.Size(177, 17);
this.saveTracingRecordsCheckBox.TabIndex = 24;
this.saveTracingRecordsCheckBox.Text = "Save production tracing records";
this.saveTracingRecordsCheckBox.UseVisualStyleBackColor = true;
//
// checkPreviousRecordsCheckBox
//
this.checkPreviousRecordsCheckBox.AutoSize = true;
this.checkPreviousRecordsCheckBox.Enabled = false;
this.checkPreviousRecordsCheckBox.Location = new System.Drawing.Point(110, 131);
this.checkPreviousRecordsCheckBox.Name = "checkPreviousRecordsCheckBox";
this.checkPreviousRecordsCheckBox.Size = new System.Drawing.Size(138, 17);
this.checkPreviousRecordsCheckBox.TabIndex = 23;
this.checkPreviousRecordsCheckBox.Text = "Check previous records";
this.checkPreviousRecordsCheckBox.UseVisualStyleBackColor = true;
//
// TracingCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.saveTracingRecordsCheckBox);
this.Controls.Add(this.checkPreviousRecordsCheckBox);
this.Controls.Add(this.connStrTextBox);
this.Controls.Add(this.connStrLabel);
this.Controls.Add(this.workplaceTextBox);
@ -128,5 +154,7 @@ namespace TBF.BenchControl.Output.DB.ProductionTracing
private System.Windows.Forms.Label workplaceLabel;
private System.Windows.Forms.TextBox connStrTextBox;
private System.Windows.Forms.Label connStrLabel;
private System.Windows.Forms.CheckBox saveTracingRecordsCheckBox;
private System.Windows.Forms.CheckBox checkPreviousRecordsCheckBox;
}
}

View File

@ -590,8 +590,10 @@ namespace TBF.BenchControl.Sequences
///
if ((simultWithPurgingCount > 0) || (readingStartInfo.Operations.Count > 0))
{
bool completed = !(modelessDlg is GenericDevices.IHasCompleted)
|| (modelessDlg as GenericDevices.IHasCompleted).Completed;
/// Get 'bool completed'
bool completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.IHasCompleted).Completed;
if (lastDataEntryCmpnt != null) completed = completed && lastDataEntryCmpnt.Completed;
if (!completed)
{
State.Create("MainSeq : Wait until the entry form is closed")
@ -606,7 +608,9 @@ namespace TBF.BenchControl.Sequences
goto stop;
}
completed = (modelessDlg as GenericDevices.IHasCompleted).Completed;
/// Update 'bool completed'
completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.IHasCompleted).Completed;
if (lastDataEntryCmpnt != null) completed = completed && lastDataEntryCmpnt.Completed;
}
while (!completed);
}
@ -617,6 +621,7 @@ namespace TBF.BenchControl.Sequences
///
/// Read start info from the DB @ cycle start
///
if (readingStartInfo.Operations.Count > 0)
{
readingStartInfo.AddOperation(checkUiOp).EnterState();
@ -653,7 +658,12 @@ namespace TBF.BenchControl.Sequences
//----------------------------------------------------------
selection = MakeSelection(MKSelContext.InsideProcedure);
switch (selection)
if (selection == Selection.Shutdown)
{
Shutdown();
return;
}
switch (selection)
{
case Selection.Q1: selectedTestName = "Q1"; break;
case Selection.Q2: selectedTestName = "Q2"; break;
@ -1403,7 +1413,7 @@ namespace TBF.BenchControl.Sequences
if (draining3 && StateMachine.Tank3.IsEmpty()) break;
/// Quit the selection loop and leave MakeSelection()
if (e.Contains(Event.UiCmdShutdown) && (context == MKSelContext.ProcedureNotSelected)) return Selection.Shutdown;
if (e.Contains(Event.UiCmdShutdown)) return Selection.Shutdown;
if (e.Contains(Event.UiCmdBreak) && (context == MKSelContext.InsideProcedure)) return Selection.Break;
if (e.Contains(Event.UiCmdPurgeBegin)) return Selection.PurgeBegin;
if (e.Contains(Event.UiCmdPurgeEnd)) return Selection.PurgeEnd;

View File

@ -71,6 +71,9 @@ namespace TBF.BenchControl.Sequences
protected IOperation enduranceDataLoggingOp;
protected GenericDevices.IDataEntry lastDataEntryCmpnt;
///
/// Process data logging
///
@ -756,13 +759,12 @@ namespace TBF.BenchControl.Sequences
protected bool OpenCycleBeginForm()
{
IList<Event> e;
GenericDevices.IDataEntry dataEntryCmpnt =
TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IDataEntry;
if (dataEntryCmpnt is IHasCycleBeginForm)
lastDataEntryCmpnt = TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IDataEntry;
if (lastDataEntryCmpnt is IHasCycleBeginForm)
{
Bridge.OnActivity(this, Strings.Enter_water_meter_data);
State.Create("MainSeq : Enter begin data")
.AddPermanentOperation((dataEntryCmpnt as IHasCycleBeginForm).ShowCycleBeginFormOp())
.AddPermanentOperation((lastDataEntryCmpnt as IHasCycleBeginForm).ShowCycleBeginFormOp())
.AddOperation(checkUiOp)
.EnterState();
e = StateMachine.WaitRunDevsRunOps();

View File

@ -68,7 +68,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
retVal.Add(iPerlCommunicationForm.Write2HzCorrectionStr);
retVal.Add(string.Format("{0} if enabled", iPerlCommunicationForm.ReadConfigurationStr));
retVal.Add(string.Format("{0} 80", iPerlCommunicationForm.SetTestModeStr));
retVal.Add("iPerl_check pruefindex q2factors direction");
retVal.Add("iPerl_check pruefindex q2factors direction prevWorkStep");
}
else
{

View File

@ -134,7 +134,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
anyMeterError = true;
anyError = true;
message += string.Format("Príliš veľa opakovaní testu vodomera {0}{1}", wm.WMPosition, Environment.NewLine);
message += string.Format("iPerl{0} : Príliš veľa opakovaní testu vodomera{1}", wm.WMPosition, Environment.NewLine);
}
}
#endif
@ -158,6 +158,16 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
// message += string.Format("Príliš veľa opakovaní testu vodomera {0}{1}", wm.WMPosition, Environment.NewLine);
//}
}
if (arg.ToLower() == "prevworkstep")
{
if (!wm.IsLastRecordOk)
{
anyMeterError = true;
anyError = true;
message += string.Format("iPerl{0} : Predchádzajúci krok nebol zaznamenaný{1}", wm.WMPosition, Environment.NewLine);
}
}
}
mtr.TestDone = true;

View File

@ -125,105 +125,186 @@ namespace TracingDB
}
public static IList<WMPart> FindWMParts(ISession session, string pcbNumber)
{
IList<WMPart> foundParts = new List<WMPart>(); /// initially empty
/// <summary>
/// Save a reference record and related records into the database.
/// </summary>
/// <param name="session">DB session</param>
/// <param name="refRecord">Referece record</param>
public static void SaveRecords(ISession session, ReferenceRecord refRecord)
{
log.Info("Saving data to MySQL database");
if (string.IsNullOrEmpty(pcbNumber)) return foundParts; /// return an empty list
session.SaveOrUpdate(refRecord);
log.InfoFormat(" ReferenceRecord : {0}", refRecord);
foreach (var r in refRecord.Records)
{
session.SaveOrUpdate(r);
log.InfoFormat(" Record : {0}", r);
}
}
/// <summary>
/// Delete a reference record and related records from the database.
/// </summary>
/// <param name="session">DB session</param>
/// <param name="refRecord">Reference record</param>
public static void DeleteRecords(ISession session, ReferenceRecord refRecord)
{
log.Info("Deleting data from MySQL database");
foreach (var r in refRecord.Records)
{
session.Delete(r);
log.InfoFormat(" Record : {0}", r);
}
session.Delete(refRecord);
log.InfoFormat(" ReferenceRecord : {0}", refRecord);
}
/// <summary>
/// Get process of the last record with the reference part code equal to 'pcbNumber'
/// </summary>
/// <param name="session">DB session</param>
/// <param name="pcbNumber">PCB number (code)</param>
/// <returns>Process</returns>
public static Process GetProcess(ISession session, string pcbNumber)
{
if (string.IsNullOrEmpty(pcbNumber)) return null;
try
{
/// Get all already existing reference records with Code == pcbNumber, referenceRecords[0] will be the most recent one
var referenceRecords = session.QueryOver<Entities.ReferenceRecord>()
/// Read all already existing reference records with Code==pcbNumber, referenceRecords[0] will be the most recent one
var referenceRecords = session.QueryOver<ReferenceRecord>()
.Where(rr => (rr.Code == pcbNumber))
.OrderBy(rr => rr.TimeStamp).Desc
.List();
if (referenceRecords.Count == 0) return foundParts; /// Returns an empty list if no such ref. record found
if (referenceRecords.Count == 0) return null; /// Returns an empty list if no such ref. record found
foundParts.Add(new WMPart(referenceRecords[0]));
Entities.Process process = referenceRecords[0].Process;
///
foreach (var refR in referenceRecords)
{
if (process != refR.Process)
{
continue; /// skip records obtained by another process
}
IList<Entities.Record> relatedRecords = session
.QueryOver<Entities.Record>()
.Where(x => (x.ReferenceRecord == refR))
.List<Entities.Record>();
foreach (var relR in relatedRecords)
{
foundParts.Add(new WMPart(relR));
foreach (var ws in process.Worksteps)
{
if (ws.ReferencePart == relR.Part)
{
FindWMPartsRecursively(process, ws.ReferencePart, relR.Code, session, ref foundParts);
}
}
}
}
return referenceRecords[0].Process;
}
catch
{
}
return foundParts;
}
static void FindWMPartsRecursively(Entities.Process process, Entities.Part refPart, string code, ISession session, ref IList<WMPart> foundParts)
{
IList<Entities.ReferenceRecord> referenceRecords = session
.QueryOver<Entities.ReferenceRecord>()
.Where(x => (x.Workstep.ReferencePart == refPart))
.Where(x => (x.Code == code))
.OrderBy(x => x.TimeStamp).Desc
.List<Entities.ReferenceRecord>();
if (referenceRecords.Count == 0) return;
foreach (var refR in referenceRecords)
{
IList<Entities.Record> relatedRecords = session
.QueryOver<Entities.Record>()
.Where(x => (x.ReferenceRecord == refR))
.List<Entities.Record>();
foreach (var relR in relatedRecords)
{
foundParts.Add(new WMPart(relR));
foreach (var ws in process.Worksteps)
{
if (ws.ReferencePart == relR.Part)
{
FindWMPartsRecursively(process, ws.ReferencePart, relR.Code, session, ref foundParts);
}
}
}
return null;
}
}
/// <summary>
/// Finds a workstep and a part to be verified (typically a previous workstep and one of its parts).
/// Updates this.verifiedWorkstep, this.verifiedPart and this.verifyReferencePart.
/// Returns false if there is no workstep or part to be verified.
/// </summary>
/// <param name="dbSession">MySQL DB session</param>
/// <param name="process">Process to be analyzed</param>
/// <param name="workstep">Workstep to be analyzed</param>
/// <returns>true if there is a verified workstep and part</returns>
public static bool AnalyzeProcess(ISession dbSession, Process process, Workstep workstep, out Workstep verifiedWorkstep, out bool verifyReferencePart, out Part verifiedPart)
{
verifiedWorkstep = null; /// Disable any verification
verifyReferencePart = true;
verifiedPart = null;
if (process == null || workstep == null) return false;
try
{
if (workstep.ReferencePart != null)
{
IList<Workstep> worksteps = dbSession.QueryOver<Workstep>()
.Where(x => (x.Process == process))
.Where(x => (x.WorkstepNr < workstep.WorkstepNr))
.OrderBy(x => x.WorkstepNr).Asc
.List<Workstep>();
for (int i = worksteps.Count - 1; i >= 0; i--)
{
if (worksteps[i].ReferencePart != null)
{
if (worksteps[i].ReferencePart.Id == workstep.ReferencePart.Id)
{
/// Enable checking reference part
verifiedWorkstep = worksteps[i];
verifiedPart = workstep.ReferencePart;
verifyReferencePart = true;
return true;
}
foreach (var thisStepPart in workstep.Parts)
{
if (worksteps[i].ReferencePart.Id == thisStepPart.Id)
{
verifiedWorkstep = worksteps[i];
verifiedPart = worksteps[i].ReferencePart;
verifyReferencePart = true;
return true;
}
}
}
foreach (var part in worksteps[i].Parts)
{
bool isUnique = (part.CodeLocation == CodeLocation.OnPart) && ((part.CodeType == CodeType.UniqueNr)
|| (part.CodeType == CodeType.FlowtubeNr)
|| (part.CodeType == CodeType.FlowtubeNrLU));
if (isUnique)
{
if (part.Id == workstep.ReferencePart.Id)
{
/// Enable checking reference part
verifiedWorkstep = worksteps[i];
verifiedPart = part;
verifyReferencePart = false;
log.ErrorFormat("AnalyzeProcess(session , {0}, {1}) returned 'true' : verWorkstep = {2}, verPart = {3}, verRefPart = {4}",
process.Name, workstep.Name);
return true;
}
foreach (var thisStepPart in workstep.Parts)
{
if (part.Id == thisStepPart.Id)
{
verifiedWorkstep = worksteps[i];
verifiedPart = part;
verifyReferencePart = false;
return true;
}
}
}
}
}
}
log.ErrorFormat("AnalyzeProcess(session , {0}, {1}) returned 'false'", process.Name, workstep.Name);
return false;
}
catch (Exception exc)
{
log.ErrorFormat("AnalyzeProcess(session , {0}, {1}) failed : {2}", process.Name, workstep.Name, exc.Message);
return false;
}
}
/// <summary>
/// Obsolete, use WorkplaceRegistration class instead
/// </summary>
public static bool RegisterWorkplace(ISession session, string workplace, string user, string ipAddress, string processName, string workstepName, DateTime valiUntil)
{
try
{
IList<Entities.WorkplaceRegistration> wpRegs = session
.QueryOver<Entities.WorkplaceRegistration>()
IList<WorkplaceRegistration> wpRegs = session
.QueryOver<WorkplaceRegistration>()
.Where(x => (x.Workplace == workplace))
.List();
if (wpRegs.Count == 0)
{
Entities.WorkplaceRegistration wpReg = new Entities.WorkplaceRegistration(workplace, user, ipAddress, processName, workstepName);
WorkplaceRegistration wpReg = new WorkplaceRegistration(workplace, user, ipAddress, processName, workstepName);
wpRegs.Add(wpReg);
session.SaveOrUpdate(wpReg);
log.InfoFormat("RegisterWorkplace(., {0}, {1}, ...) successful (new)", workplace, user);
@ -231,11 +312,11 @@ namespace TracingDB
}
else if (wpRegs.Count == 1)
{
Entities.WorkplaceRegistration wpReg = wpRegs[0];
WorkplaceRegistration wpReg = wpRegs[0];
wpReg.Active = true;
wpReg.TimeStamp = DateTime.Now;
wpReg.ValidUntil = DateTime.Now + new TimeSpan(8, 0, 0);
wpReg.ValidUntil = valiUntil;
wpReg.UserName = user;
wpReg.IPAddress = ipAddress;
wpReg.ProcessName = processName;
@ -258,18 +339,21 @@ namespace TracingDB
}
}
/// <summary>
/// Obsolete, use WorkplaceRegistration class instead
/// </summary>
public static bool UnregisterWorkplace(ISession session, string workplace)
{
try
{
IList<Entities.WorkplaceRegistration> wpRegs = session
.QueryOver<Entities.WorkplaceRegistration>()
IList<WorkplaceRegistration> wpRegs = session
.QueryOver<WorkplaceRegistration>()
.Where(x => (x.Workplace == workplace))
.List();
if (wpRegs.Count == 1)
{
Entities.WorkplaceRegistration wpReg = wpRegs[0];
WorkplaceRegistration wpReg = wpRegs[0];
wpReg.Active = false;
wpReg.TimeStamp = DateTime.Now;