Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/MECF/Framework/Common/Fsm/ModuleFsmDevice.cs

220 lines
4.9 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.Linq;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
namespace MECF.Framework.Common.Fsm
{
/// <summary>
/// 应用于构建模组Module状态机的对象。
/// </summary>
/// <remarks>
/// 模组Module在系统中为一类控制单元对应硬件系统的控制单元。
/// <br/>
/// 通常一个模组包含一组设备Device并通过Routine提供具有原子性的各种操作。
/// 设备整机有不同的模组构成并通过调用模组下的Routine完成各个功能动作。
/// 关于Routine的细节请参考<see cref="ModuleRoutine"/>对象。
/// <br/>
/// 模组基于有限状态机FSM进行工作模组实例化时构建了状态转换表各个动作基于状态转化完成
/// 状态机模型有效的控制模组的工作状态,有助于构建健壮的、稳定的系统架构。
/// </remarks>
public class ModuleFsmDevice : FsmDevice
{
#region Variables
/// <summary>
/// 当模组发生异常时触发此事件。
/// </summary>
/// <remarks>
/// 通常情况下当该事件引发时会向状态机发送Error或Alarm消息以使状态机转换到Error或Alarm状态。
/// </remarks>
public event EventHandler<string> OnEnterError;
private readonly Queue<IRoutine> _qRoutines;
#endregion
#region Constructors
/// <summary>
/// 创建模组的对象实例。
/// </summary>
public ModuleFsmDevice()
{
_qRoutines = new Queue<IRoutine>();
}
#endregion
#region Properties
/// <summary>
/// 返回当前模组是否在系统配置中启用。
/// </summary>
public bool IsInstalled
{
get
{
if (!SC.ContainsItem("System.SetUp.Is" + base.Module + "Installed"))
{
return true;
}
return SC.GetValue<bool>("System.SetUp.Is" + base.Module + "Installed");
}
}
/// <summary>
/// 设置或返回当前模组是否上线。
/// </summary>
public bool IsOnline { get; set; }
/// <summary>
/// 返回当前设备正在执行的Routine的列队。
/// </summary>
protected Queue<IRoutine> QueueRoutine => _qRoutines;
#endregion
#region Methods
/// <summary>
/// 初始化模组。
/// </summary>
/// <returns></returns>
public override bool Initialize()
{
return base.Initialize();
}
/// <summary>
/// 使用指定的参数启动Routine。
/// </summary>
/// <param name="routine">Routine对象的实例。</param>
/// <param name="args">
/// Routine的启动参数。
/// <remarks>
/// 该参数表会传递给Routine的Start()方法。
/// </remarks>
/// </param>
/// <returns>
/// <see cref="Result"/>
/// <br/>
/// Routine的执行状态。</returns>
public Result StartRoutine(IRoutine routine, params object[] args)
{
QueueRoutine.Clear();
QueueRoutine.Enqueue(routine);
return QueueRoutine.Peek().Start(args);
}
/// <summary>
/// 启动指定的Routine。
/// </summary>
/// <param name="routine">Routine对象的实例。</param>
/// <returns>
/// <see cref="Result"/>
/// <br/>
/// Routine的执行状态。</returns>
public Result StartRoutine(IRoutine routine)
{
QueueRoutine.Clear();
QueueRoutine.Enqueue(routine);
return QueueRoutine.Peek().Start();
}
/// <summary>
/// 启动列队中的Routine。
/// </summary>
/// <remarks>
/// 需要将待执行的Routine添加到<see cref="QueueRoutine"/>队列中。
/// </remarks>
/// <returns>
/// <see cref="Result"/>
/// <br/>
/// Routine的执行状态。
/// </returns>
public Result StartRoutine()
{
if (_qRoutines.Count == 0)
{
return Result.DONE;
}
var result = Result.DONE;
var list = _qRoutines.ToList();
for (int i = 0; i < list.Count; _qRoutines.Dequeue(), i++)
{
switch (list[i].Start())
{
case Result.DONE:
continue;
case Result.FAIL:
return Result.FAIL;
}
break;
}
return Result.RUN;
}
/// <summary>
/// 周期性扫描正在执行的Routine。
/// </summary>
/// <returns>
/// <see cref="Result"/>
/// <br/>
/// Routine的执行状态。
/// </returns>
public Result MonitorRoutine()
{
if (_qRoutines.Count == 0)
{
return Result.DONE;
}
var routine = _qRoutines.Peek();
var result = routine.Monitor();
if (result == Result.DONE)
{
_qRoutines.Dequeue();
var list = _qRoutines.ToList();
for (var i = 0; i < list.Count; _qRoutines.Dequeue(), i++)
{
result = list[i].Start();
switch (result)
{
case Result.DONE:
continue;
case Result.FAIL:
return Result.FAIL;
}
break;
}
}
return result;
}
/// <summary>
/// 终止当前模组的所有正在执行的Routine。
/// </summary>
public void AbortRoutine()
{
if (_qRoutines != null)
{
_qRoutines.Peek().Abort();
_qRoutines.Clear();
}
}
/// <summary>
/// 产生模组异常事件。
/// </summary>
/// <param name="module"></param>
protected virtual void InvokeOnEnterError(string module)
{
OnEnterError?.Invoke(this, module);
}
#endregion
}
}