using SKMC.Api.Common.Logger;
using SKMC.Api.Motion.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
namespace SKMC.Api.Process.Model
{
///
/// 流程步骤
///
public class ProcessStep
{
protected static readonly ILogger log = LogFactory.Get();
///
/// 活动Id
///
public int Id { get; set; }
///
/// 活动名称
///
public string Name { get; set; }
///
/// 是否活动中
///
public bool InAction { get; set; }
///
/// Di触发条件集合
///
public List TriggerDiCnds { get; set; } = new List();
///
/// 电机触发条件集合
///
public List TriggerAxisCnds { get; set; } = new List();
///
///
///
public List AlarmDiCnds { get; set; } = new List();
///
///
///
public List AlarmAxisCnds { get; set; } = new List();
///
/// 流程站点
///
public ProcessStation ProcessStation { get; set; }
// 跳过条件判断(一次)
public bool SkipCndOnce { get; set; }
///
/// 是否初始步骤
///
public bool First { get; set; }
///
/// 是否自动模式
/// 自动模式下完成Actions后会自动提交下一个流程步骤(按注册顺序)
/// 默认为自动模式
/// 可取消自动模式, 在Actions最后调用ProcessStation的PostManual提交指定的流程步骤
///
public bool AutoMode { get; set; } = true;
///
/// 满足该条件函数将执行Action动作
///
public Func ActionCnd { get; set; }
///
/// 项目实现的动作链
/// 通过ActionCnd判断后回调执行
///
public Action Actions { get; set; }
///
/// 未通过ActionCnd判断的超时时间, 单位ms, 默认-1表示不启用
///
[Obsolete("此属性已暂时废弃")]
public int Timeout { get; set; } = -1;
///
/// 超过Timeout后回调执行
///
[Obsolete("此属性已暂时废弃")]
public Action Defaults { get; set; }
///
/// 与ActionCnd同时判断, 如果满足AlarmCnd将执行Alarms
///
public Func AlarmCnd { get; set; }
///
/// 满足AlarmCnd后执行的动作
///
public Action Alarms { get; set; }
public string StepCode { get; set; }
///
/// 测试模式下绕过ActionCnd, 通过该延时触发Actions
///
public int TestDelay { get; set; }
///
/// 是否可用
///
public bool IsEnabled { get; set; } = true;
///
/// 是否挂起
///
public bool IsSuspend { get; set; }
///
/// 是否停止
///
public bool IsStoped { get; set; }
///
/// 顺序号
///
public int Seq { get; set; }
///
/// 开始时间戳
///
public long StartTicks { get; set; }
///
/// 判断次数 (ActionCnd未通过后+1)
///
public int CheckCount { get; set; }
public ProcessStep()
{
}
public ProcessStep(ProcessStation processStation) : this()
{
ProcessStation = processStation;
}
///
/// 获取流程站点的状态
///
/// 状态类型, 可以是物料也可以是站点
/// 流程站点的Id, 如果是本站则为-1
/// 是否从持久化获取, 如果为true并且从持久化获取成功, 将覆盖掉内存中已有的数据
///
public int GetStationStatus(int matType, int stationId = -1, bool fromStorage = false) =>
ProcessStation.GetStationStatus(matType, stationId, fromStorage);
///
/// 判断流程站点的状态是否在给定的状态值内
/// 只要满足其中一个状态值返回true, 全部不满足返回false
///
/// 状态类型, 可以是物料也可以是站点
/// 流程站点的Id, 如果是本站则为-1
/// 需要比较的状态值集合
///
public bool CheckStationStatus(int matType, int stationId, int[] statusVals) =>
ProcessStation.CheckStationStatus(matType, stationId, statusVals);
///
/// 设置流程站点的状态
///
/// 状态类型, 可以是物料也可以是站点
/// 状态值
/// 站点Id, -1表示本站
/// 是否同步持久化保存, 如果为true并且持久化中已有相同matType将会覆盖
public void SetStationStatus(int matType, int status, int stationId = -1, bool toStorage = false) =>
ProcessStation.SetStationStatus(matType, status, stationId, toStorage);
///
/// 删除流程站点的状态
///
///
///
public void RemoveStationStatus(int matType, int stationId = -1) =>
ProcessStation.RemoveStationStatus(matType, stationId);
///
/// 清除流程站点的所有状态
///
///
public void ClearStationStatus(int stationId = -1) => ProcessStation.ClearStationStatus(stationId);
///
/// 在ProcessStationManager中更新当前运行的Step
///
public void UpdateRunningStep()
{
ProcessStation.ProcessStationManager.runningSteps[ProcessStation.Id] = this;
}
///
/// 等待条件满足
///
/// 满足的条件
/// 超时后动作
/// 超时时间, 默认60秒
/// 条件判断间隔
public void WaitingFor(Func cnd, Action onTimeout = null, int timeout = 60000, int period = 100)
{
int loops = timeout / period + 1;
for (int i = 0; i < loops; i++)
{
if (cnd.Invoke()) return;
Thread.Sleep(period);
}
if (onTimeout != null) onTimeout.Invoke();
}
///
/// 回复Step属性状态
///
public void Reset()
{
IsStoped = false;
IsSuspend = false;
InAction = false;
}
///
/// 每次执行动作前的准备
///
public Action OnPrepare { get; set; }
///
/// 回调方法
///
public void DoActions()
{
double waitTime = 0;
if (StartTicks > 0)
{
waitTime = (DateTime.Now.Ticks - StartTicks) / 10000d;
}
log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]动作开始... 等待用时: {waitTime}");
Stopwatch stopwatch = Stopwatch.StartNew();
// 回复Di初始值
foreach (var diCnd in TriggerDiCnds)
{
diCnd.Reset();
}
InAction = true;
Actions?.Invoke();
InAction = false;
stopwatch.Stop();
log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]动作完成, 运行用时: {stopwatch.Elapsed.TotalMilliseconds}");
}
public void DoDefaults()
{
log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]等待超时...");
InAction = true;
//Defaults?.Invoke();
InAction = false;
log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]超时处理完成");
}
public void DoAlarms()
{
log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]告警开始...");
foreach (var diCnd in TriggerDiCnds)
{
diCnd.Reset();
}
InAction = true;
Alarms?.Invoke();
InAction = false;
log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]告警处理完成");
}
public void DoStop()
{
IsStoped = true;
if (OnStop != null) OnStop?.Invoke();
InAction = false;
}
///
/// 停止
///
public Action OnStop { get; set; }
public void DoEmgStop()
{
IsStoped = true;
OnEmgStop?.Invoke();
}
///
/// 急停
///
public Action OnEmgStop { get; set; }
public void DoPause()
{
IsSuspend = true;
OnPause?.Invoke();
}
public Action OnPause { get; set; }
public void DoResume()
{
IsSuspend = false;
StartTicks = DateTime.Now.Ticks;
OnResume?.Invoke();
}
public Action OnResume { get; set; }
public override bool Equals(object obj)
{
return obj is ProcessStep step && Id == step.Id;
}
public override int GetHashCode()
{
return 2108858624 + Id.GetHashCode();
}
}
}