Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/MECF/Framework/Common/Device/Bases/STBlinkPattern.cs

258 lines
7.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Aitex.Core.RT.Log;
using BlinkDataType = System.Collections.Generic.KeyValuePair<MECF.Framework.Common.Device.Bases.TowerLightStatus, uint>;
namespace MECF.Framework.Common.Device.Bases;
/// <summary>
/// 信号灯塔元件闪烁模式。
/// </summary>
[Serializable]
[DataContract]
public class STBlinkPattern : IComparable, ICloneable
{
#region Variables
/// <summary>
/// 以-或.配置闪烁模式的字串正则表达式。
/// </summary>
public const string REG_PATT_BLINK_PATTERN = @"^([-\.])+$";
/// <summary>
/// 模式字符串中每个字符对应的延时时长,单位毫秒。
/// </summary>
private const uint DELAY_MS_PER_CHAR = 100;
private const string PATTERN_FAST = "-----..";
private const string PATTERN_SLOW = "-----.......";
private const string PATTERN_JOB_DONE = "-----.......";
#endregion
#region Constructors
/// <summary>
/// 构造信号灯元件闪烁模式。
/// <para>如果未指定闪烁模式,则默认开一秒,关一秒,无限循环。</para>
/// </summary>
public STBlinkPattern()
{
TotalCycles = 0;
Pattern = PATTERN_SLOW;
}
/// <summary>
/// 创建信号灯塔元件闪烁模式对象的实例。
/// </summary>
/// /// <param name="pattern">
/// 闪烁模式。
/// 请参考属性<see cref="Pattern"/>以或许模式的设置方法。
/// </param>
/// <param name="priority">当前工作模式优先级。</param>
/// <param name="cycle">总循环次数0或负值表示无限循环。</param>
public STBlinkPattern(string pattern, int priority, int cycle = int.MaxValue)
{
Debug.Assert(!string.IsNullOrEmpty(pattern), "pattern can not be null");
TotalCycles = cycle;
Pattern = pattern;
Priority = priority;
IsPlcMode = false;
}
/// <summary>
/// 创建信号灯塔元件闪烁模式对象的实例。
/// </summary>
/// <param name="priority">当前工作模式优先级。</param>
/// <param name="cycle">总循环次数0或负值表示无限循环。</param>
/// <param name="frequencyHz">
/// PLC控制模式下的闪烁频率。
/// </param>
/// <param name="fallbackPattern">
/// 如果PLC不支持设置闪烁频率则回落到此模式。
/// </param>
public STBlinkPattern(float frequencyHz, int priority, int cycle = int.MaxValue, string fallbackPattern = PATTERN_SLOW)
{
TotalCycles = cycle;
Pattern = fallbackPattern;
FrequencyHz = frequencyHz;
Priority = priority;
IsPlcMode = true;
}
#endregion
#region Properties
/// <summary>
/// 返回是否为PLC控制模式。
/// <br/>
/// <remarks>PLC模式指闪烁效果有PLC控制以提供更精确的控制效果。</remarks>
/// </summary>
public bool IsPlcMode { get; }
/// <summary>
/// 设置或返回总循环次数。
/// </summary>
[DataMember]
public int TotalCycles { get; set; }
/// <summary>
/// 设置或返回闪烁模式。
/// <remarks>
/// 闪烁模式以字符串形式表达,表达式中仅允许包含字符’-‘(英文减号)和’.‘(英文句号)。
/// 其中<value>-</value>表示开100ms<value>.</value>表示关100ms。
/// <br/>
/// 通过'-'和‘.‘的组合,可描述不同的闪烁模式。
/// </remarks>
/// </summary>
[DataMember]
public string Pattern { get; set; }
/// <summary>
/// 闪烁频率。
/// </summary>
public float FrequencyHz { get; set; }
/// <summary>
/// 当前工作模式的优先级。
/// </summary>
public int Priority { get; set; }
#endregion
#region Static Methods
/// <summary>
/// 解析闪烁模式字串生成闪烁数据供M<see cref="SignalTowerPartBase"/>产生闪烁效果。
/// </summary>
/// <param name="pattern"></param>
/// <param name="blinkData">闪烁效果数据。</param>
/// <param name="reason">解析失败原因。</param>
/// <returns>
/// <value>True: 解析成功</value>
/// <value>False: 解析失败</value>
/// </returns>
public static bool GetBlinkData(STBlinkPattern pattern, out List<BlinkDataType> blinkData, out string reason)
{
// var regex = new Regex(@"(([-\.])(\2*))");
reason = "";
blinkData = new List<BlinkDataType>();
// 校验Pattern字串的正则Pattern仅允许有字符-‘和’.’组成。
var regPatternFormat = new Regex(REG_PATT_BLINK_PATTERN);
// Pattern分组正则
var regGroup = new Regex(@"([\-\.])\1*");
if (!regPatternFormat.IsMatch(pattern.Pattern))
{
// 如果存在除-和.以外的字符则为非法Pattern字串。
reason = "pattern contains illegal characters";
LOG.Error(reason);
return false;
}
var matches = regGroup.Matches(pattern.Pattern);
foreach (Match match in matches)
{
if (match.Success && match.Groups.Count == 2)
{
var leadChar = match.Groups[1].Value; // 编组字符
var length = (uint)match.Length;
// 根据每组的字符判断动作。
TowerLightStatus action;
switch (leadChar)
{
case "-":
action = TowerLightStatus.On;
break;
case ".":
action = TowerLightStatus.Off;
break;
default:
LOG.Error($"Undefined character {leadChar} in pattern");
continue;
}
blinkData.Add(new(action, DELAY_MS_PER_CHAR * length));
}
}
return true;
}
/// <summary>
/// <inheritdoc cref="Object.ToString()"/>
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"IsPlcMode={IsPlcMode}, Freq={FrequencyHz}Hz, Pattern={Pattern}";
}
/// <inheritdoc />
public object Clone()
{
return MemberwiseClone();
}
/// <summary>
/// 对比当前STBlinkPattern是否和指定的STBlinkPattern相同。
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public int CompareTo(object obj)
{
if (obj is not STBlinkPattern target)
return -1;
return (target.IsPlcMode == IsPlcMode
&& target.TotalCycles == TotalCycles
&& Math.Abs(target.FrequencyHz - FrequencyHz) < 0.01
&& target.Pattern == Pattern
&& target.Priority == Priority)
? 0
: -1;
}
/// <summary>
/// 获取预设的快速闪烁模式。
/// </summary>
/// <remarks>
/// 开200ms关200ms无限循环。
/// </remarks>
/// <returns></returns>
public static STBlinkPattern GetDefaultPattern()
{
return new STBlinkPattern(PATTERN_SLOW, (int)TowerLightStatus.Customized);
}
/// <summary>
/// 获取预设的工艺完成闪烁模式。
/// </summary>
/// <remarks>
/// 以开200ms、关200ms方式连续闪烁3次然后关1s循环5次。
/// </remarks>
/// <returns></returns>
public static STBlinkPattern GetJobDonePattern()
{
return new STBlinkPattern(PATTERN_JOB_DONE, priority:-1);
}
#endregion
}