Files
tbf/TBF/BenchControl/ControlBoard/Uni/Action.cs
T

313 lines
12 KiB
C#

///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using log4net;
using Dirichlet.Numerics;
namespace TBF.BenchControl.ControlBoard.Uni
{
public enum ActionID
{
/// Basic
ChangeRoute = 1, /// Change digital outputs (route)
SetFlow = 2, /// Set flow
MeasureFlow = 4, /// Activate a flow meter to measure the flow
StartTest = 8, /// Start a test
Stop = 16, /// Stop a test or a flow regulation
SwitchDiverter = 32, /// Switch diverter to tank/sink
/// Advanced
GetDiverterTransitionData,
GetScopeAnalyzerData,
ResetScopeAnalyzer,
GetSwitchCounterData,
}
public class Action
{
private static readonly ILog log = LogManager.GetLogger(typeof(Action));
public ActionID ActionId { get; set; }
public ulong Route { get; set; } /// ChangeRoute argument
public int FlowMId { get; set; } /// SetFlow, MeasureFlow and StartTest argument
public int RegVId { get; set; } /// SetFlow and StartTest argument
public int DivId { get; set; } /// StartTest and SwitchDiverter argument
public bool IsSyncMethod { get; set; } /// StartTest argument
public bool IsDivUsed { get; set; } /// StartTest argument
public bool ToTank { get; set; } /// SwitchDiverter argument
public int TotalPulsesCount { get; set; } /// StartTest argument
public int MassPulsesCount { get; set; } /// StartTest argument
public int FlowRegP1 { get; set; } /// SetFlow
public int FlowRegP2 { get; set; } /// SetFlow
public int PID { get; set; } /// SetFlow
public int TolerRV { get; set; } /// SetFlow
public int StabTime { get; set; } /// SetFlow
public int DivThreshold { get; set; } /// StartTest argument
int StartStop { get; set; } /// Implicitly used by SetFlow, StartTest and Stop: -1=not defined, 0=stop, 1=start
public Action()
{
/// Values -1 indicate the related arguments are not used yet
FlowMId = -1;
RegVId = -1;
DivId = -1;
StartStop = -1;
/// These values are used by one action type only. No conflicts possible
Route = 0;
FlowRegP1 = 0;
FlowRegP2 = 0;
TotalPulsesCount = 0;
MassPulsesCount = 0;
}
public bool IsStart()
{
return (ActionId & (ActionID.SetFlow | ActionID.StartTest)) != 0;
}
public bool IsStop()
{
return (ActionId & ActionID.Stop) != 0;
}
///----------------------------------------------------------------------------------------------
public static Action ChangeRoute(ulong route)
{
return new Action
{
ActionId = ActionID.ChangeRoute,
Route = route,
};
}
void SetChangeRouteArgs(Action action)
{
Route = action.Route;
}
bool CompareChangeRouteArgs(Action action)
{
return Route == action.Route;
}
///----------------------------------------------------------------------------------------------
public static Action MeasureFlow(int flowMeterId)
{
return new Action
{
ActionId = ActionID.MeasureFlow,
FlowMId = flowMeterId,
};
}
void SetMeasureFlowArgs(Action action)
{
FlowMId = action.FlowMId;
}
bool CompareMeasureFlowArgs(Action action)
{
return (FlowMId == -1 || FlowMId == action.FlowMId);
}
///----------------------------------------------------------------------------------------------
public static Action SetFlow(int flowMeterId, int regValveId, int flowRegPar1, int flowRegPar2,
int pid, int tolerRV, int stabTime)
{
return new Action
{
ActionId = ActionID.SetFlow,
FlowMId = flowMeterId,
RegVId = regValveId,
FlowRegP1 = flowRegPar1,
FlowRegP2 = flowRegPar2,
PID = pid,
TolerRV = tolerRV,
StabTime = stabTime,
StartStop = 1,
};
}
void SetSetFlowArgs(Action action)
{
FlowMId = action.FlowMId;
RegVId = action.RegVId;
FlowRegP1 = action.FlowRegP1;
FlowRegP2 = action.FlowRegP2;
PID = action.PID;
TolerRV = action.TolerRV;
StabTime = action.StabTime;
StartStop = 1;
}
bool CompareSetFlowArgs(Action action)
{
return (FlowMId == -1 || FlowMId == action.FlowMId) &&
(RegVId == -1 || RegVId == action.RegVId) &&
(StartStop == -1 || StartStop == 1);
}
///----------------------------------------------------------------------------------------------
public static Action StartTest(int flowMId, int divId, int divThreshold, bool isSyncMethod,
bool isDivUsed, int totalPulsesCount, int massPulsesCount = -1)
{
return new Action
{
ActionId = ActionID.StartTest,
FlowMId = flowMId,
DivId = divId,
DivThreshold = divThreshold,
IsSyncMethod = isSyncMethod,
IsDivUsed = isDivUsed,
TotalPulsesCount = totalPulsesCount,
MassPulsesCount = (massPulsesCount == -1) ? totalPulsesCount : massPulsesCount,
StartStop = 1,
};
}
void SetStartTestArgs(Action action)
{
FlowMId = action.FlowMId;
DivId = action.DivId;
DivThreshold = action.DivThreshold;
IsSyncMethod = action.IsSyncMethod;
IsDivUsed = action.IsDivUsed;
TotalPulsesCount = action.TotalPulsesCount;
MassPulsesCount = action.MassPulsesCount;
StartStop = 1;
}
bool CompareStartTestArgs(Action action)
{
return (FlowMId == -1 || FlowMId == action.FlowMId) &&
(DivId == -1 || DivId == action.DivId) &&
(StartStop == -1 || StartStop == 1);
}
///----------------------------------------------------------------------------------------------
public static Action Stop()
{
return new Action()
{
ActionId = ActionID.Stop,
StartStop = 0,
};
}
void SetStopArgs(Action action)
{
StartStop = 0;
}
bool CompareStopArgs(Action action)
{
return (StartStop == -1 || StartStop == 0);
}
///----------------------------------------------------------------------------------------------
public static Action SwitchDiverter(int divId, bool toTank)
{
return new Action
{
ActionId = ActionID.SwitchDiverter,
DivId = divId,
ToTank = toTank,
};
}
void SetSwitchDiverterArgs(Action action)
{
DivId = action.DivId;
ToTank = action.ToTank;
}
bool CompareSwitchDiverterArgs(Action action)
{
return (DivId == -1 || DivId == action.DivId);
}
///----------------------------------------------------------------------------------------------
void SetArgs(Action action)
{
ActionId |= action.ActionId;
switch (action.ActionId)
{
case ActionID.ChangeRoute: SetChangeRouteArgs(action); return;
case ActionID.MeasureFlow: SetMeasureFlowArgs(action); return;
case ActionID.SetFlow: SetSetFlowArgs(action); return;
case ActionID.StartTest: SetStartTestArgs(action); return;
case ActionID.Stop: SetStopArgs(action); return;
case ActionID.SwitchDiverter: SetSwitchDiverterArgs(action); return;
default: return;
}
}
/// <summary>
/// Checks whether there is a conflict in usage of arguments.
/// </summary>
/// <param name="action">2nd action</param>
/// <returns>true if there is no conflict</returns>
bool CompareSharedArgs(Action action)
{
switch (action.ActionId)
{
case ActionID.ChangeRoute: return CompareChangeRouteArgs(action);
case ActionID.MeasureFlow: return CompareMeasureFlowArgs(action);
case ActionID.SetFlow: return CompareSetFlowArgs(action);
case ActionID.StartTest: return CompareStartTestArgs(action);
case ActionID.Stop: return CompareStopArgs(action);
case ActionID.SwitchDiverter: return CompareSwitchDiverterArgs(action);
default: return false;
}
}
///----------------------------------------------------------------------------------------------
public static Action FetchNonConflictingActions(Queue<Action> queue)
{
log.Debug("Fetching non conflicting actions:");
if (queue == null || queue.Count == 0) return null;
Action resultA = queue.Dequeue();
log.Debug(resultA.ToString());
while (queue.Count > 0)
{
var peekA = queue.Peek();
if ((resultA.ActionId & peekA.ActionId) == 0 && resultA.CompareSharedArgs(peekA) == true)
{
/// ActionId would not be repeated and arguments are compatible => apply the new action
resultA.SetArgs(peekA);
log.Debug(peekA.ToString());
queue.Dequeue();
}
else
{
/// Leave actions in the queue and quit the loop as the next scheduled action is incompatible
break;
}
}
return resultA;
}
public override string ToString()
{
string args;
switch (ActionId)
{
case ActionID.ChangeRoute:
args = string.Format("Route={0}", Route.ToString("X16"));
break;
case ActionID.SetFlow:
args = string.Format("Etalon={0} RV={1} Par1={2} Par2={3}", FlowMId, RegVId, FlowRegP1, FlowRegP2);
break;
case ActionID.MeasureFlow:
args = string.Format("Etalon={0}", FlowMId);
break;
case ActionID.StartTest:
args = string.Format("Etalon={0} TotalP={1} MassP={2}", FlowMId, TotalPulsesCount, MassPulsesCount);
break;
default:
args = string.Empty;
break;
}
return string.Format(" {0} {1}", ActionId, args);
}
}
}