diff --git a/Config/Entities/FeedingPath.cs b/Config/Entities/FeedingPath.cs index 349cba747..731058a1d 100644 --- a/Config/Entities/FeedingPath.cs +++ b/Config/Entities/FeedingPath.cs @@ -18,7 +18,7 @@ namespace Config.Entities public virtual Unit FlowUnit { get; set; } /// Not mapped to database, used in UI public virtual string Selector { get; set; } public virtual string Pump { get; set; } - public virtual string RegVPositions { get; set; } /// Positions of regulation valves in % separated by ';' + public virtual string RegVPositions { get; set; } /// Positions of regulation valves in Category.Feeding in % separated by ';' /// Valves public virtual string ValvesOpen { get; set; } diff --git a/Config/Entities/OutputPath.cs b/Config/Entities/OutputPath.cs index 3d09e3d55..08280dbf0 100644 --- a/Config/Entities/OutputPath.cs +++ b/Config/Entities/OutputPath.cs @@ -24,6 +24,7 @@ namespace Config.Entities public virtual string Diverter { get; set; } public virtual string TempMtrDiv { get; set; } public virtual string Scale { get; set; } + public virtual string RegVPositions { get; set; } /// Positions of regulation valves in Category.Output in % separated by ';' /// Valves public virtual string ValvesOpen { get; set; } @@ -63,6 +64,7 @@ namespace Config.Entities result.Diverter = Diverter; result.TempMtrDiv = TempMtrDiv; result.Scale = Scale; + result.RegVPositions= RegVPositions; result.ValvesOpen = ValvesOpen; result.ValvesClose = ValvesClose; diff --git a/Config/Mappings/OutputPathMap.cs b/Config/Mappings/OutputPathMap.cs index 049825d11..4f15ea422 100644 --- a/Config/Mappings/OutputPathMap.cs +++ b/Config/Mappings/OutputPathMap.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2013-2015 Sensus Metering Systems +/// Copyright (c) 2013-2022 Sensus Slovensko a.s. /// using FluentNHibernate.Mapping; using Config.Entities; @@ -23,6 +23,7 @@ namespace Config.Mappings Map(x => x.Diverter); Map(x => x.TempMtrDiv); Map(x => x.Scale); + Map(x => x.RegVPositions); Map(x => x.ValvesOpen) .CustomType("StringClob") .CustomSqlType("varchar(8000)"); diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index 74bf75903..0482e4a7a 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("3.3.1973.0")] -[assembly: AssemblyFileVersion("3.3.1973.0")] +[assembly: AssemblyVersion("3.4.1975.0")] +[assembly: AssemblyFileVersion("3.4.1975.0")] diff --git a/TBF/Rig/FeedingPath.cs b/TBF/Rig/FeedingPath.cs index 706686088..f96c34bca 100644 --- a/TBF/Rig/FeedingPath.cs +++ b/TBF/Rig/FeedingPath.cs @@ -13,21 +13,19 @@ namespace TBF.Rig public double Qfrom; public double Qto; public string Selector; - public IValve Pump; /// pump to use with this path or null - public IList RegulValves; - public IList RegulValvesPct; - public IList ValvesOpen; /// a list of valves to open or null - public IList ValvesClose; /// a list of valves to close or null + public IValve Pump; /// pump to use with this path or null + public IList RegVPositions; + public IList ValvesOpen; /// a list of valves to open or null + public IList ValvesClose; /// a list of valves to close or null /// Constructor from name, the rest is empty public FeedingPath(string name, int itemNr) { ItemNr = itemNr; Name = name; - ValvesOpen = new List(); + RegVPositions = new List(); + ValvesOpen = new List(); ValvesClose = new List(); - RegulValves = new List(); - RegulValvesPct = new List(); } /// Constructor from data entity @@ -40,29 +38,22 @@ namespace TBF.Rig Pump = TbfComponents.FindComponent(entity.Pump, components) as IValve; /// - /// Feeding regulation valve components + /// Feeding regulation valves and their positions /// + RegVPositions.Clear(); foreach (var cmpnt in components) { - IRegValve regValve = cmpnt as IRegValve; - if (regValve != null && regValve.Category == TBF.Rig.ValveCategory.Feeding) + IRegValve rv = cmpnt as IRegValve; + if (rv != null && rv.Category == TBF.Rig.ValveCategory.Feeding && !(rv is TBF.Rig.Uni.RegValveTandem.RegValveTandem)) { - RegulValves.Add(regValve); + RegVPositions.Add(new RegValvePosition(rv)); } } + TBF.Utils.UpdateRegVPositionsFromStr(ref RegVPositions, entity.RegVPositions); /// - /// Feeding regulation valve precentages + /// Regular valves to open /// - string[] rvPosStr = (entity.RegVPositions != null) ? entity.RegVPositions.Split(new char[] { ';' }) : new string[0]; - for (int i = 0; i < RegulValves.Count; i++) - { - string str = (i < rvPosStr.Length) ? rvPosStr[i] : "---"; - float pct; - if (!Utils.TryParseUFloat(str, out pct) || pct > 100.0f || str == "---") pct = 0; - RegulValvesPct.Add(pct); - } - string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' }); ValvesOpen = new List(); foreach (var vName in vOpen) @@ -71,6 +62,9 @@ namespace TBF.Rig if (cmpnt is IValve) ValvesOpen.Add(cmpnt as IValve); } + /// + /// Regular valves to close + /// string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); ValvesClose = new List(); foreach (var vName in vClose) diff --git a/TBF/Rig/OutputPath.cs b/TBF/Rig/OutputPath.cs index b2a8738d1..ea3365fd7 100644 --- a/TBF/Rig/OutputPath.cs +++ b/TBF/Rig/OutputPath.cs @@ -27,6 +27,7 @@ namespace TBF.Rig public IValve StartValve3; public bool InvertSV3; public int LagSV3; + public IList RegVPositions; public IList ValvesOpen; public IList ValvesClose; @@ -35,6 +36,7 @@ namespace TBF.Rig { ItemNr = itemNr; Name = name; + RegVPositions = new List(); ValvesOpen = new List(); ValvesClose = new List(); } @@ -65,6 +67,23 @@ namespace TBF.Rig InvertSV3 = (svs.Length > 6) ? svs[6].Equals("i") : false; LagSV3 = (svs.Length > 7 && int.TryParse(svs[7], out iTmp)) ? iTmp : 0; + /// + /// Output regulation valves and their positions + /// + RegVPositions.Clear(); + foreach (var cmpnt in components) + { + IRegValve rv = cmpnt as IRegValve; + if (rv != null && rv.Category == TBF.Rig.ValveCategory.Output && !(rv is TBF.Rig.Uni.RegValveTandem.RegValveTandem)) + { + RegVPositions.Add(new RegValvePosition(rv)); + } + } + TBF.Utils.UpdateRegVPositionsFromStr(ref RegVPositions, entity.RegVPositions); + + /// + /// Regular valves to open + /// string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' }); ValvesOpen = new List(); foreach (var vName in vOpen) @@ -73,7 +92,10 @@ namespace TBF.Rig if (cmpnt is IValve) ValvesOpen.Add(cmpnt as IValve); } - string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); + /// + /// Regular valves to close + /// + string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); ValvesClose = new List(); foreach (var vName in vClose) { diff --git a/TBF/Rig/RegValvePosition.cs b/TBF/Rig/RegValvePosition.cs new file mode 100644 index 000000000..ad214cb87 --- /dev/null +++ b/TBF/Rig/RegValvePosition.cs @@ -0,0 +1,27 @@ +/// +/// Copyright (c) 2022 Sensus Slovensko a.s. +/// +using System; +using TBF.Rig.GenericDevices; + +namespace TBF.Rig +{ + public class RegValvePosition + { + public IRegValve RegValve; + public float Position; /// 0 .. 100.0f is position in %, <0 (default -1.0f) means no change + + public RegValvePosition(IRegValve regValve, float position) + { + RegValve = regValve; + Position = position; + } + + /// Constructor with reg. valve and no position change + public RegValvePosition(IRegValve regValve) + { + RegValve = regValve; + Position = -1.0f; + } + } +} diff --git a/TBF/Rig/Sequences/ProcessData.cs b/TBF/Rig/Sequences/ProcessData.cs index 5cec93a60..46cacec46 100644 --- a/TBF/Rig/Sequences/ProcessData.cs +++ b/TBF/Rig/Sequences/ProcessData.cs @@ -8,6 +8,7 @@ using SchematicDrawing; using TBF.Rig.GenericDevices; using TBF.Boxes; using TBF.Resources; +using Config.Entities; namespace TBF.Rig.Sequences { @@ -52,11 +53,35 @@ namespace TBF.Rig.Sequences /// Created when test sequence is open. /// They persist during all repetitions of the same test /// + public static Rig.OutputPath Devices { get { return outPath; } } + /// + protected static Rig.FeedingPath inPath; protected static Rig.BenchPath benchPath; protected static Rig.OutputPath outPath; - public static Rig.OutputPath Devices { get { return outPath; } } + protected static Rig.MetersPath sensPath; + protected static Rig.HeatMetersPath heatMetersPath; + protected static TransitionSequence transitionBefore; + protected static TransitionSequence transitionBetween; + protected static TransitionSequence transitionAfter; + /// + /// Advanced information about the next test + /// + protected static Rig.FeedingPath nextInPath; + protected static Rig.BenchPath nextBenchPath; + protected static Rig.OutputPath nextOutPath; + protected static Rig.MetersPath nextSensPath; + protected static Rig.HeatMetersPath nextHeatMetersPath; + protected static TransitionSequence nextTransitionBefore; + protected static double nextQfrom; + protected static double nextQto; + protected static float nextPumpPower; + protected static float nextPidCoef; + protected static int nextShortPulses; + /// + /// Schematic drawing related + /// public static readonly IList ComponentsWithMeasuredVal; public static readonly IList ComponentsWithSetpoint; public static readonly IList ComponentsWithCustomBmp; @@ -74,8 +99,11 @@ namespace TBF.Rig.Sequences /// 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; diff --git a/TBF/Rig/Sequences/SequenceBase.cs b/TBF/Rig/Sequences/SequenceBase.cs index ad10899a0..0fb5e650b 100644 --- a/TBF/Rig/Sequences/SequenceBase.cs +++ b/TBF/Rig/Sequences/SequenceBase.cs @@ -35,11 +35,11 @@ namespace TBF.Rig.Sequences ///------------------------------------------------------------ /// Global static variables set only once. ///------------------------------------------------------------ - public static IList FlowMeters; /// list of reference flowmeters - public static IList RegulValves; /// list of regulation valves - public static IList PumpsWithFM; /// list of FM controlled pumps - public static IList WaterMeters; /// list of water meters - public static IList Cameras; /// list of cameras + public static IList FlowMeters; /// list of reference flowmeters + public static IList RegVPositions; /// list of regulation valves + public static IList PumpsWithFM; /// list of FM controlled pumps + public static IList WaterMeters; /// list of water meters + public static IList Cameras; /// list of cameras ///------------------------------------------------------------ /// Procedure related (static) variables. @@ -50,34 +50,11 @@ namespace TBF.Rig.Sequences public static double Qrise; public static double Qfall; - ///------------------------------------------------------------ /// Test related (instance) variables. /// Created when test sequence is open. /// They persist during all repetitions of the same test ///------------------------------------------------------------ - protected static Rig.FeedingPath inPath; - protected static Rig.MetersPath sensPath; - protected static Rig.HeatMetersPath heatMetersPath; - - protected static TransitionSequence transitionBefore; - protected static TransitionSequence transitionBetween; - protected static TransitionSequence transitionAfter; - - /// - /// Advanced information about the next test - /// - protected static Rig.FeedingPath nextInPath; - protected static Rig.BenchPath nextBenchPath; - protected static Rig.OutputPath nextOutPath; - protected static Rig.MetersPath nextSensPath; - protected static Rig.HeatMetersPath nextHeatMetersPath; - protected static TransitionSequence nextTransitionBefore; - protected static double nextQfrom; - protected static double nextQto; - protected static float nextPumpPower; - protected static float nextPidCoef; - protected static int nextShortPulses; protected IOperation queryEnd1; @@ -347,6 +324,36 @@ namespace TBF.Rig.Sequences } + /// + /// Returns a list of reg.valve positioning operations + /// + /// List of reg.valve/position pairs, position is in %, position LT 0 ... no operation + /// List of reg.valve positioning operations + List GetRegVPositioningOps(IList regVPositions) + { + List rvPosOps = new List(); + + if (regVPositions == null) return rvPosOps; + + foreach (var rvp in regVPositions) + { + if (rvp.Position >= 0) /// Negative value means no position change + { + if (rvp.RegValve.IsCoax) + { + rvPosOps.Add(rvp.RegValve.SetRegValvePositionOp(rvp.Position, -1, 60)); + } + else + { + rvPosOps.Add(rvp.RegValve.SetRegValvePositionOp(rvp.Position - 3.0, rvp.Position + 3.0, 60)); + } + } + } + + return rvPosOps; + } + + /// /// Executes steps of a transition sequence /// @@ -432,12 +439,13 @@ namespace TBF.Rig.Sequences string activity = string.Format(message, transitionSequence.Name, step.ItemNr + 1, stepsCount); Bridge.OnActivity(this, activity); Bridge.OnMessage(this, step.Message); - log.Info(activity + " " +step.Message); + log.InfoFormat("{0} {1}", activity, step.Message); //------------------------------------------------ - /// + /// Prepare operation to switch valves + IOperation setValvesOp = StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step)); + /// Fetch the condition operation, null value is allowed if there is no condition - /// IOperation conditionOperation = null; if (step.EndCondition != "None") { @@ -469,30 +477,9 @@ namespace TBF.Rig.Sequences } } - /// Get new regulation valve positions, - float[] allRegvPositions = Utils.GetRegulValvesPositions(step.RegulValvesPct, RegulValves.Count); - /// Prepare necessary SetRegValvePositionOp operations for RV-s with changed positions - IList rvPosOps = new List(); - IList rvPosStr = new List(); - for (int i = 0; i < allRegvPositions.Length; i++) - { - if (allRegvPositions[i] >= 0) /// Negative value means no position change - { - if (RegulValves[i].IsCoax) - { - rvPosOps.Add(RegulValves[i].SetRegValvePositionOp(allRegvPositions[i], allRegvPositions[i], 60)); - rvPosStr.Add(string.Format("RV{0}.SetRegValvePositionOp({1}, {1}, 60s)", i, allRegvPositions[i])); - } - else - { - float lo = Math.Max(0, allRegvPositions[i] - 3.0f); - float hi = Math.Min(100.0f, allRegvPositions[i] + 3.0f); - rvPosOps.Add(RegulValves[i].SetRegValvePositionOp(lo, hi, 60)); - rvPosStr.Add(string.Format("RV{0}.SetRegValvePositionOp({1}, {2}, 60s)", i, lo, hi)); - } - } - } + Utils.UpdateRegVPositionsFromStr(ref RegVPositions, step.RegulValvesPct); + IList rvPosOps = GetRegVPositioningOps(RegVPositions); /// Max. one SetRegValvePositionOp can be started or stopped in one sub-step. /// Therefore SetRegValvePositionOp operations are added and removed to subsequent states one by one. @@ -507,11 +494,10 @@ namespace TBF.Rig.Sequences .Create(string.Format("SequenceBase.Transition() : Step {0} start, opening={1}, closing={2}", step.ItemNr + 1, step.ValvesOpen, step.ValvesClose)) .AddOperation(checkUiOp) .AddOperation(conditionOperation) - .AddOperation(StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step))); + .AddOperation(setValvesOp); for (int j = 0; j <= i; j++) { stepStrt.AddOperation(rvPosOps[j]); - log.Debug(rvPosStr[j]); } lastStartedRV = i; stepStrt.EnterState(); @@ -528,12 +514,11 @@ namespace TBF.Rig.Sequences .Create(string.Format("SequenceBase.Transition() : Step {0} delay {1}s, opening={2}, closing={3}", step.ItemNr + 1, delay, step.ValvesOpen, step.ValvesClose)) .AddOperation(checkUiOp) .AddOperation(conditionOperation) - .AddOperation(StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step))) + .AddOperation(setValvesOp) .AddOperation(new TimerOp(delay)); for (int j = 0; j <= lastStartedRV; j++) { stepDelay.AddOperation(rvPosOps[j]); - log.Debug(rvPosStr[j]); } stepDelay.EnterState(); bool endContitionFulfilled = false; @@ -574,11 +559,10 @@ namespace TBF.Rig.Sequences .Create(string.Format("SequenceBase.Transition() : Step {0} stop, opening={1}, closing={2}", step.ItemNr + 1, step.ValvesOpen, step.ValvesClose)) .AddOperation(checkUiOp) .AddOperation(conditionOperation) - .AddOperation(StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step))); + .AddOperation(setValvesOp); for (int j = first; j <= lastStartedRV; j++) { stepStop.AddOperation(rvPosOps[j]); - log.Debug(rvPosStr[j]); } stepStop.EnterState(); e = StateMachine.WaitRunDevsRunOps(); @@ -621,47 +605,37 @@ namespace TBF.Rig.Sequences while (!e.Contains(Event.ValvesSet)); } } - else if (context == TransitionContext.BeforeTest) + else if (context == TransitionContext.BeforeTest && inPath != null && benchPath != null && outPath != null) { log.WarnFormat("Transition(any, context={0}), setting the required route before a test", context); /// /// Always set route at the beginning of this test /// - if (inPath != null && benchPath != null && outPath != null) - { - State.Create("SequenceBase : Transition : TestStart - Default action") - .AddOperation(checkUiOp) - .AddOperation(StateMachine.ControlBoard - .SetValvesOp(BuiltIn.ValveBase.Merge(inPath.ValvesOpen, benchPath.ValvesOpen, outPath.ValvesOpen), - BuiltIn.ValveBase.Merge(inPath.ValvesClose, benchPath.ValvesClose, outPath.ValvesClose))) - .EnterState(); - do { - e = StateMachine.WaitRunDevsRunOps(); - if (e.Contains(Event.Error)) return Event.Error; - if (TestAndLogUiCmdStop(e)) return Event.UiCmdStop; - } - while (e.Contains(Event.ValvesBusy)); - } + List regVPosOps = GetRegVPositioningOps(inPath.RegVPositions); + regVPosOps.AddRange(GetRegVPositioningOps(outPath.RegVPositions)); + Event evnt = PerformSteps(BuiltIn.ValveBase.Merge(inPath.ValvesOpen, benchPath.ValvesOpen, outPath.ValvesOpen), + BuiltIn.ValveBase.Merge(inPath.ValvesClose, benchPath.ValvesClose, outPath.ValvesClose), + regVPosOps, + "SequenceBase : Transition : TestStart - Default action"); + + if (evnt == Event.Error || evnt == Event.UiCmdStop) return evnt; } else if (context == TransitionContext.AfterTestWithOverlap && nextInPath != null && nextBenchPath != null && nextOutPath != null) { log.WarnFormat("Transition(., context={0}), overlapped action (next flow regulation)", context); + /// /// Set route for the next test - State.Create("SequenceBase : AfterTestWithOverlap : Default action") - .AddOperation(checkUiOp) - .AddOperation(StateMachine.ControlBoard - .SetValvesOp(BuiltIn.ValveBase.Merge(nextInPath.ValvesOpen, nextBenchPath.ValvesOpen, nextOutPath.ValvesOpen), - BuiltIn.ValveBase.Merge(nextInPath.ValvesClose, nextBenchPath.ValvesClose, nextOutPath.ValvesClose))) - .EnterState(); - do { - e = StateMachine.WaitRunDevsRunOps(); - if (e.Contains(Event.Error)) return Event.Error; - if (TestAndLogUiCmdStop(e)) return Event.UiCmdStop; - } - while (e.Contains(Event.ValvesBusy)); + /// + List regVPosOps = GetRegVPositioningOps(nextInPath.RegVPositions); + regVPosOps.AddRange(GetRegVPositioningOps(nextOutPath.RegVPositions)); + Event evnt = PerformSteps(BuiltIn.ValveBase.Merge(nextInPath.ValvesOpen, nextBenchPath.ValvesOpen, nextOutPath.ValvesOpen), + BuiltIn.ValveBase.Merge(nextInPath.ValvesClose, nextBenchPath.ValvesClose, nextOutPath.ValvesClose), + regVPosOps, + "SequenceBase : AfterTestWithOverlap : Default action"); + if (evnt == Event.Error || evnt == Event.UiCmdStop) return evnt; /// Set PID coefficient, etc. if (StateMachine.ControlBoard is ControlBoard.Uni.UniCB) @@ -708,6 +682,69 @@ namespace TBF.Rig.Sequences } + Event PerformSteps(IList valvesToOpen, IList valvesToClose, IList rvPosOps, string stateTitle) + { + bool stopFlag = false; + bool errorFlag = false; + IList e; + + IOperation setValvesOp = StateMachine.ControlBoard.SetValvesOp(valvesToOpen, valvesToClose); + + int lastStartedRV = -1; + for (int i = 0; i < rvPosOps.Count; i++) + { + State stepStrt = State.Create(stateTitle) + .AddOperation(checkUiOp) + .AddOperation(setValvesOp); + for (int j = 0; j <= i; j++) stepStrt.AddOperation(rvPosOps[j]); + lastStartedRV = i; + stepStrt.EnterState(); + + + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error) || e.Contains(Event.RegulValveTimeOut)) { errorFlag = true; break; } + if (TestAndLogUiCmdStop(e)) { stopFlag = true; break; } + } + /// Max. valaue of lastStartedRV after exitting the loop is (rvPosOps.Count - 1) + + + if (!stopFlag && !errorFlag) + { + State stepRegul = State.Create(stateTitle) + .AddOperation(checkUiOp) + .AddOperation(setValvesOp); + for (int j = 0; j <= lastStartedRV; j++) stepRegul.AddOperation(rvPosOps[j]); + stepRegul.EnterState(); + + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error) || e.Contains(Event.RegulValveTimeOut)) { errorFlag = true; break; } + if (TestAndLogUiCmdStop(e)) { stopFlag = true; break; } + } + while (e.Contains(Event.ValvesBusy) && !e.Contains(Event.Next)); + } + + + for (int first = 1; first <= lastStartedRV; first++) + { + State stepStop = State.Create(stateTitle) + .AddOperation(checkUiOp) + .AddOperation(setValvesOp); + for (int j = first; j <= lastStartedRV; j++) stepStop.AddOperation(rvPosOps[j]); + stepStop.EnterState(); + + + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error) || e.Contains(Event.RegulValveTimeOut)) { errorFlag = true; } + if (TestAndLogUiCmdStop(e)) { stopFlag = true; } + } + + if (stopFlag) return Event.UiCmdStop; + if (errorFlag) return Event.Error; + return Event.Done; + } + + /// /// Opens a modeless dialog for entering data at the beginning of a procedure (serial numbers) /// diff --git a/TBF/Rig/StateMachine.cs b/TBF/Rig/StateMachine.cs index e3a8d1d11..b6c5c8c09 100644 --- a/TBF/Rig/StateMachine.cs +++ b/TBF/Rig/StateMachine.cs @@ -153,7 +153,7 @@ namespace TBF.Rig ProcessData.IperlHeads = new List(); SequenceBase.FlowMeters = new List(); - SequenceBase.RegulValves = new List(); + SequenceBase.RegVPositions = new List(); SequenceBase.PumpsWithFM = new List(); SequenceBase.WaterMeters = new List(); SequenceBase.Cameras = new List(); @@ -270,7 +270,7 @@ namespace TBF.Rig if (cmpnt is IFlowMeter) SequenceBase.FlowMeters.Add(cmpnt as IFlowMeter); if ((cmpnt is IRegValve) && !(cmpnt is Rig.Uni.RegValveTandem.RegValveTandem)) { - SequenceBase.RegulValves.Add(cmpnt as IRegValve); + SequenceBase.RegVPositions.Add(new RegValvePosition(cmpnt as IRegValve)); } if (cmpnt is IPumpFM && !(cmpnt is BuiltIn.PumpTandem.Pump)) SequenceBase.PumpsWithFM.Add(cmpnt as IPumpFM); if (cmpnt is IWaterMeter) SequenceBase.WaterMeters.Add(cmpnt as IWaterMeter); diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index 40f17888a..291479f1d 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -1129,6 +1129,7 @@ + diff --git a/TBF/UI/Bench/Paths/PathsDlg.cs b/TBF/UI/Bench/Paths/PathsDlg.cs index 524ab8f8d..1af831814 100644 --- a/TBF/UI/Bench/Paths/PathsDlg.cs +++ b/TBF/UI/Bench/Paths/PathsDlg.cs @@ -9,6 +9,7 @@ using log4net; using Common; using Common.Forms; using Config.Entities; +using TBF.Rig; using TBF.Rig.GenericDevices; using TBF.Resources; using TBF.UI.Shared; @@ -33,7 +34,8 @@ namespace TBF.UI.Bench.Paths public IList TbfComponents; public IList Valves; - public IList FeedingRegulValves; + public IList FeedingRegValves; + public IList OutputRegValves; public ISession Session; /// One common DB session passed also to the controls inside tab pages public IList Procedures; public IList Tests; @@ -72,13 +74,21 @@ namespace TBF.UI.Bench.Paths Valves = Rig.BuiltIn.ValveBase.GetMasterValves(TbfComponents); /// Find all feeding regulation valves - FeedingRegulValves = new List(); + FeedingRegValves = new List(); + OutputRegValves = new List(); foreach (var cmpnt in TbfComponents) { - IRegValve regValve = cmpnt as IRegValve; - if (regValve != null && regValve.Category == TBF.Rig.ValveCategory.Feeding) + if (cmpnt is IRegValve && !(cmpnt is TBF.Rig.Uni.RegValveTandem.RegValveTandem)) { - FeedingRegulValves.Add(regValve); + switch ((cmpnt as IRegValve).Category) + { + case ValveCategory.Feeding: + FeedingRegValves.Add(cmpnt as IRegValve); + break; + case ValveCategory.Output: + OutputRegValves.Add(cmpnt as IRegValve); + break; + } } } diff --git a/TBF/UI/Bench/Paths/PathsFeedingCtrl.cs b/TBF/UI/Bench/Paths/PathsFeedingCtrl.cs index 8b560a060..9f0b3d3e7 100644 --- a/TBF/UI/Bench/Paths/PathsFeedingCtrl.cs +++ b/TBF/UI/Bench/Paths/PathsFeedingCtrl.cs @@ -76,18 +76,18 @@ namespace TBF.UI.Bench.Paths Columns.Add(Strings.Pump, (ls.FeedingColumnCount > 5) ? ls.FeedingColumnWidths[5] : 60 * parent.Dpi / Constants.Dpi100pct); int clmn = (int)Column.FixedColumnsCount; - foreach (var rv in parent.FeedingRegulValves) + foreach (var rv in parent.FeedingRegValves) { - Columns.Add(rv.Cfg.Name, (ls.FeedingColumnCount > clmn) ? ls.FeedingColumnWidths[clmn] : 50 * parent.Dpi / Constants.Dpi100pct); + Columns.Add(string.Format("{0} [%]", rv.Name), (ls.FeedingColumnCount > clmn) ? ls.FeedingColumnWidths[clmn] : 50 * parent.Dpi / Constants.Dpi100pct); clmn++; } - regvCount = clmn - (int)Column.FixedColumnsCount; + regvCount = parent.FeedingRegValves.Count; foreach (var vlv in parent.Valves) { if (vlv.Category == TBF.Rig.ValveCategory.Feeding) { - Columns.Add(vlv.Cfg.Name, (ls.FeedingColumnCount > clmn) ? ls.FeedingColumnWidths[clmn] : 50 * parent.Dpi / Constants.Dpi100pct); + Columns.Add(vlv.Name, (ls.FeedingColumnCount > clmn) ? ls.FeedingColumnWidths[clmn] : 50 * parent.Dpi / Constants.Dpi100pct); clmn++; } } @@ -105,7 +105,7 @@ namespace TBF.UI.Bench.Paths if (cmpnt is IPump) pumpCBox.Items.Add(cmpnt.Cfg.Name); } - editors = new Control[fixedColumnsCount + regvCount + 64]; + editors = new Control[fixedColumnsCount + regvCount + valvesCount]; /// editors[(int)Column.Name] = new TextBox(); /// Name editors[(int)Column.Qfrom] = new TextBox(); /// Q_from @@ -125,8 +125,8 @@ namespace TBF.UI.Bench.Paths editors[fixedColumnsCount + i] = cb; } - /// Prepare valve combo-boxes (max. 64 valves) - for (int i = 0; i < 64; i++) + /// Prepare valve combo-boxes + for (int i = 0; i < valvesCount; i++) { ComboBox cb = new ComboBox(); cb.Items.Add("---"); @@ -264,7 +264,7 @@ namespace TBF.UI.Bench.Paths lvi.SubItems.Add(path.Pump != null ? path.Pump.Cfg.Name : "---"); string[] rvPosStr = (entity.RegVPositions != null) ? entity.RegVPositions.Split(new char[] {';'}) - : new string[0]; + : new string[0]; for (int i = 0; i < regvCount; i++) { lvi.SubItems.Add((i < rvPosStr.Length) ? rvPosStr[i] : "---"); @@ -322,18 +322,18 @@ namespace TBF.UI.Bench.Paths /// /// Regulation valves /// - string regulValvesPct = string.Empty; + string regulVPositions = string.Empty; for (int i = fixedColumnsCount; i < fixedColumnsCount + regvCount; i++) { - if (regulValvesPct.Length > 0) regulValvesPct += ";"; + if (regulVPositions.Length > 0) regulVPositions += ";"; float fdummy; if (lvi.SubItems[i].Text.Equals("---") || (Utils.TryParseUFloat(lvi.SubItems[i].Text, out fdummy) && (fdummy >= 0) && (fdummy <= 100.0f))) { - regulValvesPct += lvi.SubItems[i].Text; + regulVPositions += lvi.SubItems[i].Text; } } - entity.RegVPositions = regulValvesPct; + entity.RegVPositions = regulVPositions; /// /// Valves diff --git a/TBF/UI/Bench/Paths/PathsOutputCtrl.cs b/TBF/UI/Bench/Paths/PathsOutputCtrl.cs index bf55a8511..36e0ac6a7 100644 --- a/TBF/UI/Bench/Paths/PathsOutputCtrl.cs +++ b/TBF/UI/Bench/Paths/PathsOutputCtrl.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Text; using System.Windows.Forms; using log4net; using Common; @@ -48,6 +49,9 @@ namespace TBF.UI.Bench.Paths } readonly int fixedColumnsCount = (int)Column.FixedColumnsCount; + int valvescount; + int regulValvesCount; + PathsDlg parent; Control parentControl; Control[] editors; @@ -100,16 +104,25 @@ namespace TBF.UI.Bench.Paths Columns.Add(string.Format("Inv.SV3"), (ls.OutputColumnCount > 17) ? ls.OutputColumnWidths[17] : 80 * parent.Dpi / Constants.Dpi100pct); Columns.Add(string.Format("Lag SV3"), (ls.OutputColumnCount > 18) ? ls.OutputColumnWidths[18] : 80 * parent.Dpi / Constants.Dpi100pct); + valvescount = 0; + regulValvesCount = 0; int clmn = (int)Column.FixedColumnsCount; /// foreach (var vlv in parent.Valves) { if (vlv.Category == ValveCategory.Output) { - Columns.Add(vlv.Cfg.Name, (ls.OutputColumnCount > clmn) ? ls.OutputColumnWidths[clmn] : 50 * parent.Dpi / Constants.Dpi100pct); + Columns.Add(vlv.Name, (ls.OutputColumnCount > clmn) ? ls.OutputColumnWidths[clmn] : 50 * parent.Dpi / Constants.Dpi100pct); clmn++; + valvescount++; } } + foreach (var rv in parent.OutputRegValves) + { + Columns.Add(string.Format("{0} [%]", rv.Name), (ls.OutputColumnCount > clmn) ? ls.OutputColumnWidths[clmn] : 55 * parent.Dpi / Constants.Dpi100pct); + clmn++; + regulValvesCount++; + } /// Prepare fixed columns combo boxes ComboBox flowMeterComboBox = new ComboBox(); @@ -158,7 +171,7 @@ namespace TBF.UI.Bench.Paths var flowUnitBox = new ComboBox(); for (Unit u = 0; u < Unit.Count; u++) if (Units.IsFlow(u)) flowUnitBox.Items.Add(u.ToDescription()); - editors = new Control[fixedColumnsCount + 64]; + editors = new Control[fixedColumnsCount + valvescount + regulValvesCount]; /// editors[(int)Column.Name] = new TextBox(); /// Name editors[(int)Column.Qfrom] = new TextBox(); /// Q_from @@ -180,7 +193,7 @@ namespace TBF.UI.Bench.Paths editors[(int)Column.InvertSV3] = invertSV3ComboBox; editors[(int)Column.LagSV3] = lagSV3TextBox; /// Prepare valve combo-boxes (max. 64 valves) - for (int i = 0; i < 64; i++) + for (int i = 0; i < valvescount; i++) { ComboBox cb = new ComboBox(); cb.Items.Add("---"); @@ -188,7 +201,19 @@ namespace TBF.UI.Bench.Paths cb.Items.Add(Strings.close); editors[fixedColumnsCount + i] = cb; } - /// + /// Prepare regul. valve combo-boxes + for (int i = 0; i < regulValvesCount; i++) + { + ComboBox cb = new ComboBox(); + cb.Items.Add("---"); + cb.Items.Add("0"); + cb.Items.Add("25"); + cb.Items.Add("50"); + cb.Items.Add("75"); + cb.Items.Add("100"); + editors[fixedColumnsCount + valvescount + i] = cb; + } + /// for (int i = 0; i < editors.Length; i++) { editors[i].Visible = false; @@ -200,8 +225,9 @@ namespace TBF.UI.Bench.Paths void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) { - if (!Unlocked || e.SubItem >= editors.Length) return; - if ((e.Item.Tag is IHasItemNr) && + if (e.SubItem != (int)Column.FlowUnit && (!Unlocked || e.SubItem >= editors.Length)) return; + + if ((e.Item.Tag is IHasItemNr) && ((e.Item.Tag as IHasItemNr).ItemNr < FixedRowsCount) && (e.SubItem < fixedColumnsCount)) { @@ -243,10 +269,14 @@ namespace TBF.UI.Bench.Paths var entity = e.Item.Tag as Config.Entities.OutputPath; double ddummy; - if (e.SubItem >= fixedColumnsCount) + if (e.SubItem >= fixedColumnsCount && e.SubItem < fixedColumnsCount + valvescount) { e.Item.SubItems[e.SubItem].BackColor = e.DisplayText == Strings.open ? Color.LightGray : Color.White; } + else if (e.SubItem >= fixedColumnsCount + valvescount) + { + e.Item.SubItems[e.SubItem].BackColor = (e.DisplayText != "0" && e.DisplayText != "---") ? Color.LightGray : Color.White; + } else if (e.SubItem == (int)Column.Qfrom) { if (Utils.TryParseUDouble(e.DisplayText, out ddummy)) @@ -333,26 +363,43 @@ namespace TBF.UI.Bench.Paths foreach (var valve in parent.Valves) { + int subItemNr = lvi.SubItems.Count; if (valve.Category == ValveCategory.Output) { if (path.ValvesOpen != null && path.ValvesOpen.Contains(valve)) { lvi.SubItems.Add(Strings.open); - lvi.SubItems[lvi.SubItems.Count - 1].BackColor = Color.LightGray; + lvi.SubItems[subItemNr].BackColor = Color.LightGray; } else if (path.ValvesClose != null && path.ValvesClose.Contains(valve)) { lvi.SubItems.Add(Strings.close); - lvi.SubItems[lvi.SubItems.Count - 1].BackColor = Color.White; + lvi.SubItems[subItemNr].BackColor = Color.White; } else { lvi.SubItems.Add("---"); - lvi.SubItems[lvi.SubItems.Count - 1].BackColor = Color.White; + lvi.SubItems[subItemNr].BackColor = Color.White; } } } + foreach (var rvp in path.RegVPositions) + { + int subItemNr = lvi.SubItems.Count; + if (0 <= rvp.Position && rvp.Position <= 100) + { + float rvPos = rvp.Position; + lvi.SubItems.Add(rvPos.ToString()); + lvi.SubItems[subItemNr].BackColor = (rvPos == 0) ? Color.White : Color.LightGray; + } + else + { + lvi.SubItems.Add("---"); + lvi.SubItems[subItemNr].BackColor = Color.White; + } + } + lvi.Tag = entity; Items.Add(lvi); @@ -400,26 +447,46 @@ namespace TBF.UI.Bench.Paths string valvesOpen = string.Empty; string valvesClose = string.Empty; int k = 0; - for (int j = 0; j < parent.Valves.Count; j++) + foreach (var valve in parent.Valves) { - if (parent.Valves[j].Category == ValveCategory.Output) + if (valve.Category == ValveCategory.Output) { string text = lvi.SubItems[fixedColumnsCount + k].Text; if (text.Equals(Strings.open)) { if (valvesOpen != string.Empty) valvesOpen += ";"; - valvesOpen += parent.Valves[j].Cfg.Name; + valvesOpen += valve.Cfg.Name; } if (text.Equals(Strings.close)) { if (valvesClose != string.Empty) valvesClose += ";"; - valvesClose += parent.Valves[j].Cfg.Name; + valvesClose += valve.Cfg.Name; } k++; } } entity.ValvesOpen = valvesOpen; entity.ValvesClose = valvesClose; + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < regulValvesCount; i++) + { + float pct; + string text = lvi.SubItems[fixedColumnsCount + valvescount + i].Text; + if (Utils.TryParseUFloat(text, out pct) && pct >= 0 && pct <= 100.0f) + { + sb.Append(pct.ToString()); + } + else + { + sb.Append("-1"); + } + if (i != regulValvesCount - 1) + { + sb.Append(";"); + } + } + entity.RegVPositions = sb.ToString(); } public void AddOne() diff --git a/TBF/Utils.cs b/TBF/Utils.cs index 11c46af4a..41116f0e5 100644 --- a/TBF/Utils.cs +++ b/TBF/Utils.cs @@ -189,30 +189,26 @@ namespace TBF /// - /// Get an array of RegulValve positions from a TransitionStep entity + /// Update a list of regulation valve position pairs from a string /// - /// TransitionStep entity - /// float[] of regulation valve positions from 0 to 100.0f - public static float[] GetRegulValvesPositions(string regulValvesPct, int regvCount) + /// String with reg.valve positions in % separated by ';' + /// List with reg. valve / position pairs + public static void UpdateRegVPositionsFromStr(ref IList regVPositions, string regVPositionsStr) { - float[] result = new float[regvCount]; + string[] rvPosStr = string.IsNullOrEmpty(regVPositionsStr) ? new string[0] : regVPositionsStr.Split(new char[] { ';' }); - string[] rvPosStr = (regulValvesPct != null) ? regulValvesPct.Split(new char[] { ';' }) : new string[0]; - for (int i = 0; i < regvCount; i++) + for (int i = 0; i < Math.Min(rvPosStr.Length, regVPositions.Count); i++) { float fdummy; - if ((i < rvPosStr.Length) && Utils.TryParseUFloat(rvPosStr[i], out fdummy) && - (fdummy >= 0) && (fdummy <= 100.0f)) + if (Utils.TryParseUFloat(rvPosStr[i], out fdummy) && fdummy >= 0 && fdummy <= 100.0f) { - result[i] = fdummy; + regVPositions[i].Position = fdummy; } - else // if ((i < rvPosStr.Length) && rvPosStr[i].Equals("---")) + else //if (rvPosStr[i].Equals("---")) { - result[i] = -1.0f; /// Negative value means no regulation valve position change + regVPositions[i].Position = -1.0f; /// Negative value means no regulation valve position change } } - - return result; }