using System; using System.Collections.Generic; using System.IO; using log4net; using SchematicDrawing; using TBF.Rig.GenericDevices; using TBF.Boxes; using TBF.Resources; 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; ///------------------------------------------------------------ /// Test related (instance) variables. /// Created when test sequence is open. /// They persist during all repetitions of the same test ///------------------------------------------------------------ protected static Rig.BenchPath benchPath; protected static Rig.OutputPath outPath; public static readonly IList ComponentsWithMeasuredVal; public static readonly IList ComponentsWithSetpoint; /// /// Measured values and setpoints to be displayed /// public static bool[] MsrmntAvailableFlags; public static double[] MeasuredValues; public static string[] AltStrings; public static double[] Setpoints; /// /// State variables to be saved after each completed test /// public static Results.BatchResults BatchRslts; /// /// 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; public static IList RawTestInfos; /// Incomplete raw test infos from Oracle DB public static Results.Output.SensusTestInfo[] CompleteTestInfos; /// Complete TBF test infos obtained as a best mathch static ProcessData() { /// /// RegisterReaders should never be null, RegisterReader.Length should be Config.Data.WMsCount /// RegisterReader[i] where i = 0..Config.Data.WMsCount-1 may be null and should always be tested /// RegisterReaders = new IRegReader[Config.Data.WMsCount]; IsQ2PreCorrectionCalculated = false; CalculatedQ2PreCorrectionLR = 0; CalculatedQ2PreCorrectionRL = 0; ComponentsWithMeasuredVal = new List(); ComponentsWithSetpoint = new List(); } /// /// 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); #if ORACLE_DB /// Write RawTestInfos writer.Write((RawTestInfos != null) ? RawTestInfos.Count : 0); if (RawTestInfos != null) { for (int i = 0; i < RawTestInfos.Count; i++) RawTestInfos[i].WriteBinary(writer); } /// Write CompleteTestInfos writer.Write((CompleteTestInfos != null) ? CompleteTestInfos.Length : 0); if (CompleteTestInfos != null) { for (int i = 0; i < CompleteTestInfos.Length; i++) CompleteTestInfos[i].WriteBinary(writer); } #endif 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 ClearProcessData() { File.Delete(PDataFileName); } /// /// Process values. /// These variables contain immediate values or values overwritten in each test. /// public static IRegReader[] RegisterReaders; /// public static DoubleBox AmbTemp = new DoubleBox() { Name = "Ambient Temperature", Format = "F1" }; /// [Celsius] public static DoubleBox AmbPress = new DoubleBox() { Name = "Ambient Pressure", Format = "F0", Factor = 1000 }; /// [bar], printed by ToString() in [mbar] public static DoubleBox AmbHumi = new DoubleBox() { 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 DoubleBox PressUp = new DoubleBox() { Name = "Pressure Up", Format = "F2" }; /// [bar] public static DoubleBox PressDown = new DoubleBox() { Name = "Pressure Dn", Format = "F2" }; /// [bar] public static DoubleBox PressDelta = new DoubleBox() { 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 RefFrequency = new DoubleBox() { Name = "RefFreq", Format = "F2" }; public static DoubleBox RefFlow = new DoubleBox() { Name = "RefFlow", Format = "F2" }; /// [m3/h] 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() { StateMachine.ControlBoard.ClearProcessValues(); RefPulses = 0; RefFrequency.Clear(); RefFlow.Clear(); StartMass.Clear(); EndMass.Clear(); } public static void UpdateMeasuredValuesAndSetpoints() { /// Collect measured values and alternative strings if (ProcessData.MsrmntAvailableFlags == null || ProcessData.MsrmntAvailableFlags.Length != ProcessData.ComponentsWithMeasuredVal.Count) { ProcessData.MsrmntAvailableFlags = new bool[ProcessData.ComponentsWithMeasuredVal.Count]; } if (ProcessData.MeasuredValues == null || ProcessData.MeasuredValues.Length != ProcessData.ComponentsWithMeasuredVal.Count) { ProcessData.MeasuredValues = new double[ProcessData.ComponentsWithMeasuredVal.Count]; } if (ProcessData.AltStrings == null || ProcessData.AltStrings.Length != ProcessData.ComponentsWithMeasuredVal.Count) { ProcessData.AltStrings = new string[ProcessData.ComponentsWithMeasuredVal.Count]; } for (int i = 0; i < ProcessData.ComponentsWithMeasuredVal.Count; i++) { ProcessData.MsrmntAvailableFlags[i] = ProcessData.ComponentsWithMeasuredVal[i].MsrmntAvailable; ProcessData.MeasuredValues[i] = ProcessData.ComponentsWithMeasuredVal[i].MeasuredVal; ProcessData.AltStrings[i] = ProcessData.ComponentsWithMeasuredVal[i].AltString; } /// Collect setpoints if (ProcessData.Setpoints == null || ProcessData.Setpoints.Length != ProcessData.ComponentsWithSetpoint.Count) { ProcessData.Setpoints = new double[ProcessData.ComponentsWithSetpoint.Count]; } for (int i = 0; i < ProcessData.ComponentsWithSetpoint.Count; i++) { ProcessData.Setpoints[i] = ProcessData.ComponentsWithSetpoint[i].SetpointVal; } } /// /// 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(3, 4, true, new Plotter("Pressure up")); public static Statistics PressDownStat = new Statistics(3, 4, true, new Plotter("Pressure down")); public static Statistics PressDeltaStat = new Statistics(3, 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(); } /// /// Process data logging /// public void LogProcessDataTestInfo(ILog logger, string procedureName, string testName) { logger.Info(Environment.NewLine); logger.InfoFormat("{0}={1:dd.MM.yyyy HH:mm:ss} {2}={3} {4}={5} {6}={7}", Strings.Date_and_time, TestStartTime, Strings.Batch_nr, BatchRslts.Batch.BatchNr, Strings.Procedure, procedureName, Strings.Test, testName); } public void LogProcessDataHeader(ILog logger) { LogProcessDataHeader(logger, null); } public void LogProcessDataHeader(ILog logger, string sectionName) { logger.Info(Environment.NewLine); if (sectionName != null) logger.Info(sectionName); logger.Info("Time Flow TstTime Ref.cnt Ref.vol Tup Tdown Tdiv Pup Pdown Pdelta Mass VolMM Tamb Hamb Pamb Rv"); logger.Info(Environment.NewLine); } public void LogProcessData(ILog logger) { logger.InfoFormat("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14} {15} {16}", DateTime.Now.ToLongTimeString(), Utils.DoubleToStr(RefFlow.Val, 4), /// flow measured by the reference flow meter in m3/h StateMachine.ControlBoard.TestTime.ToString("F3"),/// test time in s StateMachine.ControlBoard.RefPulses, /// reference flow meter pulses count Config.Formulas.VolumeFromPulses(StateMachine.ControlBoard.RefPulses, 1.0f / LtrPerRefPulse).ToString("F3"), /// volume in l benchPath.TempMtrUp != null ? benchPath.TempMtrUp.ReadTemperature() : 0, /// temp. at the beginning of line in degree C benchPath.TempMtrDown != null ? benchPath.TempMtrDown.ReadTemperature() : 0, /// temp. at the end of line in degree C outPath.TempMtrDiv != null ? outPath.TempMtrDiv.ReadTemperature() : 0, /// temp. at the diverter in degree C PressUp, /// water pressure at the beginning of test line in bar (= 100 kPa) PressDown, /// water pressure at the end of test line in bar (= 100 kPa) PressDelta, (outPath.Scale is IScale) ? (outPath.Scale as IScale).Mass : 0, /// collected water mass in kg "VolMM", AmbTemp, /// ambient temperature in degree C AmbHumi, /// ambient humidity in R% AmbPress, /// ambient pressure in mbar (= 1 hPa) outPath.RegValve.Position.ToString("F1")); /// regulation valve position in % (0=closed / 100=open) } public void LogProcessDataHeaderHeatMeters(ILog logger, string sectionName) { logger.Info(Environment.NewLine); if (sectionName != null) logger.Info(sectionName); logger.Info("Time Flow TstTime Ref.cnt Ref.vol Tup Tdown Tdiv Pup Pdown Pdelta Mass VolMM Tamb Hamb Pamb Rv Thiac1 Thiac2 Tloac1 Tloac2"); logger.Info(Environment.NewLine); } public void LogProcessDataHeatMeters(ILog logger) { logger.InfoFormat("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14} {15} {16} {17} {18} {19} {20}", DateTime.Now.ToLongTimeString(), Utils.DoubleToStr(RefFlow.Val, 4), StateMachine.ControlBoard.TestTime.ToString("F3"), StateMachine.ControlBoard.RefPulses, Config.Formulas.VolumeFromPulses(StateMachine.ControlBoard.RefPulses, 1.0f / LtrPerRefPulse).ToString("F3"), benchPath.TempMtrUp != null ? benchPath.TempMtrUp.ReadTemperature() : 0, /// temp. at the beginning of line in degree C benchPath.TempMtrDown != null ? benchPath.TempMtrDown.ReadTemperature() : 0, /// temp. at the end of test in degree C outPath.TempMtrDiv != null ? outPath.TempMtrDiv.ReadTemperature() : 0, /// temp. at the diverter in degree C PressUp, PressDown, PressDelta, (outPath.Scale is IScale) ? (outPath.Scale as IScale).Mass : 0, /// collected water mass in kg "VolMM", AmbTemp, AmbHumi, AmbPress, outPath.RegValve.Position.ToString("F1"), TempRefHi1, TempRefHi2, TempRefLo1, TempRefLo2); } /// /// Endurance data logging /// public void LogEnduranceHeader(System.IO.StreamWriter writer) { LogEnduranceHeader(writer, null); } public void LogEnduranceHeader(System.IO.StreamWriter writer, string sectionName) { writer.WriteLine(); if (sectionName != null) writer.Write(sectionName); writer.WriteLine("Time T_up T_dn Pr_up Pr_dn Flow"); } public void LogEnduranceData(System.IO.StreamWriter writer) { writer.WriteLine(string.Format("{0:dd.MM.yyyy HH:mm.ss} {1} {2} {3} {4} {5}", DateTime.Now, benchPath.TempMtrUp != null ? benchPath.TempMtrUp.ReadTemperature() : 0, /// temp. at the beginning of line in degree C benchPath.TempMtrDown != null ? benchPath.TempMtrDown.ReadTemperature() : 0, /// temp. at the end of line in degree C PressUp, PressDown, RefFlow)); } } }