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; namespace MECF.Framework.Common.Device.Bases; /// /// 信号灯塔元件闪烁模式。 /// [Serializable] [DataContract] public class STBlinkPattern : IComparable, ICloneable { #region Variables /// /// 以-或.配置闪烁模式的字串正则表达式。 /// public const string REG_PATT_BLINK_PATTERN = @"^([-\.])+$"; /// /// 模式字符串中每个字符对应的延时时长,单位毫秒。 /// 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 /// /// 构造信号灯元件闪烁模式。 /// 如果未指定闪烁模式,则默认开一秒,关一秒,无限循环。 /// public STBlinkPattern() { TotalCycles = 0; Pattern = PATTERN_SLOW; } /// /// 创建信号灯塔元件闪烁模式对象的实例。 /// /// /// /// 闪烁模式。 /// 请参考属性以或许模式的设置方法。 /// /// 当前工作模式优先级。 /// 总循环次数,0或负值表示无限循环。 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; } /// /// 创建信号灯塔元件闪烁模式对象的实例。 /// /// 当前工作模式优先级。 /// 总循环次数,0或负值表示无限循环。 /// /// PLC控制模式下的闪烁频率。 /// /// /// 如果PLC不支持设置闪烁频率,则回落到此模式。 /// 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 /// /// 返回是否为PLC控制模式。 ///
/// PLC模式指闪烁效果有PLC控制,以提供更精确的控制效果。 ///
public bool IsPlcMode { get; } /// /// 设置或返回总循环次数。 /// [DataMember] public int TotalCycles { get; set; } /// /// 设置或返回闪烁模式。 /// /// 闪烁模式以字符串形式表达,表达式中仅允许包含字符’-‘(英文减号)和’.‘(英文句号)。 /// 其中-表示开100ms,.表示关100ms。 ///
/// 通过'-'和‘.‘的组合,可描述不同的闪烁模式。 ///
///
[DataMember] public string Pattern { get; set; } /// /// 闪烁频率。 /// public float FrequencyHz { get; set; } /// /// 当前工作模式的优先级。 /// public int Priority { get; set; } #endregion #region Static Methods /// /// 解析闪烁模式字串,生成闪烁数据供M产生闪烁效果。 /// /// /// 闪烁效果数据。 /// 解析失败原因。 /// /// True: 解析成功 /// False: 解析失败 /// public static bool GetBlinkData(STBlinkPattern pattern, out List blinkData, out string reason) { // var regex = new Regex(@"(([-\.])(\2*))"); reason = ""; blinkData = new List(); // 校验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; } /// /// /// /// public override string ToString() { return $"IsPlcMode={IsPlcMode}, Freq={FrequencyHz}Hz, Pattern={Pattern}"; } /// public object Clone() { return MemberwiseClone(); } /// /// 对比当前STBlinkPattern是否和指定的STBlinkPattern相同。 /// /// /// /// 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; } /// /// 获取预设的快速闪烁模式。 /// /// /// 开200ms,关200ms,无限循环。 /// /// public static STBlinkPattern GetDefaultPattern() { return new STBlinkPattern(PATTERN_SLOW, (int)TowerLightStatus.Customized); } /// /// 获取预设的工艺完成闪烁模式。 /// /// /// 以开200ms、关200ms方式连续闪烁3次,然后关1s,循环5次。 /// /// public static STBlinkPattern GetJobDonePattern() { return new STBlinkPattern(PATTERN_JOB_DONE, priority:-1); } #endregion }