diff --git a/TBF/Rig/ControlBoard/Uni/FlyingStartStopTestOp.cs b/TBF/Rig/ControlBoard/Uni/FlyingStartStopTestOp.cs index a8870d0d5..959b6412c 100644 --- a/TBF/Rig/ControlBoard/Uni/FlyingStartStopTestOp.cs +++ b/TBF/Rig/ControlBoard/Uni/FlyingStartStopTestOp.cs @@ -175,8 +175,8 @@ namespace TBF.Rig.ControlBoard.Uni double reqFlowLo = (0.7 * qFrom) + (0.3 * reqFlowAve); /// Move the lower limit 15% of the range up double reqFlowHi = (0.7 * qTo) + (0.3 * reqFlowAve); /// Move the upper limit 15% of the range down /// - uniCB.SetFlow(false, regV.Idx1, 2000.0 * reqFlowLo / flowMeter.NominalFlow, - 2000.0 * reqFlowHi / flowMeter.NominalFlow); + uniCB.SetFlow(false, regV.Idx1, flowMeter.NominalFreq * reqFlowLo / flowMeter.NominalFlow, + flowMeter.NominalFreq * reqFlowHi / flowMeter.NominalFlow); if (readDivTransition) { /// Schedule reading diverter transition data diff --git a/TBF/Rig/ControlBoard/Uni/UniCB.cs b/TBF/Rig/ControlBoard/Uni/UniCB.cs index ef5dd1d33..aacb2517c 100644 --- a/TBF/Rig/ControlBoard/Uni/UniCB.cs +++ b/TBF/Rig/ControlBoard/Uni/UniCB.cs @@ -803,12 +803,60 @@ namespace TBF.Rig.ControlBoard.Uni /// public void SetFlow(bool isFromUI, int regVId, double freqLo, double freqHi, int regulationMinStep = 0) { - if (IsUIBlocked && isFromUI) return; + LiveLogDiag.Log1("----------------------------------------"); + LiveLogDiag.Log1( + "SetFlow() >> ENTER isFromUI={0} regVId={1} freqLo={2} freqHi={3} regulationMinStep={4} IsUIBlocked={5}", + isFromUI, regVId, freqLo, freqHi, regulationMinStep, IsUIBlocked); - actionQueue.Enqueue(Action.SetFlow(isFromUI, regVId, freqLo, freqHi, Convert.ToInt32(Math.Round(Devices.PidCoef)), 200, regulationMinStep)); - log.InfoFormat("Enqueue( SetFlow(rv={0}, fLo={1}, fHi={2}, pid={3}) )", regVId, freqLo, freqHi, Convert.ToInt32(Math.Round(Devices.PidCoef))); + if (IsUIBlocked && isFromUI) + { + LiveLogDiag.Log1( + "SetFlow() >> EXIT (UI BLOCKED) isFromUI={0}", + isFromUI); + return; + } - foreach (var a in actionQueue) log.DebugFormat(" {0}", a); + int pid = Convert.ToInt32(Math.Round(Devices.PidCoef)); + int fixedParam = 200; + + LiveLogDiag.Log1( + "SetFlow() >> PREPARE pid={0} fixedParam={1} regulationMinStep={2}", + pid, fixedParam, regulationMinStep); + + var action = Action.SetFlow( + isFromUI, + regVId, + freqLo, + freqHi, + pid, + fixedParam, + regulationMinStep); + + LiveLogDiag.Log1( + "SetFlow() >> ACTION CREATED: rv={0} fLo={1} fHi={2} pid={3} p6={4} minStep={5}", + regVId, freqLo, freqHi, pid, fixedParam, regulationMinStep); + + actionQueue.Enqueue(action); + + LiveLogDiag.Log1( + "SetFlow() >> ENQUEUED actionQueue.Count={0}", + actionQueue.Count); + + log.InfoFormat( + "Enqueue( SetFlow(rv={0}, fLo={1}, fHi={2}, pid={3}) )", + regVId, freqLo, freqHi, pid); + + int i = 0; + foreach (var a in actionQueue) + { + LiveLogDiag.Log1( + "SetFlow() >> QUEUE[{0}] = {1}", + i++, a); + log.DebugFormat(" {0}", a); + } + + LiveLogDiag.Log1("SetFlow() >> EXIT"); + LiveLogDiag.Log1("----------------------------------------"); } public void StartTest(bool isFromUI, int flowMId, int divId, int divThreshold, @@ -981,5 +1029,18 @@ namespace TBF.Rig.ControlBoard.Uni { /// TODO } + + /// + /// Logging + /// For activation use compilation condition: LIVELOGDIAG_FlowMeter_cs + /// + static class LiveLogDiag + { + [Conditional("LIVELOGDIAG_UniCB_cs")] + public static void Log1(string format, params object[] args) + { + LiveLogCache.Instance.AddLog("UniCB.cs LOG>> " + string.Format(format, args)); + } + } } } diff --git a/TBF/Rig/Uni/FlowMetersInParallel/Factory.cs b/TBF/Rig/Uni/FlowMetersInParallel/Factory.cs index e1ae3fafe..af9fb8823 100644 --- a/TBF/Rig/Uni/FlowMetersInParallel/Factory.cs +++ b/TBF/Rig/Uni/FlowMetersInParallel/Factory.cs @@ -6,20 +6,21 @@ using TBF.Rig.Generic; namespace TBF.Rig.Uni.FlowMetersInParallel { - public class Factory : IComponentFactory - { + public class Factory : IComponentFactory + { public string ClassName { get { return GetType().Namespace.Substring(12); } } public override string ToString() { return ClassName; } - public IComponent DummyComponent() { return new FlowMeter(); } + public IComponent DummyComponent() { return new FlowMeter(); } - public IComponent GetComponent(IComponentCfg cfg, IList components) { return new FlowMeter(cfg, components); } + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new FlowMeter(cfg, components); } - public IComponentCfg DefaultConfig() { return new FlowMeterCfg(this, "I11+I12"); } + public IComponentCfg DefaultConfig() { return new FlowMeterCfg(this, "I11+I12"); } - public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) - { - return ComponentCfgBase.CreateFromDbEntity(FlowMeterCfg.Serializer, component, this); - } - } + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(FlowMeterCfg.Serializer, component, this); + } + } } + diff --git a/TBF/Rig/Uni/FlowMetersInParallel/FlowMeter.cs b/TBF/Rig/Uni/FlowMetersInParallel/FlowMeter.cs index ce6828817..d95adec57 100644 --- a/TBF/Rig/Uni/FlowMetersInParallel/FlowMeter.cs +++ b/TBF/Rig/Uni/FlowMetersInParallel/FlowMeter.cs @@ -1,10 +1,12 @@ -/// +using log4net; +using SchematicDrawing; +using SharedComponents; +/// /// Copyright (c) 2021-2022 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; -using log4net; -using SchematicDrawing; +using System.Diagnostics; using TBF.Boxes; using TBF.Rig.ControlBoard.Uni; using TBF.Rig.GenericDevices; @@ -12,17 +14,16 @@ using TBF.Rig.GenericDevices; namespace TBF.Rig.Uni.FlowMetersInParallel { public class FlowMeter : ComponentBase, IFlowMeter, IDrawingItCmpntWithMeasuredVal - { - private static readonly ILog log = LogManager.GetLogger(typeof(FlowMeter)); + { + 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; + readonly FlowMeterCfg flowMeterCfg; UniCB uniCB; IFlowMeterSingle flowMtr1; IFlowMeterSingle flowMtr2; IFlowMeterSingle flowMtr3; - IFlowMeterSingle inactiveFlowMtr; double nominalFlow; double nominalFreq; double ltrPerPulse; @@ -34,22 +35,20 @@ namespace TBF.Rig.Uni.FlowMetersInParallel 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 SchematicDrawing.IDrawingItem DrawingItem { get { return flowMeterCfg as SchematicDrawing.IDrawingItem; } } + public string MsrdFormat { get { return flowMeterCfg.MsrdFormat; } } + public Common.Unit MsrdUnit { get { return flowMeterCfg.MsrdUnit; } } + public double MsrdValLimLo { get { return flowMeterCfg.MsrdValLimLo; } set { flowMeterCfg.MsrdValLimLo = value; } } + public double MsrdValLimHi { get { return flowMeterCfg.MsrdValLimHi; } set { flowMeterCfg.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); + if (flowMtr1 != null) result = result && flowMtr1.MsrmntAvailable; + if (flowMtr2 != null) result = result && flowMtr2.MsrmntAvailable; + if (flowMtr3 != null) result = result && flowMtr3.MsrmntAvailable; return result; } } @@ -61,26 +60,27 @@ namespace TBF.Rig.Uni.FlowMetersInParallel public string AltString { get { return "Invalid format"; } } + public FlowMeter() { } - public FlowMeter() { } - - public FlowMeter(Generic.IComponentCfg cfg, IList components) - : base(cfg) - { - myCfg = cfg as FlowMeterCfg; - } + public FlowMeter(Generic.IComponentCfg cfg, IList components) + : base(cfg) + { + flowMeterCfg = cfg as FlowMeterCfg; + } public override void Initialize() { - uniCB = TbfComponents.FindComponent(myCfg.ParentName) as UniCB; + uniCB = TbfComponents.FindComponent(flowMeterCfg.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; + if (!string.IsNullOrEmpty(flowMeterCfg.Flowmeter1)) flowMtr1 = TbfComponents.FindComponent(flowMeterCfg.Flowmeter1) as IFlowMeterSingle; + if (!string.IsNullOrEmpty(flowMeterCfg.Flowmeter2)) flowMtr2 = TbfComponents.FindComponent(flowMeterCfg.Flowmeter2) as IFlowMeterSingle; + if (!string.IsNullOrEmpty(flowMeterCfg.Flowmeter3)) flowMtr3 = TbfComponents.FindComponent(flowMeterCfg.Flowmeter3) as IFlowMeterSingle; + + LiveLogDiag.Log1("{0} >> Initialize() >> ----------------------initialising------------------------", Name); nominalFlow = 0; + nominalFreq = 0; flowMetersCount = 0; flowMetersBitfield = 0; @@ -90,62 +90,122 @@ namespace TBF.Rig.Uni.FlowMetersInParallel nominalFreq += flowMtr1.NominalFreq; flowMetersBitfield |= (4 << flowMtr1.Idx1); flowMetersCount++; + + LiveLogDiag.Log1( + "{0} >> Initialize() >> flowMtr1.NominalFlow = {1} m3/h flowMtr1.NominalFreq = {2} Hz", + Name, flowMtr1.NominalFlow, flowMtr1.NominalFreq); } - if (flowMtr2 != null) - { + + if (flowMtr2 != null) + { nominalFlow += flowMtr2.NominalFlow; nominalFreq += flowMtr2.NominalFreq; flowMetersBitfield |= (4 << flowMtr2.Idx1); flowMetersCount++; + + LiveLogDiag.Log1( + "{0} >> Initialize() >> flowMtr2.NominalFlow = {1} m3/h flowMtr2.NominalFreq = {2} Hz", + Name, flowMtr2.NominalFlow, flowMtr2.NominalFreq); } + if (flowMtr3 != null) { nominalFlow += flowMtr3.NominalFlow; nominalFreq += flowMtr3.NominalFreq; flowMetersBitfield |= (4 << flowMtr3.Idx1); flowMetersCount++; + + LiveLogDiag.Log1( + "{0} >> Initialize() >> flowMtr3.NominalFlow = {1} m3/h flowMtr3.NominalFreq = {2} Hz", + Name, flowMtr3.NominalFlow, flowMtr3.NominalFreq); } + if (flowMetersCount == 0) throw new Exception("Missing flowmeters"); MsrdValLimHi = nominalFlow; - ltrPerPulse = nominalFlow / (3.6 * nominalFreq); /// Nominal freq. is sum of particular nominal frquencies + ltrPerPulse = nominalFlow / (3.6 * nominalFreq); - log.FatalFormat("{0} initialized: {1} nom.flow={2} m3/h nom.freq={3} Hz bitfield=0x{4:X2}", - Name, this, nominalFlow, nominalFreq, flowMetersBitfield); + LiveLogDiag.Log1( + "{0} >> Initialize() >> nominalFlow = {1} m3/h nominalFreq = {2} Hz bitfield = 0x{3:X2} ltrPerPulse = {4}", + Name, nominalFlow, nominalFreq, flowMetersBitfield, ltrPerPulse); + + log.FatalFormat( + "{0} initialized: nom.flow={1} m3/h nom.freq={2} Hz bitfield=0x{3:X2}", + Name, nominalFlow, nominalFreq, flowMetersBitfield); } public double ReadFlow() { - return ReadFrequency() * nominalFlow / nominalFreq; + double flowByNewFormulaSum = 0; + + if (flowMtr1 != null) + { + double contrib1 = flowMtr1.NominalFlow * uniCB.Data.ReferenceFreq[flowMtr1.Idx1] / flowMtr1.NominalFreq; + flowByNewFormulaSum += contrib1; + + LiveLogDiag.Log1( + "{0} >> ReadFlow() >> FM1: NominalFlow={1} m3/h RefFreq[1]={2} Hz NominalFreq={3} Hz Contribution={4} m3/h", + Name, flowMtr1.NominalFlow, uniCB.Data.ReferenceFreq[1], flowMtr1.NominalFreq, contrib1); + } + + if (flowMtr2 != null) + { + double contrib2 = flowMtr2.NominalFlow * uniCB.Data.ReferenceFreq[flowMtr2.Idx1] / flowMtr2.NominalFreq; + flowByNewFormulaSum += contrib2; + + LiveLogDiag.Log1( + "{0} >> ReadFlow() >> FM2: NominalFlow={1} m3/h RefFreq[2]={2} Hz NominalFreq={3} Hz Contribution={4} m3/h", + Name, flowMtr2.NominalFlow, uniCB.Data.ReferenceFreq[2], flowMtr2.NominalFreq, contrib2); + } + + if (flowMtr3 != null) + { + double contrib3 = flowMtr3.NominalFlow * uniCB.Data.ReferenceFreq[flowMtr3.Idx1] / flowMtr3.NominalFreq; + flowByNewFormulaSum += contrib3; + + LiveLogDiag.Log1( + "{0} >> ReadFlow() >> FM3: NominalFlow={1} m3/h RefFreq[3]={2} Hz NominalFreq={3} Hz Contribution={4} m3/h", + Name, flowMtr3.NominalFlow, uniCB.Data.ReferenceFreq[3], flowMtr3.NominalFreq, contrib3); + } + + LiveLogDiag.Log1( + "{0} >> ReadFlow() >> return = flowByNewFormulaSum = {1} m3/h", + Name, flowByNewFormulaSum); + LiveLogDiag.Log1( + "{0} >> FM1: Idx1={1}, RefFreq[1]={2}, RefFreq[Idx1]={3}", + Name, + flowMtr1.Idx1, + uniCB.Data.ReferenceFreq[1], + uniCB.Data.ReferenceFreq[flowMtr1.Idx1]); + + return flowByNewFormulaSum; } public double ReadFrequency() { - return uniCB.RefFrequency; + double freq = uniCB.RefFrequency; + LiveLogDiag.Log1("{0} >> ReadFrequency() >> return = {1} Hz", Name, freq); + return freq; } - /// - /// 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); - } + /// + /// Events: FlowDone, Error + /// + public IOperation ReadFlowOp(ref DoubleBox flow) + { + LiveLogDiag.Log1("{0} >> ReadFlowOp(ref DoubleBox) >> operation created", Name); + return new ReadFlowOp(this, ref flow); + } + /// + /// Events: flowDone, Error + /// + public IOperation ReadFlowOp(ref DoubleBox flow, Event flowDone) + { + LiveLogDiag.Log1("{0} >> ReadFlowOp(ref DoubleBox, Event) >> operation created", Name); + return new ReadFlowOp(this, ref flow, flowDone); + } double flowRawSum; double flowSum; @@ -163,42 +223,98 @@ namespace TBF.Rig.Uni.FlowMetersInParallel 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)); + + LiveLogDiag.Log1( + "{0} >> StartStatistics() >> flowRawSum={1} flowSum={2} timeSum={3} rng1={4} rng2={5} rng3={6}", + Name, flowRawSum, flowSum, timeSum, rng1, rng2, rng3); } public void UpdateStatistics(int timeDelta) { double tempFlow; + if (flowMtr1 != null) { - flowRawSum += timeDelta * (tempFlow = flowMtr1.ReadFlow()); - flowSum += timeDelta * flowMtr1.CorrectedFlow(tempFlow, rng1); ; + tempFlow = flowMtr1.ReadFlow(); + flowRawSum += timeDelta * tempFlow; + flowSum += timeDelta * flowMtr1.CorrectedFlow(tempFlow, rng1); + + LiveLogDiag.Log1( + "{0} >> UpdateStatistics() >> FM1: timeDelta={1} tempFlow={2} corrected={3}", + Name, timeDelta, tempFlow, flowMtr1.CorrectedFlow(tempFlow, rng1)); } + if (flowMtr2 != null) { - flowRawSum += timeDelta * (tempFlow = flowMtr2.ReadFlow()); - flowSum += timeDelta * flowMtr2.CorrectedFlow(tempFlow, rng2); ; + tempFlow = flowMtr2.ReadFlow(); + flowRawSum += timeDelta * tempFlow; + flowSum += timeDelta * flowMtr2.CorrectedFlow(tempFlow, rng2); + + LiveLogDiag.Log1( + "{0} >> UpdateStatistics() >> FM2: timeDelta={1} tempFlow={2} corrected={3}", + Name, timeDelta, tempFlow, flowMtr2.CorrectedFlow(tempFlow, rng2)); } + if (flowMtr3 != null) { - flowRawSum += timeDelta * (tempFlow = flowMtr3.ReadFlow()); - flowSum += timeDelta * flowMtr3.CorrectedFlow(tempFlow, rng3); ; + tempFlow = flowMtr3.ReadFlow(); + flowRawSum += timeDelta * tempFlow; + flowSum += timeDelta * flowMtr3.CorrectedFlow(tempFlow, rng3); + + LiveLogDiag.Log1( + "{0} >> UpdateStatistics() >> FM3: timeDelta={1} tempFlow={2} corrected={3}", + Name, timeDelta, tempFlow, flowMtr3.CorrectedFlow(tempFlow, rng3)); } timeSum += timeDelta; + + LiveLogDiag.Log1( + "{0} >> UpdateStatistics() >> flowRawSum={1} flowSum={2} timeSum={3}", + Name, flowRawSum, flowSum, timeSum); } 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); + + LiveLogDiag.Log1( + "{0} >> StopStatistics() >> flowRawSum={1:F3} m3/h flowSum={2:F3} m3/h", + Name, flowRawSum, flowSum); + + 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); + double ltrPerPulseCorrected = (flowRawSum == 0) + ? LtrPerPulse + : LtrPerPulse * flowSum / flowRawSum; + + LiveLogDiag.Log1( + "{0} >> LtrPerPulseCorrected() >> flow={1} m3/h flowRawSum={2} flowSum={3} temperature={4} C ltrPerPulseCorrected={5}", + Name, flow, flowRawSum, flowSum, temperature, ltrPerPulseCorrected); + + log.WarnFormat( + "LtrPerPulseCorrected() flow = {0} m3/h flowRawSum = {1} m3/h flowSum = {2} m3/h temperature = {3} C ltrPerPulseCorrected = {4}", + flow, flowRawSum, flowSum, temperature, ltrPerPulseCorrected); + return ltrPerPulseCorrected; } + + /// + /// Logging + /// For activation use compilation condition: LIVELOGDIAG_FlowMeter_cs + /// + static class LiveLogDiag + { + [Conditional("LIVELOGDIAG_FlowMeter_cs")] + public static void Log1(string format, params object[] args) + { + LiveLogCache.Instance.AddLog("FlowMeter.cs LOG>> " + string.Format(format, args)); + } + } } -} +} \ No newline at end of file diff --git a/TBF/Rig/Uni/FlowMetersInParallel/FlowMeterCfg.cs b/TBF/Rig/Uni/FlowMetersInParallel/FlowMeterCfg.cs index b449a2ea6..77c6da489 100644 --- a/TBF/Rig/Uni/FlowMetersInParallel/FlowMeterCfg.cs +++ b/TBF/Rig/Uni/FlowMetersInParallel/FlowMeterCfg.cs @@ -13,9 +13,9 @@ using TBF.Rig.Generic; namespace TBF.Rig.Uni.FlowMetersInParallel { public class FlowMeterCfg : ComponentCfgBase, IChildComponentCfg, IParamsProvider, IDrawingItemWithMeasuredVal - { - public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(FlowMeterCfg) })[0]; - public override XmlSerializer GetSerializer() { return Serializer; } + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(FlowMeterCfg) })[0]; + public override XmlSerializer GetSerializer() { return Serializer; } public IComponentCfgCtrl GetControl(IList cmpntEntities) { @@ -24,15 +24,14 @@ namespace TBF.Rig.Uni.FlowMetersInParallel return new Configs.ParamsProvider.ComponentCfgCtrl(this, parents); } - /// - /// Serialized parameters - /// + /// + /// Serialized parameters + /// public string Flowmeter1; /// 0 Flowmeter component name or string.Empty public string Flowmeter2; /// 1 - ' ' - public string Flowmeter3; /// 2 - ' ' - - public string InactiveFlowmtr; /// 3 Inactive flowmeter component name or string.Empty - public string MsrdFormat { get; set; } /// 4 - public Unit MsrdUnit { get; set; } /// 5 + public string MsrdFormat { get; set; } /// 3 + public Unit MsrdUnit { get; set; } /// 4 /// Schematic drawing info public Shape Shape { get; set; } @@ -55,12 +54,12 @@ namespace TBF.Rig.Uni.FlowMetersInParallel [XmlIgnore] public double MsrdValLimHi { get; set; } - - private IEnumerable flowMeters; - [XmlIgnore] public bool IsOffline { get; set; } + + private IEnumerable flowMeters; + /// Private parameterless constructor invoked by all other (public) constructors FlowMeterCfg() { @@ -87,7 +86,6 @@ namespace TBF.Rig.Uni.FlowMetersInParallel Flowmeter1 = "I11"; Flowmeter2 = "I12"; Flowmeter3 = string.Empty; - InactiveFlowmtr = "I13"; MsrdFormat = "{0:F3} m3/h"; MsrdUnit = Unit.m3ph; } @@ -97,9 +95,8 @@ namespace TBF.Rig.Uni.FlowMetersInParallel "Flow meter 1", /// 0 "Flow meter 2", /// 1 "Flow meter 3", /// 2 - "Inactive flow meter", /// 3 - "Display format", /// 4 - "Unit of flow on a display", /// 5 + "Display format", /// 3 + "Unit of flow on a display", /// 4 }; public string ParamName(int i) { return paramNames[i]; } public int ParamsCount() { return paramNames.Length; } @@ -111,48 +108,44 @@ namespace TBF.Rig.Uni.FlowMetersInParallel case 0: case 1: case 2: - case 3: if (flowMeters == null) return null; var fmtrs = new List(); foreach (var fmtr in flowMeters) fmtrs.Add(fmtr.Name); fmtrs.Add("---"); return fmtrs; - case 5: - return new string[] { "m3/h", "l/h", "gal/m" }; + case 4: + return new string[] { "m3/h", "l/h" }; default: return null; } } - public string ToString(int i) - { + public string ToString(int i) + { switch (i) { case 0: return string.IsNullOrEmpty(Flowmeter1) ? "---" : Flowmeter1; case 1: return string.IsNullOrEmpty(Flowmeter2) ? "---" : Flowmeter2; case 2: return string.IsNullOrEmpty(Flowmeter3) ? "---" : Flowmeter3; - case 3: return string.IsNullOrEmpty(InactiveFlowmtr) ? "---" : InactiveFlowmtr; - case 4: return MsrdFormat; - case 5: return MsrdUnit.ToDescription(); + case 3: return MsrdFormat; + case 4: return MsrdUnit.ToDescription(); default: - return string.Format("Name={0} {1} {2} {3} ~{4} fmt={5} unit={6} Lo={7} Hi={8}", - Name, Flowmeter1, Flowmeter2, Flowmeter3, InactiveFlowmtr, + return string.Format("Name={0} {1} {2} {3} fmt={4} unit={5} Lo={6} Hi={7}", + Name, Flowmeter1, Flowmeter2, Flowmeter3, MsrdFormat, MsrdUnit.ToDescription(), MsrdValLimLo, MsrdValLimHi); } - } + } public CfgUpdateFlags UpdateParam(int i, string str) { switch (i) { - case 0: Flowmeter1 = (str != "---") ? str : string.Empty; return CfgUpdateFlags.RestartRqrd; - case 1: Flowmeter2 = (str != "---") ? str : string.Empty; return CfgUpdateFlags.RestartRqrd; - case 2: Flowmeter3 = (str != "---") ? str : string.Empty; return CfgUpdateFlags.RestartRqrd; - case 3: InactiveFlowmtr = (str != "---") ? str : string.Empty; return CfgUpdateFlags.RestartRqrd; - case 4: MsrdFormat = str; return CfgUpdateFlags.RestartRqrd; - //case 5: MsrdUnit = (str == "l/h") ? Unit.lph : Unit.m3ph; return CfgUpdateFlags.RestartRqrd; - case 5: MsrdUnit = ParseFlowUnit(str); return CfgUpdateFlags.RestartRqrd; + case 0: Flowmeter1 = (str != "---") ? str : string.Empty; return CfgUpdateFlags.RestartRqrd; + case 1: Flowmeter2 = (str != "---") ? str : string.Empty; return CfgUpdateFlags.RestartRqrd; + case 2: Flowmeter3 = (str != "---") ? str : string.Empty; return CfgUpdateFlags.RestartRqrd; + case 3: MsrdFormat = str; return CfgUpdateFlags.RestartRqrd; + case 4: MsrdUnit = (str == "l/h") ? Unit.lph : Unit.m3ph; return CfgUpdateFlags.RestartRqrd; default: return CfgUpdateFlags.None; } @@ -167,11 +160,10 @@ namespace TBF.Rig.Uni.FlowMetersInParallel case 0: case 1: case 2: - case 3: - case 5: + case 4: if (ParamValues(i).Contains(str)) return true; break; - case 4: + case 3: return true; default: message = "Invalid index"; @@ -187,7 +179,6 @@ namespace TBF.Rig.Uni.FlowMetersInParallel prms.Flowmeter1 = this.Flowmeter1; prms.Flowmeter2 = this.Flowmeter2; prms.Flowmeter3 = this.Flowmeter3; - prms.InactiveFlowmtr = this.InactiveFlowmtr; prms.MsrdFormat = this.MsrdFormat; prms.MsrdUnit = this.MsrdUnit; } @@ -203,19 +194,5 @@ namespace TBF.Rig.Uni.FlowMetersInParallel { return true; /// =OK, do nothing } - public static Unit ParseFlowUnit(string str) - { - //Check if the string is a valid unit description - Unit fromDescription = Units.FromDescription(str); - if (fromDescription != Unit.None) return fromDescription; - //check if the string is a valid unit name - switch (str) - { - case "l/h": return Unit.lph; - case "gal/m": return Unit.USgalpm; - case "m3/h": - default: return Unit.m3ph; - } - } } } diff --git a/TBF/Rig/Uni/FlowMetersInParallel/ReadFlowOp.cs b/TBF/Rig/Uni/FlowMetersInParallel/ReadFlowOp.cs index 23a7a97a0..968f4e681 100644 --- a/TBF/Rig/Uni/FlowMetersInParallel/ReadFlowOp.cs +++ b/TBF/Rig/Uni/FlowMetersInParallel/ReadFlowOp.cs @@ -8,57 +8,57 @@ using TBF.Rig.GenericDevices; namespace TBF.Rig.Uni.FlowMetersInParallel { - public class ReadFlowOp : IOperation - { - private static readonly ILog log = LogManager.GetLogger(typeof(ReadFlowOp)); + public class ReadFlowOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadFlowOp)); public override string ToString() { return string.Format("ReadFlowOp({0},.,.,{1})", flowMeter.Idx1, eventDone); } - /// Set by the constructor + /// Set by the constructor readonly IFlowMeter flowMeter; - readonly DoubleBox flowBox; - readonly Event eventDone; + readonly DoubleBox flowBox; + readonly Event eventDone; - /// - /// Events: FlowInDone, FlowOutDone or Error - /// - /// Flow meter reference - /// Reference to the measured flow variable, value is in bar - /// Event to be returned by Run() when completed OK + /// + /// Events: FlowInDone, FlowOutDone or Error + /// + /// Flow meter reference + /// Reference to the measured flow variable, value is in bar + /// Event to be returned by Run() when completed OK public ReadFlowOp(IFlowMeter flowMeter, ref DoubleBox flowBox, Event eventDone) { if (flowMeter == null) throw new ArgumentNullException(); this.flowMeter = flowMeter; - this.eventDone = eventDone; - this.flowBox = flowBox; + this.eventDone = eventDone; + this.flowBox = flowBox; - log.Debug(this.ToString()); + log.Debug(this.ToString()); } public ReadFlowOp(IFlowMeter flowMeter, ref DoubleBox flowBox) - : this(flowMeter, ref flowBox, Event.FlowMeasurementDone) - { - } + : this(flowMeter, ref flowBox, Event.FlowMeasurementDone) + { + } - /// Start this operation - public void Start() { } + /// Start this operation + public void Start() { } - /// Run this operation - /// - /// Event.FlowInDone or Event.FlowOutDone - /// - public Event Run() - { + /// Run this operation + /// + /// Event.FlowInDone or Event.FlowOutDone + /// + public Event Run() + { if (flowMeter.MsrmntAvailable) - { + { if (flowBox != null) flowBox.Val = flowMeter.ReadFlow(); - return eventDone; - } + return eventDone; + } return Event.Error; - } + } - /// Stop this operation - public void Stop() { } - } + /// Stop this operation + public void Stop() { } + } } diff --git a/TBF/Rig/Uni/RegValve/SetFlowOp.cs b/TBF/Rig/Uni/RegValve/SetFlowOp.cs index da241045b..36cc84667 100644 --- a/TBF/Rig/Uni/RegValve/SetFlowOp.cs +++ b/TBF/Rig/Uni/RegValve/SetFlowOp.cs @@ -1,28 +1,28 @@ -/// -/// Copyright (c) 2021 Sensus Slovensko a.s. -/// +using Config.Entities; +using log4net; +using SharedComponents; using System; using System.Collections.Generic; -using log4net; -using Config.Entities; +using System.Diagnostics; +using TBF.Boxes; using TBF.Rig.ControlBoard.Uni; using TBF.Rig.GenericDevices; -using TBF.Boxes; namespace TBF.Rig.Uni.RegValve { - public class SetFlowOp : IOperation - { - private static readonly ILog log = LogManager.GetLogger(typeof(SetFlowOp)); - public override string ToString() - { - return string.Format("SetFlowOp({0}, Qfrom={1}, Qto={2})", regV.Name, shrinkedTgtFlowLo, shrinkedTgtFlowHi); - } + public class SetFlowOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(SetFlowOp)); + + public override string ToString() + { + return string.Format("SetFlowOp({0}, Qfrom={1}, Qto={2})", regV.Name, shrinkedTgtFlowLo, shrinkedTgtFlowHi); + } public const double RqrdFlowRangeRatio = 0.5; /// - /// Set by the constructor + /// Set by the constructor /// readonly UniCB uniCB; readonly RegValve regV; @@ -36,22 +36,22 @@ namespace TBF.Rig.Uni.RegValve readonly double maximalFlow; - /// - /// Internal state of this operation - /// - enum OpState - { - Idle = 0, - ValveMoveToPosition1, /// Wait 1 takt - ValveMoveToPosition2, /// This is actual move to position - ValveMoveToPosition3, /// Wait 1 takt - SettingPosition, - Wait4FlowMsrmntAndSendRVMove, /// Wait until the flow measurement starts, then issue reg. valve move command - SettingFlow, /// Measure the flow and verify whether it is within limits sufficiently long time - FlowReached, - SendCommandAgain, - } - OpState opState; + /// + /// Internal state of this operation + /// + enum OpState + { + Idle = 0, + ValveMoveToPosition1, + ValveMoveToPosition2, + ValveMoveToPosition3, + SettingPosition, + Wait4FlowMsrmntAndSendRVMove, + SettingFlow, + FlowReached, + SendCommandAgain, + } + OpState opState; double currentReqFlowLo; double currentReqFlowHi; @@ -60,32 +60,29 @@ namespace TBF.Rig.Uni.RegValve int setFlowTime; int expireTime; - DoubleBox msrdFlow; + DoubleBox msrdFlow; int isFlowOkDuration; - - /// + /// /// Set required water flow. Conditionally leave the measurement running. - /// Events: FlowSet, FlowTimeOut - /// - /// Control board device - /// Regulation valve component - /// Flowmeter component - /// Lower limit of the flow to be achieved in [m3/h] - /// Upper limit of the flow to be achieved in [m3/h] - /// DoubleBox for measured flow - /// Timeout for the flow setting in [s] - /// Flow setting starts after this delay in [s] - /// true = Leave the measurement running after op. stop - /// Only Elde.Valve flow are used, other flow on the lists are ignored - public SetFlowOp(UniCB uniCB, IRegValve regValve, IFlowMeter flowMeter, double qFrom, double qTo, DoubleBox msrdFlow, - int timeout, int delay, bool leaveFlowControlRunning) + /// Events: FlowSet, FlowTimeOut + /// + public SetFlowOp( + UniCB uniCB, + IRegValve regValve, + IFlowMeter flowMeter, + double qFrom, + double qTo, + DoubleBox msrdFlow, + int timeout, + int delay, + bool leaveFlowControlRunning) { - this.uniCB = uniCB; + this.uniCB = uniCB; if (this.uniCB == null) throw new ArgumentNullException("Control board is null or not Uni"); this.regV = regValve as RegValve; - if (this.regV == null) throw new ArgumentNullException(string.Format("{0} is not Uni.RegValve", regValve.Name)); + if (this.regV == null) throw new ArgumentNullException(string.Format("{0} is not Uni.RegValve", regValve.Name)); this.flowMeter = flowMeter; if (this.flowMeter == null) throw new ArgumentNullException("flowMeter"); @@ -96,242 +93,397 @@ namespace TBF.Rig.Uni.RegValve double rqrdFlowHiBeforeCorr = qTo - MeasurementCorrection.GetCorrection(qTo, flowMeter.Corrections); targetFlowAve = (rqrdFlowLoBeforeCorr + rqrdFlowHiBeforeCorr) / 2; shrinkedTgtFlowLo = (RqrdFlowRangeRatio * rqrdFlowLoBeforeCorr) - + ((1 - RqrdFlowRangeRatio) * targetFlowAve); /// Move the lower limit 15% of the range up + + ((1 - RqrdFlowRangeRatio) * targetFlowAve); shrinkedTgtFlowHi = (RqrdFlowRangeRatio * rqrdFlowHiBeforeCorr) - + ((1 - RqrdFlowRangeRatio) * targetFlowAve); /// Move the upper limit 15% of the range down + + ((1 - RqrdFlowRangeRatio) * targetFlowAve); this.msrdFlow = msrdFlow; this.timeout = timeout; this.delay = delay; this.leaveFlowControlRunning = leaveFlowControlRunning; - log.Debug(this.ToString()); + log.Debug(this.ToString()); + + LiveLogDiag.Log1( + "{0} >> CTOR() >> qFrom={1} qTo={2} rqrdFlowLoBeforeCorr={3} rqrdFlowHiBeforeCorr={4} targetFlowAve={5} shrinkedTgtFlowLo={6} shrinkedTgtFlowHi={7} nominalFlow={8} nominalFreq={9} maximalFlow={10} delay={11} timeout={12} leaveFlowControlRunning={13}", + regV.Name, qFrom, qTo, rqrdFlowLoBeforeCorr, rqrdFlowHiBeforeCorr, targetFlowAve, + shrinkedTgtFlowLo, shrinkedTgtFlowHi, flowMeter.NominalFlow, flowMeter.NominalFreq, + maximalFlow, delay, timeout, leaveFlowControlRunning); } - /// - /// Set required water flow - Do not leave the measurement running. - /// Events: FlowSet - /// public SetFlowOp(UniCB uniCB, IRegValve regValve, IFlowMeter flowMeter, double qFrom, double qTo, DoubleBox flowbox, int timeout, int delay) : this(uniCB, regValve, flowMeter, qFrom, qTo, flowbox, timeout, delay, false) { } - /// - /// Set required water flow - Do not leave the measurement running. - /// Events: FlowSet - /// public SetFlowOp(UniCB uniCB, IRegValve regValve, IFlowMeter flowMeter, double qFrom, double qTo, DoubleBox flowbox, int timeout) : this(uniCB, regValve, flowMeter, qFrom, qTo, flowbox, timeout, 0, false) { } - /// - /// Set required water flow - No timeout. - /// Events: FlowSet - /// public SetFlowOp(UniCB uniCB, IRegValve regValve, IFlowMeter flowMeter, double qFrom, double qTo, DoubleBox flowbox) : this(uniCB, regValve, flowMeter, qFrom, qTo, flowbox, int.MaxValue, 0, false) { } - /// + /// /// Fetch target position limits from the dictionary or return false - /// - /// Average of the flow targer range (input) - /// Target valve position low limit (output) - /// Target valve position high limit (output) - /// true when positions for the target flow are stored in the memory, otherwise return false + /// bool FetchTargetPosition(double avgReqFlow, out double positionLo, out double positionHi) - { + { double targetPosition; - if (regV.Dict.TryGetValue(avgReqFlow, out targetPosition)) - { - positionLo = Math.Max(targetPosition * 0.95, 0.0); - positionHi = Math.Min(targetPosition * 1.05, 100.0); - return true; - } - else - { - positionLo = 0; - positionHi = 0; - return false; - } - } + if (regV.Dict.TryGetValue(avgReqFlow, out targetPosition)) + { + positionLo = Math.Max(targetPosition * 0.95, 0.0); + positionHi = Math.Min(targetPosition * 1.05, 100.0); + + LiveLogDiag.Log1( + "{0} >> FetchTargetPosition() >> avgReqFlow={1} FOUND targetPosition={2} positionLo={3} positionHi={4}", + regV.Name, avgReqFlow, targetPosition, positionLo, positionHi); + + return true; + } + else + { + positionLo = 0; + positionHi = 0; + + LiveLogDiag.Log1( + "{0} >> FetchTargetPosition() >> avgReqFlow={1} NOT FOUND", + regV.Name, avgReqFlow); + + return false; + } + } void StoreTargetPosition(double avgReqFlow, double actPosition) - { - if (!regV.Dict.ContainsKey(targetFlowAve)) - { - regV.Dict.Add(new KeyValuePair(avgReqFlow, actPosition)); - } - return; - } - - /// Start this operation - public void Start() { - log.InfoFormat("SetFlowOp:Start() rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}", - regV.Idx1, flowMeter.Idx1, currentReqFlowLo, currentReqFlowHi); + if (!regV.Dict.ContainsKey(targetFlowAve)) + { + regV.Dict.Add(new KeyValuePair(avgReqFlow, actPosition)); - /// Store the current time, etc. + LiveLogDiag.Log1( + "{0} >> StoreTargetPosition() >> STORED avgReqFlow={1} actPosition={2}", + regV.Name, avgReqFlow, actPosition); + } + else + { + LiveLogDiag.Log1( + "{0} >> StoreTargetPosition() >> SKIPPED because targetFlowAve={1} already exists in Dict", + regV.Name, targetFlowAve); + } + + return; + } + + /// Start this operation + public void Start() + { setFlowTime = StateMachine.Time + delay; expireTime = StateMachine.Time + timeout; if (expireTime < 0) expireTime = int.MaxValue; isFlowOkDuration = 0; + currentReqFlowLo = 0; + currentReqFlowHi = 0; + + log.InfoFormat( + "SetFlowOp:Start() rv#={0} flowMtr#={1} TARGET_SHRINKED: flowLo={2} flowHi={3}", + regV.Idx1, flowMeter.Idx1, shrinkedTgtFlowLo, shrinkedTgtFlowHi); + + LiveLogDiag.Log1( + "{0} >> Start() >> rv#={1} flowMtr#={2} setFlowTime={3} expireTime={4} delay={5} timeout={6} shrinkedTgtFlowLo={7} shrinkedTgtFlowHi={8} targetFlowAve={9} nominalFlow={10} nominalFreq={11}", + regV.Name, regV.Idx1, flowMeter.Idx1, setFlowTime, expireTime, delay, timeout, + shrinkedTgtFlowLo, shrinkedTgtFlowHi, targetFlowAve, flowMeter.NominalFlow, flowMeter.NominalFreq); /// Start the flow measurement + LiveLogDiag.Log1( + "{0} >> Start() >> calling uniCB.MeasureFlow(false, flowMeter.Idx1={1})", + regV.Name, flowMeter.Idx1); + uniCB.MeasureFlow(false, flowMeter.Idx1); - opState = OpState.Wait4FlowMsrmntAndSendRVMove; - } + opState = OpState.Wait4FlowMsrmntAndSendRVMove; - /// + LiveLogDiag.Log1( + "{0} >> Start() >> opState={1}", + regV.Name, opState); + } + + /// /// Run this operation /// - /// - /// Event.OpArgumentError - /// Event.Starting - /// Event.Busy - /// Event.FlowReached - /// Event.RegulValveTimeOut - /// - public Event Run() - { + public Event Run() + { log.DebugFormat("Op.Run() opState={0}", opState); - if (StateMachine.Time > expireTime) return Event.RegulValveTimeOut; + LiveLogDiag.Log1( + "{0} >> Run() >> time={1} opState={2} currentReqFlowLo={3} currentReqFlowHi={4} isFlowOkDuration={5}", + regV.Name, StateMachine.Time, opState, currentReqFlowLo, currentReqFlowHi, isFlowOkDuration); + + if (StateMachine.Time > expireTime) + { + LiveLogDiag.Log1( + "{0} >> Run() >> TIMEOUT: StateMachine.Time={1} > expireTime={2}", + regV.Name, StateMachine.Time, expireTime); + + return Event.RegulValveTimeOut; + } if (opState == OpState.Wait4FlowMsrmntAndSendRVMove) { - if (!flowMeter.MsrmntAvailable) return Event.Starting; + LiveLogDiag.Log1( + "{0} >> Run() >> Wait4FlowMsrmntAndSendRVMove: MsrmntAvailable={1}", + regV.Name, flowMeter.MsrmntAvailable); + + if (!flowMeter.MsrmntAvailable) + return Event.Starting; double flow1 = flowMeter.ReadFlow(); - /// Set the targer flow/frequency range - currentReqFlowLo = shrinkedTgtFlowLo; /// Default lower limit - currentReqFlowHi = shrinkedTgtFlowHi; /// Default upper limit - //if (flow1 >= targetFlowAve) currentReqFlowHi = targetFlowAve; /// Decrease upper limit - //if (flow1 <= targetFlowAve) currentReqFlowLo = targetFlowAve; /// Increase lower limit + LiveLogDiag.Log1( + "{0} >> Run() >> Wait4FlowMsrmntAndSendRVMove: initial measured flow1={1}", + regV.Name, flow1); + + /// Set the target flow/frequency range + currentReqFlowLo = shrinkedTgtFlowLo; + currentReqFlowHi = shrinkedTgtFlowHi; + + LiveLogDiag.Log1( + "{0} >> Run() >> target range assigned: currentReqFlowLo={1} currentReqFlowHi={2} maximalFlow={3}", + regV.Name, currentReqFlowLo, currentReqFlowHi, maximalFlow); + + //if (flow1 >= targetFlowAve) currentReqFlowHi = targetFlowAve; + //if (flow1 <= targetFlowAve) currentReqFlowLo = targetFlowAve; if ((currentReqFlowLo >= currentReqFlowHi) || (currentReqFlowLo > maximalFlow) || (currentReqFlowHi <= 0)) { + LiveLogDiag.Log1( + "{0} >> Run() >> OpArgumentError: currentReqFlowLo={1} currentReqFlowHi={2} maximalFlow={3}", + regV.Name, currentReqFlowLo, currentReqFlowHi, maximalFlow); + return Event.OpArgumentError; } if (StateMachine.Time > setFlowTime) { - uniCB.SetFlow(false, regV.Idx1, flowMeter.NominalFreq * currentReqFlowLo / flowMeter.NominalFlow, - flowMeter.NominalFreq * currentReqFlowHi / flowMeter.NominalFlow); + double freqLo = flowMeter.NominalFreq * currentReqFlowLo / flowMeter.NominalFlow; + double freqHi = flowMeter.NominalFreq * currentReqFlowHi / flowMeter.NominalFlow; + + LiveLogDiag.Log1( + "{0} >> Run() >> calling uniCB.SetFlow(false, rv#={1}, freqLo={2}, freqHi={3}) from nominalFreq={4}, nominalFlow={5}, flowLo={6}, flowHi={7}", + regV.Name, regV.Idx1, freqLo, freqHi, flowMeter.NominalFreq, flowMeter.NominalFlow, currentReqFlowLo, currentReqFlowHi); + + uniCB.SetFlow(false, regV.Idx1, freqLo, freqHi); log.InfoFormat("Run(): rv#={0} TARGET: flowLo={1} flowHi={2}", regV.Idx1, currentReqFlowLo, currentReqFlowHi); opState = OpState.SettingFlow; + + LiveLogDiag.Log1( + "{0} >> Run() >> opState changed to {1}", + regV.Name, opState); + } + else + { + LiveLogDiag.Log1( + "{0} >> Run() >> waiting for delay: StateMachine.Time={1}, setFlowTime={2}", + regV.Name, StateMachine.Time, setFlowTime); } return Event.Starting; } - if (opState == OpState.ValveMoveToPosition1) - { - opState = OpState.ValveMoveToPosition2; - return Event.Starting; - } - else if (opState == OpState.ValveMoveToPosition2) /// Move to position - { - /// Issues the appropriate ValveMove(...) command - regV.MoveToPosition(false, targetPositionLo, targetPositionHi); + if (opState == OpState.ValveMoveToPosition1) + { + LiveLogDiag.Log1("{0} >> Run() >> ValveMoveToPosition1 -> ValveMoveToPosition2", regV.Name); + opState = OpState.ValveMoveToPosition2; + return Event.Starting; + } + else if (opState == OpState.ValveMoveToPosition2) + { + LiveLogDiag.Log1( + "{0} >> Run() >> ValveMoveToPosition2: MoveToPosition(targetPositionLo={1}, targetPositionHi={2})", + regV.Name, targetPositionLo, targetPositionHi); + + regV.MoveToPosition(false, targetPositionLo, targetPositionHi); - opState = OpState.SettingPosition; - return Event.Starting; - } - else if (opState == OpState.ValveMoveToPosition3) - { opState = OpState.SettingPosition; - return Event.Starting; - } - else if (opState == OpState.SettingPosition) - { - /// Repeated untill position is reached + + LiveLogDiag.Log1("{0} >> Run() >> opState changed to {1}", regV.Name, opState); + return Event.Starting; + } + else if (opState == OpState.ValveMoveToPosition3) + { + LiveLogDiag.Log1("{0} >> Run() >> ValveMoveToPosition3 -> SettingPosition", regV.Name); + + opState = OpState.SettingPosition; + return Event.Starting; + } + else if (opState == OpState.SettingPosition) + { double rvPosition = regV.Position; + + LiveLogDiag.Log1( + "{0} >> Run() >> SettingPosition: rvPosition={1}, targetPositionLo={2}, targetPositionHi={3}", + regV.Name, rvPosition, targetPositionLo, targetPositionHi); + if ((targetPositionLo <= rvPosition) && (rvPosition <= targetPositionHi)) - { - opState = OpState.Wait4FlowMsrmntAndSendRVMove; - } - return Event.Starting; - } - else if (opState == OpState.SettingFlow) - { - /// Regulation valve is setting flow to the required value - /// + { + opState = OpState.Wait4FlowMsrmntAndSendRVMove; + + LiveLogDiag.Log1( + "{0} >> Run() >> position reached, opState changed to {1}", + regV.Name, opState); + } + + return Event.Starting; + } + else if (opState == OpState.SettingFlow) + { double frequency = flowMeter.ReadFrequency(); double flow = flowMeter.ReadFlow(); - if (msrdFlow != null && flow != 0) msrdFlow.Val = flow; + + LiveLogDiag.Log1( + "{0} >> Run() >> SettingFlow: frequency={1} flow={2} reqLo={3} reqHi={4}", + regV.Name, frequency, flow, currentReqFlowLo, currentReqFlowHi); + + if (msrdFlow != null && flow != 0) + { + msrdFlow.Val = flow; + + LiveLogDiag.Log1( + "{0} >> Run() >> SettingFlow: msrdFlow.Val updated to {1}", + regV.Name, msrdFlow.Val); + } if (currentReqFlowLo <= flow && flow <= currentReqFlowHi) - { - isFlowOkDuration++; /// Increment the flow within range duration + { + isFlowOkDuration++; + + LiveLogDiag.Log1( + "{0} >> Run() >> SettingFlow: flow IN RANGE, isFlowOkDuration={1}/{2}", + regV.Name, isFlowOkDuration, regV.FlowStableSec); if (isFlowOkDuration >= regV.FlowStableSec) - { - /// Flow is within range for sufficiently long time + { if (regV.StoredPositionReuse) - { - double rvPosition = regV.Position; /// Read the current position + { + double rvPosition = regV.Position; double storedPosition; - if (regV.Dict.TryGetValue(targetFlowAve, out storedPosition)) - { - /// update the stored valve position + + LiveLogDiag.Log1( + "{0} >> Run() >> StoredPositionReuse ON: rvPosition={1} targetFlowAve={2}", + regV.Name, rvPosition, targetFlowAve); + + if (regV.Dict.TryGetValue(targetFlowAve, out storedPosition)) + { StoreTargetPosition(targetFlowAve, (rvPosition + storedPosition) / 2.0); - log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% stored={3} <--- Updating a stored position", - regV.Idx1, targetFlowAve, rvPosition.ToString("F1"), storedPosition); - } - else - { - /// store the valve position - StoreTargetPosition(targetFlowAve, rvPosition); - log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% <--- Storing a new position", - regV.Idx1, targetFlowAve, rvPosition.ToString("F1")); - } - } - log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, REACHED)", flow, currentReqFlowLo, currentReqFlowHi); + log.InfoFormat( + "Run(): rv#={0} reqFlow={1} pos={2}% stored={3} <--- Updating a stored position", + regV.Idx1, targetFlowAve, rvPosition.ToString("F1"), storedPosition); - opState = OpState.FlowReached; - return Event.FlowReached; - } - else - { - log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, FLOW_OK_TIMER={3}s)", flow, currentReqFlowLo, currentReqFlowHi, isFlowOkDuration); - return Event.Busy; - } - } - else - { - /// Flow is out of range + LiveLogDiag.Log1( + "{0} >> Run() >> updating stored position: old={1} newAvg={2}", + regV.Name, storedPosition, (rvPosition + storedPosition) / 2.0); + } + else + { + StoreTargetPosition(targetFlowAve, rvPosition); + + log.InfoFormat( + "Run(): rv#={0} reqFlow={1} pos={2}% <--- Storing a new position", + regV.Idx1, targetFlowAve, rvPosition.ToString("F1")); + + LiveLogDiag.Log1( + "{0} >> Run() >> storing new position: {1}", + regV.Name, rvPosition); + } + } + + log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, REACHED)", flow, currentReqFlowLo, currentReqFlowHi); + + opState = OpState.FlowReached; + + LiveLogDiag.Log1( + "{0} >> Run() >> FLOW REACHED, opState changed to {1}", + regV.Name, opState); + + return Event.FlowReached; + } + else + { + log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, FLOW_OK_TIMER={3}s)", flow, currentReqFlowLo, currentReqFlowHi, isFlowOkDuration); + + LiveLogDiag.Log1( + "{0} >> Run() >> flow in range but not stable long enough yet", + regV.Name); + + return Event.Busy; + } + } + else + { isFlowOkDuration = 0; - + log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2})", flow, currentReqFlowLo, currentReqFlowHi); - return Event.Busy; - } - } - else /// opState == OpState.FlowReached - { - log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, REACHED)", flowMeter.ReadFlow(), currentReqFlowLo, currentReqFlowHi); - return Event.FlowReached; - } - } + + LiveLogDiag.Log1( + "{0} >> Run() >> SettingFlow: flow OUT OF RANGE, reset isFlowOkDuration to 0", + regV.Name); + + return Event.Busy; + } + } + else + { + double finalFlow = flowMeter.ReadFlow(); + + log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, REACHED)", finalFlow, currentReqFlowLo, currentReqFlowHi); + + LiveLogDiag.Log1( + "{0} >> Run() >> FlowReached state: finalFlow={1} reqLo={2} reqHi={3}", + regV.Name, finalFlow, currentReqFlowLo, currentReqFlowHi); + + return Event.FlowReached; + } + } /// Stop this operation public void Stop() - { + { + LiveLogDiag.Log1( + "{0} >> Stop() >> leaveFlowControlRunning={1} opState(before)={2}", + regV.Name, leaveFlowControlRunning, opState); + if (!leaveFlowControlRunning) { - uniCB.StopFlowControl(false, regV.Idx1); /// Stop the flow measurement + LiveLogDiag.Log1( + "{0} >> Stop() >> calling uniCB.StopFlowControl(false, regV.Idx1={1})", + regV.Name, regV.Idx1); + + uniCB.StopFlowControl(false, regV.Idx1); } opState = OpState.Idle; + + LiveLogDiag.Log1( + "{0} >> Stop() >> opState(after)={1}", + regV.Name, opState); } - } -} + + /// + /// Logging + /// For activation use compilation condition: LIVELOGDIAG_FlowMeter_cs + /// + static class LiveLogDiag + { + [Conditional("LIVELOGDIAG_RegValve_cs")] + public static void Log1(string format, params object[] args) + { + LiveLogCache.Instance.AddLog("RegValve.cs LOG>> " + string.Format(format, args)); + } + } + } +} \ No newline at end of file diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index da9be45ed..2e8dee076 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -71,7 +71,7 @@ bin\x86\Release\ - TRACE;CAMERA;LANG_PL;IPERL; + TRACE;CAMERA;LANG_PL;IPERL;LIVELOGDIAG_FlowMeter_cs;LIVELOGDIAG_RegValve_cs true pdbonly AnyCPU