tbf/TestBenchFramework/BenchControl/Elde/Valve/SetValvesOp.cs
2014-08-01 08:36:17 +02:00

196 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.GenericDevices;
namespace TBF.BenchControl.Elde.Valve
{
public class SetValvesOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(SetValvesOp));
/// Set by the constructor
ControlBoardDev controlBoard;
class SwitchPoint
{
public int TimeSec;
public IList<IValve> VOpen;
public IList<IValve> VClose;
public ulong MasksOpen;
public ulong MasksClose;
}
IList<SwitchPoint> switchPointsRaw;
IList<SwitchPoint> switchPoints;
int nextIx;
int swStartTime;
/// <summary>
/// Processes coupled valves and creates switch points.
/// </summary>
/// <param name="valvesOpen">A list of opening master valves</param>
/// <param name="valvesClose">A list of closing master valves</param>
/// <returns></returns>
IList<SwitchPoint> CollectSwitchPoints(IList<IValve> valvesOpen, IList<IValve> valvesClose)
{
IList<SwitchPoint> result = new List<SwitchPoint>();
result.Add(new SwitchPoint { TimeSec = 0, VOpen = valvesOpen, VClose = valvesClose });
foreach (var valve in StateMachine.CoupledValves)
{
if ((!valve.Invert && valvesOpen.Contains(valve.CoupledTo)) ||
(valve.Invert && valvesClose.Contains(valve.CoupledTo)))
{
/// The coupled valve 'valve' is opening
int time = valve.LagOpening;
if (time == 0)
{
result[0].VOpen.Add(valve);
}
else
{
result.Add(new SwitchPoint { TimeSec = time,
VOpen = ValveBase.MakeList(valve),
VClose = new List<IValve>() });
}
}
else if ((!valve.Invert && valvesClose.Contains(valve.CoupledTo)) ||
(valve.Invert && valvesOpen.Contains(valve.CoupledTo)))
{
/// The coupled valve 'valve' is closing
int time = valve.LagClosing;
if (time == 0)
{
result[0].VClose.Add(valve);
}
else
{
result.Add(new SwitchPoint { TimeSec = time,
VOpen = new List<IValve>(),
VClose = ValveBase.MakeList(valve) });
}
}
}
return result;
}
IList<SwitchPoint> SortAndMergeSwitchPoints(IList<SwitchPoint> unsorted)
{
IList<SwitchPoint> result = new List<SwitchPoint>();
SwitchPoint lastAdded = null;
while (unsorted.Count > 0)
{
SwitchPoint first = null;
foreach (var point in unsorted)
{
if (first == null || first.TimeSec > point.TimeSec) first = point;
}
if (lastAdded == null || lastAdded.TimeSec != first.TimeSec)
{
result.Add(first);
lastAdded = first;
}
else
{
lastAdded.VOpen = ValveBase.Merge(lastAdded.VOpen, first.VOpen);
lastAdded.VClose = ValveBase.Merge(lastAdded.VClose, first.VClose);
}
unsorted.Remove(first);
}
return result;
}
void MakeMasks(IList<SwitchPoint> switchPoints, int timeShift)
{
foreach (var point in switchPoints)
{
/// Only Elde.Valve valves are used, other valves are ignored
point.MasksOpen = 0;
foreach (var valve in point.VOpen)
{
if (valve is Valve) point.MasksOpen |= (valve as Valve).Mask;
if (valve is Pump.Pump) point.MasksOpen |= (valve as Pump.Pump).Mask;
if (valve is PumpWithFM.Pump) point.MasksOpen |= (valve as PumpWithFM.Pump).Mask;
}
point.MasksClose = 0;
foreach (var valve in point.VClose)
{
if (valve is Valve) point.MasksClose |= (valve as Valve).Mask;
if (valve is Pump.Pump) point.MasksClose |= (valve as Pump.Pump).Mask;
if (valve is PumpWithFM.Pump) point.MasksClose |= (valve as PumpWithFM.Pump).Mask;
}
point.TimeSec += timeShift;
}
}
/// <summary>
/// Open and/or close multiple valves.
/// Events: ValvesSet
/// </summary>
/// <param name="controlBoard">Control board device</param>
/// <param name="valvesOpen">A list of opening master valves</param>
/// <param name="valvesClose">A list of closing master valves</param>
/// <remarks>Only Elde.Valve valves are used, other valves on the lists are ignored</remarks>
public SetValvesOp(ControlBoardDev controlBoard, IList<IValve> valvesOpen, IList<IValve> valvesClose)
{
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
this.controlBoard = controlBoard;
if (valvesOpen == null) valvesOpen = new List<IValve>();
if (valvesClose == null) valvesOpen = new List<IValve>();
switchPointsRaw = CollectSwitchPoints(valvesOpen, valvesClose);
switchPoints = SortAndMergeSwitchPoints(switchPointsRaw);
int timeShift = -switchPoints[0].TimeSec;
MakeMasks(switchPoints, timeShift);
}
/// <summary>
/// Open one valve and/or close one valve.
/// Events: ValvesSet
/// </summary>
/// <param name="controlBoard">Control board device</param>
/// <param name="valveOpen">Valve to be opened</param>
/// <param name="valveClose">Valve to be closed</param>
/// <remarks>Only Elde.Valve valves are used, other valves on the lists are ignored</remarks>
public SetValvesOp(ControlBoardDev controlBoard, IValve valveOpen, IValve valveClose)
: this(controlBoard, ValveBase.MakeList(valveOpen), ValveBase.MakeList(valveClose))
{
}
/// <summary>Start this operation</summary>
public void Start()
{
controlBoard.SetValves(switchPoints[0].MasksOpen, switchPoints[0].MasksClose);
swStartTime = StateMachine.Time;
nextIx = 1;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.SetValvesDone
/// </returns>
public Event Run()
{
if (nextIx >= switchPoints.Count) return Event.ValvesSet;
if (StateMachine.Time >= swStartTime + switchPoints[nextIx].TimeSec)
{
controlBoard.SetValves(switchPoints[nextIx].MasksOpen, switchPoints[nextIx].MasksClose);
nextIx++;
}
return Event.None;
}
/// <summary>Start this operation</summary>
public void Stop()
{
}
}
}