/// /// Copyright (c) 2021-2022 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using log4net; using SchematicDrawing; using TBF.Boxes; using TBF.Rig.ControlBoard.Uni; using TBF.Rig.GenericDevices; namespace TBF.Rig.Uni.FlowMetersInParallel { public class FlowMeter : ComponentBase, IFlowMeter, IDrawingItCmpntWithMeasuredVal { private static readonly ILog log = LogManager.GetLogger(typeof(FlowMeter)); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } readonly FlowMeterCfg myCfg; UniCB uniCB; IFlowMeterSingle flowMtr1; IFlowMeterSingle flowMtr2; IFlowMeterSingle flowMtr3; IFlowMeterSingle inactiveFlowMtr; double nominalFlow; double nominalFreq; double ltrPerPulse; int flowMetersCount; int flowMetersBitfield; public int Idx1 { get { return flowMetersBitfield; } } public double NominalFlow { get { return nominalFlow; } } public double NominalFreq { get { return nominalFreq; } } public double LtrPerPulse { get { return ltrPerPulse; } } public SchematicDrawing.IDrawingItem DrawingItem { get { return myCfg as SchematicDrawing.IDrawingItem; } } public string MsrdFormat { get { return myCfg.MsrdFormat; } } public Common.Unit MsrdUnit { get { return myCfg.MsrdUnit; } } public double MsrdValLimLo { get { return myCfg.MsrdValLimLo; } set { myCfg.MsrdValLimLo = value; } } public double MsrdValLimHi { get { return myCfg.MsrdValLimHi; } set { myCfg.MsrdValLimHi = value; } } public bool MsrmntAvailable { get { bool result = true; if (flowMtr1 != null) result = (result && flowMtr1.MsrmntAvailable); if (flowMtr2 != null) result = (result && flowMtr2.MsrmntAvailable); if (flowMtr3 != null) result = (result && flowMtr3.MsrmntAvailable); if (inactiveFlowMtr != null) result = (result && !inactiveFlowMtr.MsrmntAvailable); return result; } } public double MeasuredVal { get { return ReadFlow(); } } public string AltString { get { return "Invalid format"; } } public FlowMeter() { } public FlowMeter(Generic.IComponentCfg cfg, IList components) : base(cfg) { myCfg = cfg as FlowMeterCfg; } public override void Initialize() { uniCB = TbfComponents.FindComponent(myCfg.ParentName) as UniCB; if (uniCB == null) throw new Exception("Cannot find " + Name + " parent"); if (!string.IsNullOrEmpty(myCfg.Flowmeter1)) flowMtr1 = TbfComponents.FindComponent(myCfg.Flowmeter1) as IFlowMeterSingle; if (!string.IsNullOrEmpty(myCfg.Flowmeter2)) flowMtr2 = TbfComponents.FindComponent(myCfg.Flowmeter2) as IFlowMeterSingle; if (!string.IsNullOrEmpty(myCfg.Flowmeter3)) flowMtr3 = TbfComponents.FindComponent(myCfg.Flowmeter3) as IFlowMeterSingle; if (!string.IsNullOrEmpty(myCfg.InactiveFlowmtr)) inactiveFlowMtr = TbfComponents.FindComponent(myCfg.InactiveFlowmtr) as IFlowMeterSingle; nominalFlow = 0; flowMetersCount = 0; flowMetersBitfield = 0; if (flowMtr1 != null) { nominalFlow += flowMtr1.NominalFlow; nominalFreq += flowMtr1.NominalFreq; flowMetersBitfield |= (4 << flowMtr1.Idx1); flowMetersCount++; } if (flowMtr2 != null) { nominalFlow += flowMtr2.NominalFlow; nominalFreq += flowMtr2.NominalFreq; flowMetersBitfield |= (4 << flowMtr2.Idx1); flowMetersCount++; } if (flowMtr3 != null) { nominalFlow += flowMtr3.NominalFlow; nominalFreq += flowMtr3.NominalFreq; flowMetersBitfield |= (4 << flowMtr3.Idx1); flowMetersCount++; } if (flowMetersCount == 0) throw new Exception("Missing flowmeters"); MsrdValLimHi = nominalFlow; ltrPerPulse = nominalFlow / (3.6 * nominalFreq); /// Nominal freq. is sum of particular nominal frquencies log.FatalFormat("{0} initialized: {1} nom.flow={2} m3/h nom.freq={3} Hz bitfield=0x{4:X2}", Name, this, nominalFlow, nominalFreq, flowMetersBitfield); } public double ReadFlow() { return ReadFrequency() * nominalFlow / nominalFreq; } public double ReadFrequency() { return uniCB.RefFrequency; } /// /// Events: FlowDone, Error /// /// Reference to a variable for the flow in Bar /// ReadFlowOp instance reference casted to IOperaton public IOperation ReadFlowOp(ref DoubleBox flow) { return new ReadFlowOp(this, ref flow); } /// /// Events: flowDone, Error /// /// Reference to a variable for the flow in Bar /// Event returned when measurement done /// ReadFlowOp instance reference casted to IOperaton public IOperation ReadFlowOp(ref DoubleBox flow, Event flowDone) { return new ReadFlowOp(this, ref flow, flowDone); } double flowRawSum; double flowSum; int timeSum; int rng1; int rng2; int rng3; public void StartStatistics(Config.Entities.Test test) { flowRawSum = 0; flowSum = 0; timeSum = 0; if (flowMtr1 != null) rng1 = Math.Max(0, flowMtr1.GetRange(test.TempLimLo, test.TempLimHi)); if (flowMtr2 != null) rng2 = Math.Max(0, flowMtr2.GetRange(test.TempLimLo, test.TempLimHi)); if (flowMtr3 != null) rng3 = Math.Max(0, flowMtr3.GetRange(test.TempLimLo, test.TempLimHi)); } public void UpdateStatistics(int timeDelta) { double tempFlow; if (flowMtr1 != null) { flowRawSum += timeDelta * (tempFlow = flowMtr1.ReadFlow()); flowSum += timeDelta * flowMtr1.CorrectedFlow(tempFlow, rng1); ; } if (flowMtr2 != null) { flowRawSum += timeDelta * (tempFlow = flowMtr2.ReadFlow()); flowSum += timeDelta * flowMtr2.CorrectedFlow(tempFlow, rng2); ; } if (flowMtr3 != null) { flowRawSum += timeDelta * (tempFlow = flowMtr3.ReadFlow()); flowSum += timeDelta * flowMtr3.CorrectedFlow(tempFlow, rng3); ; } timeSum += timeDelta; } public void StopStatistics() { flowRawSum /= Convert.ToDouble(timeSum); flowSum /= Convert.ToDouble(timeSum); log.WarnFormat("StopStatistics() flowRawSum = {0:F3} m3/h flowSum = {1:F3} m3/h", flowRawSum, flowSum); } public double LtrPerPulseCorrected(double flow, float temperature) { double ltrPerPulseCorrected = (flowRawSum == 0) ? LtrPerPulse : LtrPerPulse * flowSum / flowRawSum; log.WarnFormat("LtrPerPulseCorrected() flow = {0:F3} m3/h flowRawSum = {1:F3} m3/h flowSum = {2:F3} m3/h temperature = {3:F1} C ltrPerPulseCorrected = {4}", flow, flowRawSum, flowSum, temperature, ltrPerPulseCorrected); return ltrPerPulseCorrected; } } }