/// /// Copyright (c) 2015-2023 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.IO; using log4net; using Common; using TBF.Rig.GenericDevices; using TBF.Boxes; namespace TBF.Rig.Sequences { public class ProcessData { static readonly ILog log = LogManager.GetLogger(typeof(ProcessData)); public static readonly string PDataFileName = "process_data.tbf"; /// /// References to components initialized on StateMachine start-up /// public static IBenchInfo BenchInfo; public static IErrorFlags ErrorFlagsComp; public static IStatisticsMonitoring StatisticsMonitoringComp; public static Output.DB.SensusOracle.Database OracleDB; public static Output.DB.SensusOracle.OrderDetails OrderDetails; public static Output.DB.ProductionTracing.Tracing TracingDB; /// /// Safe wrappers /// public static int WMsCount { get { return TBF.Data.WMsCount; } } public static int LinesCount { get { return TBF.Data.WMsCount / TBF.Data.LineSize; } } public static int LineSize { get { return TBF.Data.LineSize; } } public static int CompoundWMsCount { get { return TBF.Data.CompoundWMsCount; } } /// public static Unit VolumeUnit { get { return BenchInfo != null ? BenchInfo.VolumeUnit : Unit.l; } } public static Unit FlowUnit { get { return BenchInfo != null ? BenchInfo.FlowUnit : Unit.m3ph; } } public static Unit MassUnit { get { return BenchInfo != null ? BenchInfo.MassUnit : Unit.kg; } } public static Unit TempUnit { get { return BenchInfo != null ? BenchInfo.TempUnit : Unit.C; } } public static Unit PressUnit { get { return BenchInfo != null ? BenchInfo.PressUnit : Unit.bar; } } public static Unit LengthUnit { get { return BenchInfo != null ? BenchInfo.LengthUnit : Unit.mm; } } /// /// Procedure related state variables /// // public static TBF.UI.ProcedureInfo SelectedProcedure; public static Common.IOrderInfo OrderInfo; // public static SharedDatabase.WorkflowSummary WorkflowSummary; /// Selected production tracing workflow public static IDictionary SampleRemainingTimeSec = new Dictionary(); /// /// State variables to be saved after each completed test /// public static Results.BatchResults BatchRslts; public static int BatchNr { get { return (BatchRslts != null && BatchRslts.Batch != null) ? BatchRslts.Batch.BatchNr : 0; } } /// /// iPERL related state variables to be saved after each completed test public static IList IperlHeads; public static bool IsQ2PreCorrectionCalculated; public static int CalculatedQ2PreCorrectionLR; public static int CalculatedQ2PreCorrectionRL; /// /// State of water filled in the test bench. /// Updated by Transition(sequence, context) /// when context == TransitionContext.PurgeBegin /// or context == TransitionContext.PurgeEnd /// public static FillState FillState; static ProcessData() { /// /// RegisterReaders should never be null, RegisterReader.Length should be TBF.Data.WMsCount /// RegisterReader[i] where i = 0..TBF.Data.WMsCount-1 may be null and should always be tested /// RegisterReaders = new IRegReader[TBF.Data.WMsCount]; IsQ2PreCorrectionCalculated = false; CalculatedQ2PreCorrectionLR = 0; CalculatedQ2PreCorrectionRL = 0; FillState = FillState.Unknown; } /// /// Save process data to file (invoked after each completed test). /// public static void SaveProcessData() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(PDataFileName))) { BatchRslts.WriteBinary(writer); writer.Write(IperlHeads.Count); for (int i = 0; i < IperlHeads.Count; i++) { IperlHeads[i].WriteBinary(writer); } writer.Write(IsQ2PreCorrectionCalculated); writer.Write(CalculatedQ2PreCorrectionLR); writer.Write(CalculatedQ2PreCorrectionRL); log.WarnFormat("Process data succesfully saved to file {0}", PDataFileName); } } public static bool LoadProcessDataHeader(out int batchNr, out string programVersion, out string procedureName, out bool isRemoteProcedure) { using (BinaryReader reader = new BinaryReader(File.OpenRead(PDataFileName))) { try { Results.Entities.Batch.ReadStart(reader, out batchNr, out programVersion, out procedureName, out isRemoteProcedure); return true; } catch (Exception) { batchNr = 0; programVersion = string.Empty; procedureName = string.Empty; isRemoteProcedure = false; return false; } } } /// /// Load process data from file (invoked when cycle is continued after it has been interrupted). /// /// true when successful public static bool LoadProcessData() { using (BinaryReader reader = new BinaryReader(File.OpenRead(PDataFileName))) { try { BatchRslts = new Results.BatchResults(); BatchRslts.ReadBinary(reader); int iPerlHeadsCount = reader.ReadInt32(); for (int i = 0; i < iPerlHeadsCount; i++) { if (IperlHeads != null && i < IperlHeads.Count) { IperlHeads[i].ReadBinary(reader); } else { new TestMethods.iPerlCommunication.iPerlHead.IperlHead().ReadBinary(reader); } } IsQ2PreCorrectionCalculated = reader.ReadBoolean(); CalculatedQ2PreCorrectionLR = reader.ReadInt32(); CalculatedQ2PreCorrectionRL = reader.ReadInt32(); #if ORACLE_DB /// Read RawTestInfos int rawTestInfosCount = reader.ReadInt32(); IList RawTestInfos = new List(); for (int i = 0; i < rawTestInfosCount; i++) { Results.Output.SensusTestInfo ti = new Results.Output.SensusTestInfo(); ti.ReadBinary(reader); RawTestInfos.Add(ti); } /// Read CompleteTestInfos int completeTestInfosLen = reader.ReadInt32(); Results.Output.SensusTestInfo[] CompleteTestInfos = new Results.Output.SensusTestInfo[completeTestInfosLen]; for (int i = 0; i < completeTestInfosLen; i++) { Results.Output.SensusTestInfo ti = new Results.Output.SensusTestInfo(); ti.ReadBinary(reader); CompleteTestInfos[i] = ti; } #endif log.WarnFormat("Process data succesfully loaded from file {0}", PDataFileName); return true; } catch (Exception exc) { log.ErrorFormat("Error loading Process data from file {0}: {1}", PDataFileName, exc.Message); return false; } } } public static void ClearProcessDataFile() { File.Delete(PDataFileName); } /// /// Process values. /// These variables contain immediate values or values overwritten in each test. /// public static IRegReader[] RegisterReaders; /// public static FloatBox AmbTemp = new FloatBox() { Name = "Ambient Temperature", Format = "F1" }; /// [Celsius] public static FloatBox AmbPress = new FloatBox() { Name = "Ambient Pressure", Format = "F0", Factor = 1000 }; /// [bar], printed by ToString() in [mbar] public static FloatBox AmbHumi = new FloatBox() { Name = "Ambient Humidity", Format = "F1" }; /// [%] public static DoubleBox TempUp = new DoubleBox() { Name = "Temperature Up", Format = "F2" }; /// [°C] public static DoubleBox TempDown = new DoubleBox() { Name = "Temperature Dn", Format = "F2" }; /// [°C] public static DoubleBox TempDiv = new DoubleBox() { Name = "Temperature Div", Format = "F2" }; /// [°C] public static FloatBox PressUp = new FloatBox() { Name = "Pressure Up", Format = "F2" }; /// [bar] public static FloatBox PressDown = new FloatBox() { Name = "Pressure Dn", Format = "F2" }; /// [bar] public static FloatBox PressDelta = new FloatBox() { Name = "Pressure Delta", Format = "F2" }; /// [bar] public static FloatBox Conductivity = new FloatBox(750) { Name = "Conductivity", Format = "F0" }; /// [uS/cm], default is 750 public static double LtrPerRefPulse; /// to calculate the ref.volume public static int RefPulses; public static int RefPulsesDelta; public static DoubleBox RefFreq = new DoubleBox() { Name = "RefFreq", Format = "F2" }; public static DoubleBox RefFlow = new DoubleBox() { Name = "RefFlow", Format = "F2" }; /// [m3/h] public static DoubleBox Mass = new DoubleBox() { Name = "Mass", Format = "F3" }; /// [kg] public static DoubleBox StartMass = new DoubleBox() { Name = "Start Mass", Format = "F3" }; /// [kg] public static DoubleBox EndMass = new DoubleBox() { Name = "End Mass", Format = "F3" }; /// [kg] public static DateTime TestStartTime; public static DateTime TestEndTime; public static double StartTime; public static double EndTime; /// Heat meters only public static DoubleBox TempRefHi1 = new DoubleBox() { Name = "T hi ac 1", Format = "F3" }; /// [°C] public static DoubleBox TempRefHi2 = new DoubleBox() { Name = "T hi ac 2", Format = "F3" }; /// [°C] public static DoubleBox TempRefLo1 = new DoubleBox() { Name = "T lo ac 1", Format = "F3" }; /// [°C] public static DoubleBox TempRefLo2 = new DoubleBox() { Name = "T lo ac 2", Format = "F3" }; /// [°C] /// /// To clear process values at the beginning of each test /// protected void ClearProcessValues() { for (int i = 0; i < TBF.Data.WMsCount; i++) { if (RegisterReaders[i] != null) RegisterReaders[i].Clear(); } RefPulses = 0; RefFreq.Clear(); RefFlow.Clear(); Mass.Clear(); StartMass.Clear(); EndMass.Clear(); } /// /// Statistics of 'continuous' variables (temperature, pressure, flow, etc.). /// All statistics are re-initialized in each test. /// public static Statistics AmbTempStat = new Statistics(new Plotter("Ambient temperature")); public static Statistics AmbPressStat = new Statistics(new Plotter("Ambient pressure")); public static Statistics AmbHumiStat = new Statistics(new Plotter("Ambient humidity")); public static Statistics TempUpStat = new Statistics(0, 4, true, new Plotter("Temperature up")); public static Statistics TempDownStat = new Statistics(0, 4, true, new Plotter("Temperature down")); public static Statistics TempDiffStat = new Statistics(0, 4, true); public static Statistics TempDivStat = new Statistics(0, 4, true, new Plotter("Temperature div")); public static Statistics PressUpStat = new Statistics(7, 4, true, new Plotter("Pressure up")); public static Statistics PressDownStat = new Statistics(7, 4, true, new Plotter("Pressure down")); public static Statistics PressDeltaStat = new Statistics(7, 4, true); public static Statistics ConductStat = new Statistics(0, 4, true, new Plotter("Conductivity")); public static Statistics RefFlowStat = new Statistics(5, 7, true, new Plotter("Flow")); public static Statistics TempRefHiStat = new Statistics(); public static Statistics TempRefLoStat = new Statistics(); public static Statistics Energy = new Statistics(); public static Statistics VolumeForEnergy = new Statistics(); public static int lastEnergyUpdateTime; public static Statistics DiverterStart = new Statistics(new Plotter("Div start")); public static Statistics DiverterEnd = new Statistics(new Plotter("Div end")); public static int machineTimeStart; public static int lastMachineTime; protected static void StartNewStatistics(int machineTime, int batchNr, string testName, int repetition, int skippedSamplesCount) { machineTimeStart = machineTime; lastMachineTime = machineTime; AmbTempStat.Start (batchNr, testName, repetition); AmbPressStat.Start(batchNr, testName, repetition); AmbHumiStat.Start (batchNr, testName, repetition); TempUpStat.Start (batchNr, testName, repetition, skippedSamplesCount); TempDownStat.Start (batchNr, testName, repetition, skippedSamplesCount); TempDiffStat.Start (batchNr, testName, repetition, skippedSamplesCount); TempDivStat.Start (batchNr, testName, repetition, skippedSamplesCount); PressUpStat.Start (batchNr, testName, repetition, skippedSamplesCount); PressDownStat.Start (batchNr, testName, repetition, skippedSamplesCount); PressDeltaStat.Start(batchNr, testName, repetition, skippedSamplesCount); ConductStat.Start (batchNr, testName, repetition, skippedSamplesCount); RefFlowStat.Start (batchNr, testName, repetition, skippedSamplesCount); TempRefHiStat.Start (batchNr, testName, repetition); TempRefLoStat.Start (batchNr, testName, repetition); Energy.Start (batchNr, testName, repetition); VolumeForEnergy.Start(batchNr, testName, repetition); lastEnergyUpdateTime = 0; } protected static void UpdateAllStatistics(int machineTime) { int timeDelta = machineTime - lastMachineTime; AmbTempStat.Update(AmbTemp); AmbPressStat.Update(AmbPress); AmbHumiStat.Update(AmbHumi); TempUpStat.Update(TempUp); TempDownStat.Update(TempDown); TempDiffStat.Update(Math.Abs(TempUp.Val - TempDown.Val)); TempDivStat.Update(TempDiv); PressUpStat.Update(PressUp); PressDownStat.Update(PressDown); PressDeltaStat.Update(PressDelta); ConductStat.Update(Conductivity); RefFlowStat.Update(RefFlow); if (BatchRslts.Batch.HeatMeter) { TempRefHiStat.Update((TempRefHi1.Val + TempRefHi2.Val) / 2); TempRefLoStat.Update((TempRefLo1.Val + TempRefLo2.Val) / 2); } lastMachineTime = machineTime; } protected static void StopRecordingStatistics() { AmbTempStat.Stop(); AmbPressStat.Stop(); AmbHumiStat.Stop(); TempUpStat.Stop(); TempDownStat.Stop(); TempDiffStat.Stop(); TempDivStat.Stop(); PressUpStat.Stop(); PressDownStat.Stop(); PressDeltaStat.Stop(); ConductStat.Stop(); RefFlowStat.Stop(); TempRefHiStat.Stop(); TempRefLoStat.Stop(); Energy.Stop(); VolumeForEnergy.Stop(); } } }