Limit类新增ignoreReverse属性,=true忽略单项limit反转Action

This commit is contained in:
SIC1016\caipeilun 2023-09-01 17:47:09 +08:00
parent d841220f69
commit 8f66a4d067
9 changed files with 70 additions and 47 deletions

View File

@ -41,6 +41,11 @@ public interface IInterlockLimit
/// </summary>
string Tip { get; }
/// <summary>
/// 返回该Limit是否对Action进行反转
/// </summary>
bool IgnoreReverse { get; }
/*/// <summary>
/// 判断两个互锁限制条件是否相等。
/// </summary>
@ -66,7 +71,6 @@ public interface IInterlockLimit
/// <returns></returns>
bool CanDo(out string reason);
/// <summary>
/// 获取指定互锁限制条件中限制条件的内容。
/// </summary>

View File

@ -163,11 +163,11 @@ public abstract class InterlockManagerBase<TAction>
if (actionNode.HasAttribute("tip.en-US"))
dicTips["en-US"] = actionNode.GetAttribute("tip.en-US");
var ignoreReverse = false;
var ignoreReverse_All = false;//单个Action的全局ignore为True时所有Limit条件不反向控制
if (actionNode.HasAttribute("ignoreReverse"))
{
var strIgnoreReverse = actionNode.GetAttribute("ignoreReverse");
if (!bool.TryParse(strIgnoreReverse, out ignoreReverse))
if (!bool.TryParse(strIgnoreReverse, out ignoreReverse_All))
LOG.Error($"Unable to convert attribute 'ignoreReverse' of action '{doName}' to bool.");
}
@ -213,17 +213,21 @@ public abstract class InterlockManagerBase<TAction>
_lstActions.Add(action);
// 如果当前Action设置了忽略翻转则不要注册Limit到当前Action的映射避免Limit触发导致Action翻转。
if (!ignoreReverse)
if (!ignoreReverse_All)
{
foreach (var limit in action.Limits)
{
// 创建以Limit分组的Action字典
if (!_dicLimitToActionMap.ContainsKey(limit))
_dicLimitToActionMap[limit] = new List<IInterlockAction>();
if (!limit.IgnoreReverse)//如果单个limit也忽略反转不要注册Limit到当前Action的映射避免Limit触发导致Action翻转。
{
// 创建以Limit分组的Action字典
if (!_dicLimitToActionMap.ContainsKey(limit))
_dicLimitToActionMap[limit] = new List<IInterlockAction>();
_dicLimitToActionMap[limit].Add(action);
_dicLimitToActionMap[limit].Add(action);
}
}
}
}
Debug.Assert(!_dicActionsPerModule.ContainsKey(ModuleName.UnDefined),
@ -302,6 +306,14 @@ public abstract class InterlockManagerBase<TAction>
tip = dicLimitTips["en-US"];
}
var ignoreReverse = false;
if (limitNode.HasAttribute("ignoreReverse"))
{
var strIgnoreReverse = limitNode.GetAttribute("ignoreReverse");
if (!bool.TryParse(strIgnoreReverse, out ignoreReverse))
LOG.Error($"Unable to convert attribute 'ignoreReverse' of Limit to bool.");
}
// 节点不包含didoaiao或者不包含value属性
IInterlockLimit limit;
if (limitNode.HasAttribute("di"))
@ -309,40 +321,40 @@ public abstract class InterlockManagerBase<TAction>
var limitName = limitNode.GetAttribute("di");
var io = GetIoByIoType(IOType.DI, limitName);
var provider = new DiValueProvider((DIAccessor)io);
limit = new DiLimit(provider, limitValue, tip, dicLimitTips);
limit = new DiLimit(provider, limitValue, tip, dicLimitTips, ignoreReverse);
}
else if (limitNode.HasAttribute("do"))
{
var limitName = limitNode.GetAttribute("do");
var io = GetIoByIoType(IOType.DO, limitName);
var provider = new DoValueProvider((DOAccessor)io);
limit = new DoLimit(provider, limitValue, tip, dicLimitTips);
limit = new DoLimit(provider, limitValue, tip, dicLimitTips, ignoreReverse);
}
else if (limitNode.HasAttribute("ai"))
{
var limitName = limitNode.GetAttribute("ai");
var io = GetIoByIoType(IOType.AI, limitName);
var provider = new AiValueProvider((AIAccessor)io);
limit = new AiLimit(provider, limitValue, tip, dicLimitTips);
limit = new AiLimit(provider, limitValue, tip, dicLimitTips, ignoreReverse);
}
else if (limitNode.HasAttribute("ao"))
{
var limitName = limitNode.GetAttribute("ao");
var io = GetIoByIoType(IOType.AO, limitName);
var provider = new AoValueProvider((AOAccessor)io);
limit = new AoLimit(provider, limitValue, tip, dicLimitTips);
limit = new AoLimit(provider, limitValue, tip, dicLimitTips, ignoreReverse);
}
else if (limitNode.HasAttribute("polldouble"))
{
var limitName = limitNode.GetAttribute("polldouble");
var provider = new DoubleDataPollProvider(limitName);
limit = new DoubleDataPollLimit(provider, limitValue, tip, dicLimitTips);
limit = new DoubleDataPollLimit(provider, limitValue, tip, dicLimitTips, ignoreReverse);
}
else if (limitNode.HasAttribute("pollbool"))
{
var limitName = limitNode.GetAttribute("pollbool");
var provider = new BoolDataPollProvider(limitName);
limit = new BoolDataPollLimit(provider, limitValue, tip, dicLimitTips);
limit = new BoolDataPollLimit(provider, limitValue, tip, dicLimitTips, ignoreReverse);
}
else
{

View File

@ -12,8 +12,8 @@ internal class AiLimit : InterlockLimitBase<AiValueProvider, double>
#region Constructors
public AiLimit(AiValueProvider dataProvider, string value, string tip,
Dictionary<string, string> cultureTip)
: base(dataProvider, value, tip, cultureTip)
Dictionary<string, string> cultureTip,bool ignoreReverse)
: base(dataProvider, value, tip, cultureTip, ignoreReverse)
{
LimitRange = new InterlockLimitRangeDouble(value);
}

View File

@ -11,8 +11,8 @@ internal class AoLimit : InterlockLimitBase<AoValueProvider, double>
{
#region Constructors
public AoLimit(AoValueProvider dataProvider, string value, string tip, Dictionary<string, string> cultureTip)
: base(dataProvider, value, tip, cultureTip)
public AoLimit(AoValueProvider dataProvider, string value, string tip, Dictionary<string, string> cultureTip, bool ignoreReverse)
: base(dataProvider, value, tip, cultureTip, ignoreReverse)
{
LimitRange = new InterlockLimitRangeDouble(value);
}

View File

@ -10,7 +10,7 @@ public class BoolDataPollLimit : InterlockLimitBase<BoolDataPollProvider, bool>
#region Constructors
public BoolDataPollLimit(IInterlockLimitDataProvider dataProvider, string value, string tip,
Dictionary<string, string> cultureTip) : base(dataProvider, value, tip, cultureTip)
Dictionary<string, string> cultureTip,bool ignoreReverse) : base(dataProvider, value, tip, cultureTip, ignoreReverse)
{
if (bool.TryParse(value, out var limitValue))
LimitValue = limitValue;

View File

@ -17,8 +17,8 @@ internal class DiLimit : InterlockLimitBase<DiValueProvider, bool>
public override string DaemonReason =>
$"{DataProvider.Name} = [{(LimitValue ? "ON" : "OFF")}]{(string.IsNullOrEmpty(Tip) ? "" : $",{Tip}")}";
public DiLimit(DiValueProvider dataProvider, string value, string tip, Dictionary<string, string> cultureTip)
: base(dataProvider, value, tip, cultureTip)
public DiLimit(DiValueProvider dataProvider, string value, string tip, Dictionary<string, string> cultureTip,bool ignoreReverse)
: base(dataProvider, value, tip, cultureTip,ignoreReverse)
{
if (bool.TryParse(value, out var limitValue))
LimitValue = limitValue;

View File

@ -17,8 +17,8 @@ internal class DoLimit : InterlockLimitBase<DoValueProvider, bool>
public override string DaemonReason =>
$"{DataProvider.Name} = [{(LimitValue ? "ON" : "OFF")}]{(string.IsNullOrEmpty(Tip) ? "" : $",{Tip}")}";
public DoLimit(DoValueProvider dataProvider, string value, string tip, Dictionary<string, string> cultureTip)
: base(dataProvider, value, tip, cultureTip)
public DoLimit(DoValueProvider dataProvider, string value, string tip, Dictionary<string, string> cultureTip, bool ignoreReverse)
: base(dataProvider, value, tip, cultureTip, ignoreReverse)
{
if (bool.TryParse(value, out var limitValue))
LimitValue = limitValue;

View File

@ -9,7 +9,7 @@ public class DoubleDataPollLimit : InterlockLimitBase<DoubleDataPollProvider, do
#region Constructors
public DoubleDataPollLimit(IInterlockLimitDataProvider dataProvider, string value, string tip,
Dictionary<string, string> cultureTip) : base(dataProvider, value, tip, cultureTip)
Dictionary<string, string> cultureTip,bool ignoreReverse) : base(dataProvider, value, tip, cultureTip, ignoreReverse)
{
LimitRange = new InterlockLimitRangeDouble(value);
}

View File

@ -16,20 +16,21 @@ public abstract class InterlockLimitBase<TAccessor, TValue> : IInterlockLimit
private Dictionary<string, string> _cultureTip;
private readonly R_TRIG _trigger;
#endregion
#endregion
#region Constructor
#region Constructor
/// <summary>
/// 互锁限制条件的构造函数。
/// </summary>
/// <param name="dataProvider">数据供应器对象实例</param>
/// <param name="value">当前限制条件中的IO状态。</param>
/// <param name="tip">默认语言提示信息。</param>
/// <param name="cultureTip">多国语言提示信息。</param>
/// <exception cref="InvalidIoNameException">IO名称错误前缀不是“DI_”、”DO_“、”AI_“或"AO_".</exception>
protected InterlockLimitBase(IInterlockLimitDataProvider dataProvider, string value, string tip,
Dictionary<string, string> cultureTip)
/// <summary>
/// 互锁限制条件的构造函数。
/// </summary>
/// <param name="dataProvider">数据供应器对象实例</param>
/// <param name="value">当前限制条件中的IO状态。</param>
/// <param name="tip">默认语言提示信息。</param>
/// <param name="cultureTip">多国语言提示信息。</param>
/// <param name="ignoreReverse">是否触发Action反转</param>
/// <exception cref="InvalidIoNameException">IO名称错误前缀不是“DI_”、”DO_“、”AI_“或"AO_".</exception>
protected InterlockLimitBase(IInterlockLimitDataProvider dataProvider, string value, string tip,
Dictionary<string, string> cultureTip,bool ignoreReverse = false)
{
Debug.Assert(dataProvider != null, "The data provider can not be null.");
_trigger = new R_TRIG();
@ -37,6 +38,7 @@ public abstract class InterlockLimitBase<TAccessor, TValue> : IInterlockLimit
Tip = tip;
_cultureTip = cultureTip;
UniqueId = $"{dataProvider.Name}.{value}";
IgnoreReverse = ignoreReverse;
}
#endregion
@ -93,11 +95,16 @@ public abstract class InterlockLimitBase<TAccessor, TValue> : IInterlockLimit
/// </summary>
public string Tip { get; }
#endregion
/// <summary>
/// 返回该Limit是否对Action进行反转
/// </summary>
public bool IgnoreReverse { get; }
#region Methods
#endregion
/*
#region Methods
/*
/// <summary>
/// 判断两个互锁限制条件是否相等。
/// </summary>
@ -112,14 +119,14 @@ public abstract class InterlockLimitBase<TAccessor, TValue> : IInterlockLimit
return Name == li.Name && li.LimitValue == LimitValue;
}*/
/// <summary>
/// 返回互锁限制监测的信号当前值和期望值不相等的条件是否触发。
/// <remarks>
/// 捕获当前值和期望值不相等信号的上升沿当上升沿到达时触发输出Q。
/// </remarks>
/// </summary>
/// <returns></returns>
public bool IsTriggered()
/// <summary>
/// 返回互锁限制监测的信号当前值和期望值不相等的条件是否触发。
/// <remarks>
/// 捕获当前值和期望值不相等信号的上升沿当上升沿到达时触发输出Q。
/// </remarks>
/// </summary>
/// <returns></returns>
public bool IsTriggered()
{
_trigger.CLK = !CheckInRange();
return _trigger.Q;