diff --git a/TBF/Rig/Output/DB/DatabaseWriter/Factory.cs b/TBF/Rig/Output/DB/DatabaseWriter/Factory.cs new file mode 100644 index 000000000..cd076ef5c --- /dev/null +++ b/TBF/Rig/Output/DB/DatabaseWriter/Factory.cs @@ -0,0 +1,33 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// + +using System.Collections.Generic; +using TBF.Rig.Generic; + +namespace TBF.Rig.Output.DB.DatabaseWriter +{ + /// + /// Factory component 'DatabaseWriter' implements more storing modules + /// Mosules: + /// * store whole results in database + /// * store to specific mexico database structure - not implemented yet + /// * store configurable data SQL template to a specific database - not implemented yet + /// + public class Factory : IComponentFactory + { + public string ClassName { get { return GetType().Namespace.Substring(8); } } /// For backward compatibility + public override string ToString() { return ClassName; } + + public IComponent DummyComponent() { return new WritingToDb(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new WritingToDb(cfg); } + + public IComponentCfg DefaultConfig() { return new WriterCfg("DatabaseWriter", this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(WriterCfg.Serializer, component, this); + } + } +} diff --git a/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.cs b/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.cs new file mode 100644 index 000000000..943b9a9c9 --- /dev/null +++ b/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.cs @@ -0,0 +1,148 @@ +/// +/// Copyright (c) 2018-2019 Sensus Slovensko a.s. +/// + +using System; +using System.Collections.Generic; +using System.Net; +using Common; +using TBF.Rig.Generic; + + +namespace TBF.Rig.Output.DB.DatabaseWriter +{ + public partial class WriteDbCfgCtrl : Configs.ConfigCtrlUtils, IComponentCfgCtrl + { + public bool ShowMore { get { return false; } } + + WriterCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as WriterCfg; + Redraw(); + } + } + + public WriteDbCfgCtrl() + { + InitializeComponent(); + } + + private void WriterCfgCtrl_Load(object sender, EventArgs e) + { + if (config == null) return; + Redraw(); + } + + public void Closing() + { + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + connStrTextBox.Text = config.ConnStr; + connStr2TextBox.Text = config.ConnStr2; + checkPreviousRecordsCheckBox.Checked = config.CheckPreviousRecords; + saveTracingRecordsCheckBox.Checked = config.SaveTracingRecords; + + Network.AdapterInfo.RefreshNetAdaptersInfo(); + IList adapters = Network.AdapterInfo.NetAdapters; + + string cfgAdapter = string.Empty; + foreach (Network.AdapterInfo ai in adapters) + { + string record; + + if (ai.IPAddress == null) + { + /// This happens with network adapters that currently have no IP address, + /// for instance not connected wireless or dial-up adapters + record = "???.???.???.???"; + } + else + { + /// Do not consider IPv6 adapters as well as "Any", "Broadcast", "Loopback" or "None" addresses + if ((ai.IPAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) || + ai.IPAddress.Equals(IPAddress.Any) || + ai.IPAddress.Equals(IPAddress.Broadcast) || + ai.IPAddress.Equals(IPAddress.IPv6Any) || + ai.IPAddress.Equals(IPAddress.IPv6Loopback) || + ai.IPAddress.Equals(IPAddress.IPv6None) || + ai.IPAddress.Equals(IPAddress.Loopback) || + ai.IPAddress.Equals(IPAddress.None)) + { + continue; + } + + record = ai.IPAddress.ToString(); + } + + record += " - " + ai.Description; + int i = netAdapterComboBox.Items.Add(record); + if (ai.Description == config.NetAdapter) + { + /// Select the adapter currently in the configuration + netAdapterComboBox.SelectedIndex = i; + } + } + + /// Select the first one if the adapter from the configuration does not exist on the system + if (netAdapterComboBox.SelectedIndex < 0 && netAdapterComboBox.Items.Count > 0) + { + netAdapterComboBox.SelectedIndex = 0; + } + } + + public void Unlock() + { + nameTextBox.Enabled = true; + connStrTextBox.Enabled = true; + connStr2TextBox.Enabled = true; + netAdapterComboBox.Enabled = true; + checkPreviousRecordsCheckBox.Enabled = true; + saveTracingRecordsCheckBox.Enabled = true; + } + + public CfgUpdateFlags VerifyCfg(ref string message) + { + return CfgUpdateFlags.None; + } + + public CfgUpdateFlags UpdateCfg() + { + CfgUpdateFlags flags = CfgUpdateFlags.None; + + if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed + + if (config.Name != nameTextBox.Text) + { + config.Name = nameTextBox.Text; + flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd); + } + + flags |= UpdateDifferent(ref config.ConnStr, connStrTextBox.Text, CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd); + flags |= UpdateDifferent(ref config.ConnStr2, connStr2TextBox.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); + + /// Network adapter + string strAdapter = netAdapterComboBox.Text; + int iDash = strAdapter.IndexOf(" - "); + string netAdapter = (iDash < 0) ? "" : strAdapter.Substring(iDash + 3); + if (config.NetAdapter != netAdapter) + { + config.NetAdapter = netAdapter; + flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd); + } + + return flags; + } + } +} diff --git a/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.designer.cs b/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.designer.cs new file mode 100644 index 000000000..3d50f1b36 --- /dev/null +++ b/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.designer.cs @@ -0,0 +1,184 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +namespace TBF.Rig.Output.DB.DatabaseWriter +{ + partial class WriteDbCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = 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.netAdapterLabel = new System.Windows.Forms.Label(); + this.netAdapterComboBox = new System.Windows.Forms.ComboBox(); + this.connStr2TextBox = new System.Windows.Forms.TextBox(); + this.connStr2Label = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(117, 32); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(326, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(5, 35); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(38, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name:"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(114, 10); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // connStrTextBox + // + this.connStrTextBox.Enabled = false; + this.connStrTextBox.Location = new System.Drawing.Point(8, 74); + this.connStrTextBox.Name = "connStrTextBox"; + this.connStrTextBox.Size = new System.Drawing.Size(435, 20); + this.connStrTextBox.TabIndex = 4; + // + // connStrLabel + // + this.connStrLabel.AutoSize = true; + this.connStrLabel.Location = new System.Drawing.Point(5, 58); + this.connStrLabel.Name = "connStrLabel"; + this.connStrLabel.Size = new System.Drawing.Size(92, 13); + this.connStrLabel.TabIndex = 3; + this.connStrLabel.Text = "Connection string:"; + // + // saveTracingRecordsCheckBox + // + this.saveTracingRecordsCheckBox.AutoSize = true; + this.saveTracingRecordsCheckBox.Enabled = false; + this.saveTracingRecordsCheckBox.Location = new System.Drawing.Point(117, 221); + this.saveTracingRecordsCheckBox.Name = "saveTracingRecordsCheckBox"; + this.saveTracingRecordsCheckBox.Size = new System.Drawing.Size(177, 17); + this.saveTracingRecordsCheckBox.TabIndex = 10; + 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(117, 199); + this.checkPreviousRecordsCheckBox.Name = "checkPreviousRecordsCheckBox"; + this.checkPreviousRecordsCheckBox.Size = new System.Drawing.Size(138, 17); + this.checkPreviousRecordsCheckBox.TabIndex = 9; + this.checkPreviousRecordsCheckBox.Text = "Check previous records"; + this.checkPreviousRecordsCheckBox.UseVisualStyleBackColor = true; + // + // netAdapterLabel + // + this.netAdapterLabel.AutoSize = true; + this.netAdapterLabel.Location = new System.Drawing.Point(5, 147); + this.netAdapterLabel.Name = "netAdapterLabel"; + this.netAdapterLabel.Size = new System.Drawing.Size(89, 13); + this.netAdapterLabel.TabIndex = 7; + this.netAdapterLabel.Text = "Network adapter:"; + // + // netAdapterComboBox + // + this.netAdapterComboBox.Enabled = false; + this.netAdapterComboBox.FormattingEnabled = true; + this.netAdapterComboBox.Location = new System.Drawing.Point(8, 163); + this.netAdapterComboBox.Name = "netAdapterComboBox"; + this.netAdapterComboBox.Size = new System.Drawing.Size(435, 21); + this.netAdapterComboBox.TabIndex = 8; + // + // connStr2TextBox + // + this.connStr2TextBox.Enabled = false; + this.connStr2TextBox.Location = new System.Drawing.Point(8, 118); + this.connStr2TextBox.Name = "connStr2TextBox"; + this.connStr2TextBox.Size = new System.Drawing.Size(434, 20); + this.connStr2TextBox.TabIndex = 6; + // + // connStr2Label + // + this.connStr2Label.AutoSize = true; + this.connStr2Label.Location = new System.Drawing.Point(5, 102); + this.connStr2Label.Name = "connStr2Label"; + this.connStr2Label.Size = new System.Drawing.Size(101, 13); + this.connStr2Label.TabIndex = 5; + this.connStr2Label.Text = "Connection string 2:"; + // + // TracingCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.connStr2TextBox); + this.Controls.Add(this.connStr2Label); + this.Controls.Add(this.netAdapterComboBox); + this.Controls.Add(this.netAdapterLabel); + this.Controls.Add(this.saveTracingRecordsCheckBox); + this.Controls.Add(this.checkPreviousRecordsCheckBox); + this.Controls.Add(this.connStrTextBox); + this.Controls.Add(this.connStrLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "WriteDbCfgCtrl"; + this.Size = new System.Drawing.Size(450, 250); + this.Load += new System.EventHandler(this.WriterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.TextBox connStrTextBox; + private System.Windows.Forms.Label connStrLabel; + private System.Windows.Forms.CheckBox saveTracingRecordsCheckBox; + private System.Windows.Forms.CheckBox checkPreviousRecordsCheckBox; + private System.Windows.Forms.Label netAdapterLabel; + private System.Windows.Forms.ComboBox netAdapterComboBox; + private System.Windows.Forms.TextBox connStr2TextBox; + private System.Windows.Forms.Label connStr2Label; + } +} diff --git a/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.resx b/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TBF/Rig/Output/DB/DatabaseWriter/WriteDBCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TBF/Rig/Output/DB/DatabaseWriter/WriterCfg.cs b/TBF/Rig/Output/DB/DatabaseWriter/WriterCfg.cs new file mode 100644 index 000000000..bd5eb875b --- /dev/null +++ b/TBF/Rig/Output/DB/DatabaseWriter/WriterCfg.cs @@ -0,0 +1,57 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// + +using System.Collections.Generic; +using System.Xml.Serialization; +using TBF.Rig.Generic; + +namespace TBF.Rig.Output.DB.DatabaseWriter +{ + /// + /// Class and file name is preserved for backward compatibility + /// + public class WriterCfg : ComponentCfgBase, Generic.IComponentCfg + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(WriterCfg) })[0]; + public override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl(IList cmpntEntities) { return new WriteDbCfgCtrl(); } + + + public string ConnStr; + public string ConnStr2; + public string NetAdapter; + public bool CheckPreviousRecords; + public bool SaveTracingRecords; + + + /// Private parameterless constructor invoked by all other (public) constructors + WriterCfg() + { + ParentName = string.Empty; + NetAdapter = string.Empty; + ConnStr = "server=10.42.128.24; database=sledovanie2020; uid=vyroba2020; pwd=qwerty; charset=utf8;"; + ConnStr2 = "server=10.42.128.24; database=sledovanie2019; uid=vyroba2019; pwd=qwerty; charset=utf8;"; + CheckPreviousRecords = true; + SaveTracingRecords = true; + } + + public WriterCfg(string name, IComponentFactory factory) + : this() + { + this.Name = name; + this.Factory = factory; + } + + public string ToString(int i) + { + return string.Format("Name={0}, CheckPrev.={1}, SaveRecords={2}, ConnStr={3}, , ConnStr2={4}", + Name, + CheckPreviousRecords, + SaveTracingRecords, + ConnStr, + ConnStr2); + } + } +} diff --git a/TBF/Rig/Output/DB/DatabaseWriter/WritingToDB.cs b/TBF/Rig/Output/DB/DatabaseWriter/WritingToDB.cs new file mode 100644 index 000000000..f6f270fee --- /dev/null +++ b/TBF/Rig/Output/DB/DatabaseWriter/WritingToDB.cs @@ -0,0 +1,577 @@ +/// +/// Copyright (c) 2018-2023 Sensus Slovensko a.s. +/// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using Common; +using log4net; +using NHibernate; +using SharedDatabase; +using SharedDatabase.Entities; +using TBF.Rig.Sequences; + +namespace TBF.Rig.Output.DB.DatabaseWriter +{ + public enum Retv + { + OK, + Error, + } + + class DateTimeComparer : IComparer + { + public int Compare(DateTime x, DateTime y) + { + return DateTime.Compare(x, y); + } + } + + public class WritingToDb : ComponentBase, IOperation, GenericDevices.IResultsWriter, GenericDevices.IStartInfoReader, Generic.IDevice + { + private static readonly ILog log = LogManager.GetLogger(typeof(WritingToDb)); + public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } + + public const string WorkstepName = "Test_bench"; + + public OrderInfo DefaultOrder; + + WriterCfg tracingCfg; + string workplace + { + get + { + TBF.Rig.GenericDevices.IBenchInfo benchInfo = TBF.Rig.Sequences.ProcessData.BenchInfo; + return (benchInfo != null) ? benchInfo.TestBenchName : "TestBench"; + } + } + + IPAddress ipAddress; + IPAddress netMask; + public IPAddress IPAddress { get { return ipAddress; } } + public IPAddress NetMask { get { return netMask; } } + + enum OpState + { + None, + CheckPreviousRecordsScheduled, + CheckPreviousRecordsRunning, + SaveTracingRecordsScheduled, + SaveTracingRecordsRunning, + } + /// + OpState currentOpState; + bool opCompleted; + bool anyError; + + + /// + /// Watermeters to check at the beginning of the cycle + /// + IList waterMeters; + + /// + /// Data (tracing records) to write at the end of cycle + /// + Results.Entities.Batch batch; + + public ISessionFactory SessionFactory; /// Factory to create database sessions that is initialized in the constructor + + + public WritingToDb() {} + + public WritingToDb(Generic.IComponentCfg cfg) + : base(cfg) + { + tracingCfg = cfg as WriterCfg; + if (tracingCfg == null) throw new ArgumentException("tracingCfg"); + + Network.AdapterInfo.RefreshNetAdaptersInfo(); + Network.AdapterInfo netadapter = Network.AdapterInfo.GetNetAdapter(tracingCfg.NetAdapter); + ipAddress = netadapter.IPAddress; + + netMask = netadapter.NetMask; + currentOpState = OpState.None; + log.Warn(this.ToString()); + + DefaultOrder = null; + } + + /// + /// IDevice interface implementation + /// + public override void Initialize() + { + if (tracingCfg.DebugLevel == DebugMode.Simulate) return; + + string ipAddress = GetIPAddress(); + + /// + /// Session factory is used to create database sessions + /// + SharedDatabase.TracingDB.SessionFactory = this.SessionFactory = + FluentNHibernate.Cfg.Fluently.Configure() + .Database(FluentNHibernate.Cfg.Db.MySQLConfiguration.Standard.ConnectionString(tracingCfg.ConnStr)) + .Mappings(m => m.FluentMappings.AddFromAssemblyOf()) + .ExposeConfiguration(SharedDatabase.TracingDB.BuildSchema) + .BuildSessionFactory(); + + try + { + using (var session = SessionFactory.OpenSession()) + { + /// + /// Initialize DefaultOrder + /// + var dfltOrders = session.QueryOver() + .Where(x => x.POName == "0000001") + .And(x => (x.POState == (sbyte)OrderState.New || x.POState == (sbyte)OrderState.Active)) + .List(); + if (dfltOrders.Count > 0) DefaultOrder = dfltOrders[0]; + +#if !DEBUG + /// + /// Register this test bench in the tracing DB for approx. 2 weeks (RELEASE version only) + /// + SharedDatabase.TracingDB.RegisterWorkplaceObsolete(session, + workplace, + CurrentUser.UserName(), + GetIPAddress(), + "", + WorkstepName, + DateTime.Now + new TimeSpan(15, 0, 0, 0)); + session.Flush(); +#endif + session.Close(); + } + } + catch (Exception ex) + { + log.ErrorFormat("Cannot load a default order from a database or regster this workplace: {0}", ex); + DefaultOrder = null; + } + } + /// + string GetIPAddress() + { + return (ipAddress != null) ? ipAddress.ToString() : "1.2.3.4"; + } + /// + public void RunDeviceBefore() { } + public void RunDeviceAfter() { } + /// + public void StopDevice() + { + if (tracingCfg.DebugLevel != DebugMode.Normal) return; + + using (ISession session = SessionFactory.OpenSession()) + { + SharedDatabase.TracingDB.UnregisterWorkplaceObsolete(session, workplace); + session.Flush(); + } + } + public void StopDevice2() {} + + public IList ReadOrders() + { + try + { + using (var session = SessionFactory.OpenSession()) + { + var result = session.QueryOver() + .Where(x => (x.POState == (sbyte)OrderState.New || x.POState == (sbyte)OrderState.Active)) + .List(); + session.Close(); + return result; + } + } + catch (Exception ex) + { + log.ErrorFormat("ReadOrders() failed: {0}", ex.Message); + return new List(); + } + } + + /// + /// Read reference records belonging to a specified order. + /// Used when retrieving housing S/N-s belonging to obtained eRegister numbers. + /// + /// DB sesson + /// Order + /// List of reference records-s + public IList ReadRefRecords(ISession session, OrderInfo order, OrderInfo dfltOrder = null, Process dfltWFlow = null) + { + try + { + var refRecords = session.QueryOver() + .Where(x => (x.POName == order.POName)) + .List(); + refRecords.Reverse(); + + if (dfltOrder != null && dfltWFlow != null) + { + var moreRecords = session.QueryOver() + .Where(x => (x.POName == dfltOrder.POName)) + .And(x => (x.Workflow == dfltWFlow.Name)) + .List(); + for (int i = moreRecords.Count - 1; i >= 0; i--) refRecords.Add(moreRecords[i]); + } + + return refRecords; + } + catch (Exception exc) + { + log.ErrorFormat("Cannot read ref.records from the tracing DB: {0}", exc.Message); + return new List(); + } + } + + + /// + /// Read records belonging to a specified order + /// + /// DB sesson + /// Order + /// List of records + public IList ReadRecords(ISession session, OrderInfo order, OrderInfo dfltOrder = null, Process dfltWFlow = null) + { + try + { + var records = session.QueryOver() + .JoinQueryOver(rec => rec.ReferenceRecord) + .Where(rr => rr.POName == order.POName) + .List(); + records.Reverse(); + + if (dfltOrder != null && dfltWFlow != null) + { + var moreRecords = session.QueryOver() + .JoinQueryOver(rec => rec.ReferenceRecord) + .Where(rr => (rr.POName == dfltOrder.POName)) + .And(rr => (rr.Workflow == dfltWFlow.Name)) + .List(); + for (int i = moreRecords.Count - 1; i >= 0; i--) records.Add(moreRecords[i]); + } + + return records; + } + catch (Exception exc) + { + log.ErrorFormat("Cannot read records from the tracing DB: {0}", exc.Message); + return new List(); + } + } + + + /// + /// Reads information on start of a cycle, Events: Event.InfoRead + /// + /// Results of water meters + /// Reference to the operation + public IOperation ReadStartInfoOp(IList waterMeters) + { + if (!tracingCfg.CheckPreviousRecords) + { + return null; + } + else if ((currentOpState == OpState.CheckPreviousRecordsRunning) || (currentOpState == OpState.SaveTracingRecordsRunning)) + { + throw new Exception("Sequence error"); + } + else + { + this.waterMeters = waterMeters; + currentOpState = OpState.CheckPreviousRecordsScheduled; + return this; + } + } + + /// + /// Writes the test cycle results into a file, Events: Event.ResultsWritten + /// + /// Procedure to print the results of + /// Results to write into the file + /// Reference to the operation + public IOperation ProcessResultsOp(Results.Entities.Batch batch) + { + if (!tracingCfg.SaveTracingRecords) + { + return null; + } + else if ((currentOpState == OpState.CheckPreviousRecordsRunning) || (currentOpState == OpState.SaveTracingRecordsRunning)) + { + throw new Exception("Sequence error"); + } + else + { + this.batch = batch; + currentOpState = OpState.SaveTracingRecordsScheduled; + return this; + } + } + + + /// Start this operation + public void Start() + { + if (currentOpState == OpState.CheckPreviousRecordsScheduled) + { + currentOpState = OpState.CheckPreviousRecordsRunning; + } + else if (currentOpState == OpState.SaveTracingRecordsScheduled) + { + currentOpState = OpState.SaveTracingRecordsRunning; + } + + opCompleted = false; + anyError = false; + } + + /// Run this operation + /// Event.ResultsWritten or Event.Error + public Event Run() + { + log.WarnFormat("{0} : Run() : currentOp = {1}", Name, currentOpState); + + if (currentOpState == OpState.CheckPreviousRecordsRunning) + { + if (tracingCfg.DebugLevel == DebugMode.Simulate) return Event.InfoRead; + if (opCompleted) return anyError ? Event.InfoNotRead : Event.InfoRead; + + /// Run once + opCompleted = true; + if (CheckPreviousRecords(waterMeters) != Retv.OK) anyError = true; + return anyError ? Event.InfoNotRead : Event.InfoRead; + } + + if (currentOpState == OpState.SaveTracingRecordsRunning) + { + if (tracingCfg.DebugLevel == DebugMode.Simulate || batch.WaterMeters.Count == 0) return Event.ResultsWritten; + if (opCompleted) return anyError ? Event.ErrorProcessingResults : Event.ResultsWritten; + + /// Run once + opCompleted = true; + if (SaveTracingRecords(batch) != Retv.OK) anyError = true; + + if (anyError && !string.IsNullOrEmpty(SharedDatabase.EventsDB.ConnectionString)) + { + try + { + NHibernate.ISession session = SharedDatabase.EventsDB.CreateSession(); + SharedDatabase.EventsDB.LoadSubscribers(session); + + TBF.UiBridge.Bridge.TriggerEvent(session, Name, EventClass.ComputerResources, Severity.Error, + string.Format("Nepodarilo sa uložiť výsledky do sledovacej DB: Číslo dávky={0}", batch.BatchNr), + string.Format("Nepodarilo sa uložiť výsledky do sledovacej DB\r\nČíslo dávky = {0}", batch.BatchNr), + SubscriberGroup.Metrology | SubscriberGroup.Maintenance | SubscriberGroup.Production); + } + catch (Exception exc) + { + log.ErrorFormat("Triggering event(s) failed: {0}", exc.Message); + } + } + + return anyError ? Event.ErrorProcessingResults : Event.ResultsWritten; + } + + return Event.None; + } + + /// Stop this operation + public void Stop() + { + currentOpState = OpState.None; + } + + + Retv CheckPreviousRecords(IList waterMeters) + { + Retv retVal = Retv.Error; + + var sampleWM = waterMeters.FirstOrDefault(x => x != null && x.Disabled == false); + if (sampleWM != null) + { + using (ISession session = SessionFactory.OpenSession()) + { + for (int i = 0; i < waterMeters.Count; i++) + { + Results.Entities.WaterMeter wm = waterMeters[i]; + + if ((wm != null) && !wm.Disabled) + { + CheckPreviousRecordOfSingleWM(session, wm); + } + } + + retVal = Retv.OK; /// Successfully completed (regardless of wm.LastRecordIsNok) + } + } + + return retVal; /// Returns Retv.Error if checking not completed successfully + } + + + Retv CheckPreviousRecordOfSingleWM(ISession session, Results.Entities.WaterMeter wm) + { + if (!string.IsNullOrEmpty(wm.SerialNr) && ProcessData.WorkflowSummary != null) + { + /// Get all reference records with Code == SerialNr from all worksteps different from 'Test_bench' + var refRecords = session.QueryOver() + .Where(rr => (rr.Code1 == wm.SerialNr)) + .List(); + + if (refRecords.Count == 1) + { + ReferenceRecord refRecord = refRecords[0]; + StepRecord previousStep = string.IsNullOrEmpty(ProcessData.WorkflowSummary.PreviousWorkstepName) ? null + : refRecord.StepRecords.FirstOrDefault(x => x.Workstep == ProcessData.WorkflowSummary.PreviousWorkstepName); + + if (refRecord.Name1 == ProcessData.WorkflowSummary.Part1Name && + refRecord.Name2 == ProcessData.WorkflowSummary.Part2Name && + (ProcessData.WorkflowSummary.PreviousWorkstepName == null || + (previousStep != null && previousStep.Workstep == ProcessData.WorkflowSummary.PreviousWorkstepName))) + { + wm.Workflow = ProcessData.WorkflowSummary.Workflow.Name; + wm.LastRecordIsNok = false; /// OK + return Retv.OK; + } + } + } + + /// S/N is missing OR no records found OR workflows do not match OR previous StepRecord is missing + wm.Workflow = string.Empty; + wm.LastRecordIsNok = true; /// NOK + return Retv.OK; + } + + + /// + /// Write results of a batch of water meters to the DB + /// + /// DB session + /// Batch entity + Retv SaveTracingRecords(Results.Entities.Batch batch) + { + ITransaction transaction = null; + ISession session = null; + + var order = ProcessData.OrderInfo as SharedDatabase.Entities.OrderInfo; + if (order != null && ProcessData.WorkflowSummary != null && !string.IsNullOrEmpty(ProcessData.WorkflowSummary.WorkstepName)) + { + /// + /// Save to regular tracing DB + /// + try + { + session = SessionFactory.OpenSession(); + transaction = session.BeginTransaction(); + + string workplace = (ProcessData.BenchInfo != null) ? ProcessData.BenchInfo.TestBenchName : "TestBench"; + int writtenRecordsCount = 0; + foreach (var wm in batch.WaterMeters) + { + if (!wm.Disabled && !string.IsNullOrEmpty(wm.SerialNr)) + { + writtenRecordsCount += SaveSingleWM2DB(session, wm, order.POName, ProcessData.WorkflowSummary, workplace); + } + } + + transaction.Commit(); + session.Flush(); + + log.WarnFormat("Batch {0}: {1} of {2} watermeters written to the regular production tracing DB", + batch.BatchNr, writtenRecordsCount, batch.WaterMeters.Count); + } + catch (Exception exc) + { + if (transaction != null && !transaction.WasCommitted) transaction.Rollback(); + + log.ErrorFormat("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(); + } + } + } + + return Retv.OK; + } + + /// + /// Write one meter results to the DB + /// + /// DB session + /// Watermeter entity + int SaveSingleWM2DB(ISession session, Results.Entities.WaterMeter wm, string poName, WorkflowSummary wflowSummary, string worplace) + { + if (string.IsNullOrEmpty(wflowSummary.WorkstepName)) return 0; + + IList existingRecords = session.QueryOver() + .Where(x => (x.Code1 == wm.SerialNr)) + .List(); + if (existingRecords.Count > 1) + { + /// Unexpected error + log.ErrorFormat("Multiple reference records exist: Code1 = {0}", wm.SerialNr); + return 0; + } + + /// + /// Reference record + /// + ReferenceRecord refRecord = null; + if (existingRecords.Count == 1) + { + /// TODO: Check if the selected worflow is the same as in the found record + refRecord = existingRecords[0]; + + refRecord.POName = poName; + refRecord.Workflow = wflowSummary.Workflow.Name; + refRecord.Code2 = wm.SerialNrAux; + refRecord.Code3 = wm.CompleteSerialNr; + refRecord.Code4 = wm.RadioAddress; + } + else + { + refRecord = new ReferenceRecord(poName, + wflowSummary.Workflow.Name, + wflowSummary.Part1Name, /// PCB (iPERL) or housing (620/640) SAP number + wm.SerialNr, /// PcbNumber (iPERL) or housing S/N (620/640) + wflowSummary.Part2Name, /// Flowtube SAP nummber (iPERL) or "eRegister#" (640) or empty + wm.SerialNrAux, /// Flowtube S/N (iPERL) or eRegister number (640) or empty + wm.CompleteSerialNr, /// Complete assigned S/N + wm.RadioAddress); /// Radio address (iPERL and 640) + } + + /// + /// Step record + /// + StepRecord stepRecord = new StepRecord(refRecord, + wflowSummary.WorkstepName, + workplace, + Common.CurrentUser.UserName(), + wm.PassedFromTests() ? 0 : 1); + if (refRecord.StepRecords == null) + { + refRecord.StepRecords = new List { stepRecord }; + } + else + { + refRecord.StepRecords.Add(stepRecord); + } + + session.SaveOrUpdate(refRecord); + session.SaveOrUpdate(stepRecord); + return 1; + } + } +} diff --git a/TBF/Rig/TbfComponents.cs b/TBF/Rig/TbfComponents.cs index b92a08765..639d72a98 100644 --- a/TBF/Rig/TbfComponents.cs +++ b/TBF/Rig/TbfComponents.cs @@ -91,6 +91,7 @@ namespace TBF.Rig new Network.Camera.RoiForFixedStartKeyence.Factory(), new Network.Comet.Ambient.Factory(), new Network.RestAPI.Factory(), + new Output.DB.DatabaseWriter.Factory(), // 'DatabaseWriter' module implements more store specific modules new Output.DB.ProductionTracing.Factory(), new Output.DB.SaveDiverterCorrections.Factory(), new Output.DB.SaveFlowmeterCorrections.Factory(), diff --git a/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs b/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs index fdc65f6b9..9efbec11d 100644 --- a/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs +++ b/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs @@ -6,10 +6,13 @@ using System.Collections.Generic; using System.Text; using log4net; using Common; +using Config.Entities; +using Results.Entities; using TBF.Rig; using TBF.Rig.GenericDevices; using TBF.Boxes; using TBF.Resources; +using TBF.Rig.TestMethods.GenesisCommunication.GenesisHead; using TBF.UiBridge; namespace TBF.Rig.TestMethods.FlyingStart @@ -135,6 +138,8 @@ namespace TBF.Rig.TestMethods.FlyingStart Bridge.OnTestSelected(this, new TestSelectedEventArgs(test, repetitionNr, inPath, benchPath, outPath, sensPath, heatMetersPath)); string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr); TestStartTime = DateTime.Now; + // Genesis switch + bool atleastOneGenesis = GenesisHeadBatch.Start(sensPath.RegisterReaders, Program.LocalSettings.LastSNTexts); /// /// Optionally display prompt to emerge temperature meters to appropriate baths for heat meters test @@ -323,6 +328,20 @@ namespace TBF.Rig.TestMethods.FlyingStart temperature_set: + //TODO genesis - check with genesis switch + if (atleastOneGenesis) + { + if (test.Name.ToLower().Contains("calib")) + { + GenesisHeadBatch.BatchHolder.Value.MetersLogin(); + GenesisHeadBatch.BatchHolder.Value.MetersInitCalibration(); + + } else if (test.Name.ToLower().Contains("Init")) + { + GenesisHeadBatch.BatchHolder.Value.MetersLogin(); + GenesisHeadBatch.BatchHolder.Value.MetersInitMeasurement(); + } + } /// /// Prepare cameras, ROI-s and measurementOperations /// @@ -358,7 +377,12 @@ namespace TBF.Rig.TestMethods.FlyingStart foreach (var rr in sensPath.RegisterReaders) { - if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr); + if (rr is IRegReaderDatastream) + (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr); + + if (rr is GenesisHead) // Genesis - CORDONEL head + (rr as GenesisHead).StartRead(test.Name, BatchRslts.Batch.BatchNr, repetitionNr); + } @@ -426,8 +450,21 @@ namespace TBF.Rig.TestMethods.FlyingStart /// Measurement loop end StopRecordingStatistics(); + + //TODO genesis - check with genesis switch + if (atleastOneGenesis) + { + if (test.Name.ToLower().Contains("calib")) + { + GenesisHeadBatch.BatchHolder.Value.MetersStopCalibration(); + } + else if (test.Name.ToLower().Contains("Init")) + { + GenesisHeadBatch.BatchHolder.Value.MetersStopMeasurement(); + } + } - //------------------------------------------------ + //------------------------------------------------ Bridge.OnActivity(this, Strings.Test_completed); //------------------------------------------------ @@ -589,6 +626,7 @@ namespace TBF.Rig.TestMethods.FlyingStart GenericDevices.IRegReaderDatastream dstrReader = regReader as GenericDevices.IRegReaderDatastream; TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = regReader as TestMethods.iPerlCommunication.iPerlHead.IperlHead; GenericDevices.IRegReaderLiveCamera cameraRoi = regReader as GenericDevices.IRegReaderLiveCamera; + GenesisHead Genesis = regReader as GenesisHead; if (meterRslt != null && regReader != null) { @@ -596,83 +634,147 @@ namespace TBF.Rig.TestMethods.FlyingStart meterRslt.PulsesPerLiter = regReader.PulsesPerLtr; meterRslt.PulsesMeter = Convert.ToDouble(regReader.WMPulses); - if (dstrReader != null) - { - meterRslt.TimestampStart = dstrReader.TimestampSecStart; - meterRslt.TimestampEnd = dstrReader.NoSamples ? (dstrReader.TimestampSecStart + tstRslt.TestTime) : dstrReader.TimestampSecEnd; - meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart; - meterRslt.VolumeStart = dstrReader.VolumeLtrStart; /// liter - meterRslt.VolumeEnd = dstrReader.VolumeLtrEnd; /// liter - meterRslt.VolumeMeter = Math.Abs(dstrReader.VolumeLtrEnd - dstrReader.VolumeLtrStart); - meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime; - meterRslt.PulsesMaster = tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime; + + if (Genesis != null) + { + Genesis.Stop(tstRslt.TestTime, tstRslt.VolumeCTV); - if (iPerl != null) + meterRslt.TimestampStart = Genesis.TimestampSecStart; + meterRslt.TimestampEnd = Genesis.TimestampSecEnd; + meterRslt.TestTime = Genesis.WMTestTime; + meterRslt.VolumeStart = Genesis.BeginWMState; + meterRslt.VolumeEnd = Genesis.EndWMState; /// liter + meterRslt.VolumeMeter = Math.Abs(Genesis.WMVolume); + meterRslt.VolumeRef = tstRslt.VolumeCTV; + if (GenesisHeadBatch.MeterIdDetailResults == null) { - if (iPerl.ResultCode != 0 && (meterRslt.WaterMeter.ResultCode & (int)Results.Entities.ResultCode.OptoErrorCodeMask) == 0) + Genesis.Log("MeterIdDetailResults na!"); + } + else + { + if (Genesis.DetailedResults != null) { - meterRslt.WaterMeter.ResultCode |= iPerl.ResultCode; + try + { + GenesisHeadBatch.MeterIdDetailResults.Add(meterRslt.SerialNr(), Genesis.DetailedResults); + } + catch (Exception ex) { Genesis.Log(ex.Message.ToString()); } } -#if IPERL - meterRslt.WaterMeter.CalibFactor = iPerl.CalibFactor; - meterRslt.ExtraDataPath = iPerl.ExtraDataPath; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 1) meterRslt.X1 = iPerl.X[0]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 2) meterRslt.X2 = iPerl.X[1]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 3) meterRslt.X3 = iPerl.X[2]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 4) meterRslt.X4 = iPerl.X[3]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 5) meterRslt.X5 = iPerl.X[4]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 6) meterRslt.X6 = iPerl.X[5]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 7) meterRslt.X7 = iPerl.X[6]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 8) meterRslt.X8 = iPerl.X[7]; - if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 9) meterRslt.X9 = iPerl.X[8]; -#endif - iPerl.LastTestResult2 = iPerl.LastTestResult; /// Save shift previous test result - iPerl.LastTestResult = meterRslt; /// Save this test result - } - } - else if (cameraRoi != null) - { - meterRslt.TimestampStart = cameraRoi.TimestampStart; /// second - meterRslt.TimestampEnd = cameraRoi.TimestampEnd; /// second - - meterRslt.VolumeStart = cameraRoi.VolumeStart; /// liter - meterRslt.VolumeEnd = cameraRoi.VolumeEnd; /// liter - meterRslt.VolumeMeter = cameraRoi.VolumeEnd - cameraRoi.VolumeStart; /// liter - - if (meterRslt.VolumeMeter != 0) - { - /// Normal measurement with camera - meterRslt.TestTime = cameraRoi.TimestampEnd - cameraRoi.TimestampStart; /// second - meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime; - meterRslt.PulsesMaster = tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime; - } - else - { - /// None or one pulse from the water meter using camera - meterRslt.TestTime = tstRslt.TestTime; - meterRslt.VolumeRef = tstRslt.VolumeCTV; - meterRslt.PulsesMaster = tstRslt.PulsesMaster; + else + { + Genesis.Log("DetailedResults na!"); + } } + + Genesis.Log("VolumeRef=" + meterRslt.VolumeRef); + Genesis.Log("TestTime Meter =" + meterRslt.TestTime + "S, test time ref =" + tstRslt.TestTime + "s"); + Genesis.Log(" results for " + test.Name); + Genesis.Log(" Ref Vol = " + meterRslt.VolumeRef + " m³"); + Genesis.Log(" Ref Time = " + tstRslt.TestTime + " s"); + Genesis.Log(" Meter Time = " + meterRslt.TestTime + " s"); + Genesis.Log(" Meter Vol = " + meterRslt.VolumeMeter + " m³"); + + var calError = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef); + Genesis.Log(" MeterError = " + calError.ToString() + " %"); } - else - { - meterRslt.PulsesMaster = Convert.ToDouble(regReader.WMRefPulses); - meterRslt.VolumeStart = 0; - meterRslt.VolumeEnd = 0; - meterRslt.VolumeMeter = meterRslt.PulsesMeter * regReader.LtrsPerPulse; /// liter - /// - if (regReader.WMPulses >= 1) - { - /// Normal measurement - meterRslt.TestTime = cBrd.TestTimeWM(regReader.Position); - meterRslt.VolumeRef = meterRslt.PulsesMaster * tstRslt.ConstMaster; /// liter - } - else - { - /// None or one pulse from the water meter - meterRslt.TestTime = tstRslt.TestTime; - meterRslt.VolumeRef = tstRslt.VolumeCTV; /// liter - } + else + { + if (dstrReader != null) + { + meterRslt.TimestampStart = dstrReader.TimestampSecStart; + meterRslt.TimestampEnd = dstrReader.NoSamples + ? (dstrReader.TimestampSecStart + tstRslt.TestTime) + : dstrReader.TimestampSecEnd; + meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart; + meterRslt.VolumeStart = dstrReader.VolumeLtrStart; /// liter + meterRslt.VolumeEnd = dstrReader.VolumeLtrEnd; /// liter + meterRslt.VolumeMeter = + Math.Abs(dstrReader.VolumeLtrEnd - dstrReader.VolumeLtrStart); + meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime; + meterRslt.PulsesMaster = + tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime; + + if (iPerl != null) + { + if (iPerl.ResultCode != 0 && (meterRslt.WaterMeter.ResultCode & + (int)Results.Entities.ResultCode + .OptoErrorCodeMask) == 0) + { + meterRslt.WaterMeter.ResultCode |= iPerl.ResultCode; + } +#if IPERL + meterRslt.WaterMeter.CalibFactor = iPerl.CalibFactor; + meterRslt.ExtraDataPath = iPerl.ExtraDataPath; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 1) + meterRslt.X1 = iPerl.X[0]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 2) + meterRslt.X2 = iPerl.X[1]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 3) + meterRslt.X3 = iPerl.X[2]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 4) + meterRslt.X4 = iPerl.X[3]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 5) + meterRslt.X5 = iPerl.X[4]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 6) + meterRslt.X6 = iPerl.X[5]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 7) + meterRslt.X7 = iPerl.X[6]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 8) + meterRslt.X8 = iPerl.X[7]; + if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 9) + meterRslt.X9 = iPerl.X[8]; +#endif + iPerl.LastTestResult2 = + iPerl.LastTestResult; /// Save shift previous test result + iPerl.LastTestResult = meterRslt; /// Save this test result + } + } + else if (cameraRoi != null) + { + meterRslt.TimestampStart = cameraRoi.TimestampStart; /// second + meterRslt.TimestampEnd = cameraRoi.TimestampEnd; /// second + + meterRslt.VolumeStart = cameraRoi.VolumeStart; /// liter + meterRslt.VolumeEnd = cameraRoi.VolumeEnd; /// liter + meterRslt.VolumeMeter = cameraRoi.VolumeEnd - cameraRoi.VolumeStart; /// liter + + if (meterRslt.VolumeMeter != 0) + { + /// Normal measurement with camera + meterRslt.TestTime = + cameraRoi.TimestampEnd - cameraRoi.TimestampStart; /// second + meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime; + meterRslt.PulsesMaster = + tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime; + } + else + { + /// None or one pulse from the water meter using camera + meterRslt.TestTime = tstRslt.TestTime; + meterRslt.VolumeRef = tstRslt.VolumeCTV; + meterRslt.PulsesMaster = tstRslt.PulsesMaster; + } + } + else + { + meterRslt.PulsesMaster = Convert.ToDouble(regReader.WMRefPulses); + meterRslt.VolumeStart = 0; + meterRslt.VolumeEnd = 0; + meterRslt.VolumeMeter = meterRslt.PulsesMeter * regReader.LtrsPerPulse; /// liter + /// + if (regReader.WMPulses >= 1) + { + /// Normal measurement + meterRslt.TestTime = cBrd.TestTimeWM(regReader.Position); + meterRslt.VolumeRef = meterRslt.PulsesMaster * tstRslt.ConstMaster; /// liter + } + else + { + /// None or one pulse from the water meter + meterRslt.TestTime = tstRslt.TestTime; + meterRslt.VolumeRef = tstRslt.VolumeCTV; /// liter + } + } } meterRslt.Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef); @@ -724,10 +826,14 @@ namespace TBF.Rig.TestMethods.FlyingStart /// Append the results to the CSV-file allResults.Info(TestResult2CsvLine(testName, test.Part)); + //TODO genesis - process result writing + //ProcessDatabaseResultsWriting(test, tstRslt); + if (stopCycle) retVal = Event.ErrorFlagsStop; stopTest: + GenesisHeadBatch.BatchHolder.Value.RemoveAllMeters(); StopRecordingStatistics(); cBrd.StopAll(false); @@ -748,8 +854,36 @@ namespace TBF.Rig.TestMethods.FlyingStart return new List { retVal }; } + //backup how work genesis - not a clean code! + // private void ProcessDatabaseResultsWriting(Test test, TestRslt tstRslt) + // { + // IList e; + // if (!String.IsNullOrEmpty(test.Procedure.ResultsWriter)) + // { + // string[] writers = StateMachine.Procedure.ResultsWriter.Split(new char[] { '~' }); + // foreach (var writerName in writers) + // { + // IResultsWriter writer = TbfComponents.FindComponent(writerName) as IResultsWriter; + // if (writer != null && writer is ) + // { + // var SensusLaWriter = ((DB.SensusLa.Database)writer); + // + // State.Create(string.Format("{0}({1}) : Store results into db.", test.Method, test.Name)) + // .AddOperation(checkUiOp) + // .AddOperation(SensusLaWriter.WriteResultsOp(tstRslt, BatchRslts, GenesisHeadBatch.MeterIdDetailResults)) + // .EnterState(); + // do + // { + // e = StateMachine.WaitRunDevsRunOps(); + // } + // while (!e.Contains(Event.Error) && !e.Contains(Event.ResultsWritten) && !e.Contains(Event.ResultsNotWritten)); + // } + // } + // } + // } - IList Simulate(Config.Entities.Test test, int repetitionNr, bool isLastRepetition, + + IList Simulate(Config.Entities.Test test, int repetitionNr, bool isLastRepetition, Compound.TestParams compoundTestParams, HeatMeters.TestParams heatMetersTestParams, Common.DebugMode debugLevel) diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index d7307e586..fe5c0fc00 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -1031,6 +1031,15 @@ + + + + UserControl + + + WriteDBCfgCtrl.cs + + @@ -3260,6 +3269,9 @@ MessageBoxForm.cs + + WriteDBCfgCtrl.cs + TracingCfgCtrl.cs