ProcessStep.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Threading;
  5. namespace SKMC.Api.Process.Model
  6. {
  7. /// <summary>
  8. /// 流程步骤
  9. /// </summary>
  10. public class ProcessStep : Activity
  11. {
  12. /// <summary>
  13. /// 是否开启高速触发模式, 高速模式下会直接读取一次AlarmDiCnds、AlarmAxisCnds相关的数值, 而非高速模式下将从MotionCache读取
  14. /// </summary>
  15. public bool TriggerFastMode { get; set; } = false;
  16. public List<DioCnd> AlarmDiCnds { get; set; } = new List<DioCnd>();
  17. public List<AxisCnd> AlarmAxisCnds { get; set; } = new List<AxisCnd>();
  18. // 跳过条件判断(一次)
  19. public bool SkipCndOnce { get; set; }
  20. /// <summary>
  21. /// 是否初始步骤
  22. /// </summary>
  23. public bool First { get; set; }
  24. /// <summary>
  25. /// 是否自动模式
  26. /// 自动模式下完成Actions后会自动提交下一个流程步骤(按注册顺序)
  27. /// 默认为自动模式
  28. /// 可取消自动模式, 在Actions最后调用ProcessStation的PostManual提交指定的流程步骤
  29. /// </summary>
  30. public bool AutoMode { get; set; } = true;
  31. /// <summary>
  32. /// 满足该条件函数将执行Action动作
  33. /// </summary>
  34. public Func<bool> ActionCnd { get; set; }
  35. /// <summary>
  36. /// 项目实现的动作链
  37. /// 通过ActionCnd判断后回调执行
  38. /// </summary>
  39. public Action Actions { get; set; }
  40. /// <summary>
  41. /// 未通过ActionCnd判断的超时时间, 单位ms, 默认-1表示不启用
  42. /// </summary>
  43. [Obsolete("此属性已暂时废弃")]
  44. public int Timeout { get; set; } = -1;
  45. /// <summary>
  46. /// 超过Timeout后回调执行
  47. /// </summary>
  48. [Obsolete("此属性已暂时废弃")]
  49. public Action Defaults { get; set; }
  50. /// <summary>
  51. /// 与ActionCnd同时判断, 如果满足AlarmCnd将执行Alarms
  52. /// </summary>
  53. public Func<bool> AlarmCnd { get; set; }
  54. /// <summary>
  55. /// 满足AlarmCnd后执行的动作
  56. /// </summary>
  57. public Action Alarms { get; set; }
  58. public string StepCode { get; set; }
  59. /// <summary>
  60. /// 测试模式下绕过ActionCnd, 通过该延时触发Actions
  61. /// </summary>
  62. public int TestDelay { get; set; }
  63. /// <summary>
  64. /// 是否可用
  65. /// </summary>
  66. public bool IsEnabled { get; set; } = true;
  67. /// <summary>
  68. /// 是否挂起
  69. /// </summary>
  70. public bool IsSuspend { get; set; }
  71. /// <summary>
  72. /// 是否停止
  73. /// </summary>
  74. public bool IsStoped { get; set; }
  75. /// <summary>
  76. /// 顺序号
  77. /// </summary>
  78. public int Seq { get; set; }
  79. /// <summary>
  80. /// 开始时间戳
  81. /// </summary>
  82. public long StartTicks { get; set; }
  83. /// <summary>
  84. /// 判断次数 (ActionCnd未通过后+1)
  85. /// </summary>
  86. public int CheckCount { get; set; }
  87. public ProcessStep()
  88. {
  89. }
  90. public ProcessStep(ProcessStation processStation) : this()
  91. {
  92. ProcessStation = processStation;
  93. }
  94. /// <summary>
  95. /// 获取流程站点的状态
  96. /// </summary>
  97. /// <param name="matType">状态类型, 可以是物料也可以是站点</param>
  98. /// <param name="stationId">流程站点的Id, 如果是本站则为-1</param>
  99. /// <param name="fromStorage">是否从持久化获取, 如果为true并且从持久化获取成功, 将覆盖掉内存中已有的数据</param>
  100. /// <returns></returns>
  101. public int GetStationStatus(int matType, int stationId = -1, bool fromStorage = false) =>
  102. ProcessStation.GetStationStatus(matType, stationId, fromStorage);
  103. /// <summary>
  104. /// 判断流程站点的状态是否在给定的状态值内
  105. /// 只要满足其中一个状态值返回true, 全部不满足返回false
  106. /// </summary>
  107. /// <param name="matType">状态类型, 可以是物料也可以是站点</param>
  108. /// <param name="stationId">流程站点的Id, 如果是本站则为-1</param>
  109. /// <param name="statusVals">需要比较的状态值集合</param>
  110. /// <returns></returns>
  111. public bool CheckStationStatus(int matType, int stationId, int[] statusVals) =>
  112. ProcessStation.CheckStationStatus(matType, stationId, statusVals);
  113. /// <summary>
  114. /// 设置流程站点的状态
  115. /// </summary>
  116. /// <param name="matType">状态类型, 可以是物料也可以是站点</param>
  117. /// <param name="status">状态值</param>
  118. /// <param name="stationId">站点Id, -1表示本站</param>
  119. /// <param name="toStorage">是否同步持久化保存, 如果为true并且持久化中已有相同matType将会覆盖</param>
  120. public void SetStationStatus(int matType, int status, int stationId = -1, bool toStorage = false) =>
  121. ProcessStation.SetStationStatus(matType, status, stationId, toStorage);
  122. /// <summary>
  123. /// 删除流程站点的状态
  124. /// </summary>
  125. /// <param name="matType"></param>
  126. /// <param name="stationId"></param>
  127. public void RemoveStationStatus(int matType, int stationId = -1) =>
  128. ProcessStation.RemoveStationStatus(matType, stationId);
  129. /// <summary>
  130. /// 清除流程站点的所有状态
  131. /// </summary>
  132. /// <param name="stationId"></param>
  133. public void ClearStationStatus(int stationId = -1) => ProcessStation.ClearStationStatus(stationId);
  134. /// <summary>
  135. /// 在ProcessStationManager中更新当前运行的Step
  136. /// </summary>
  137. public void UpdateRunningStep()
  138. {
  139. ProcessStation.ProcessStationManager.runningSteps[ProcessStation.Id] = this;
  140. }
  141. /// <summary>
  142. /// 等待条件满足
  143. /// </summary>
  144. /// <param name="cnd">满足的条件</param>
  145. /// <param name="onTimeout">超时后动作</param>
  146. /// <param name="timeout">超时时间, 默认60秒</param>
  147. /// <param name="period">条件判断间隔</param>
  148. public void WaitingFor(Func<bool> cnd, Action onTimeout = null, int timeout = 60000, int period = 100)
  149. {
  150. int loops = timeout / period + 1;
  151. for (int i = 0; i < loops; i++)
  152. {
  153. if (cnd.Invoke()) return;
  154. Thread.Sleep(period);
  155. }
  156. if (onTimeout != null) onTimeout.Invoke();
  157. }
  158. /// <summary>
  159. /// 回复Step属性状态
  160. /// </summary>
  161. public void Reset()
  162. {
  163. IsStoped = false;
  164. IsSuspend = false;
  165. InAction = false;
  166. }
  167. /// <summary>
  168. /// 每次执行动作前的准备
  169. /// </summary>
  170. public Action OnPrepare { get; set; }
  171. /// <summary>
  172. /// 回调方法
  173. /// </summary>
  174. public void DoActions()
  175. {
  176. double waitTime = 0;
  177. if (StartTicks > 0)
  178. {
  179. waitTime = (DateTime.Now.Ticks - StartTicks) / 10000d;
  180. }
  181. log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]动作开始... 等待用时: {waitTime}");
  182. Stopwatch stopwatch = Stopwatch.StartNew();
  183. // 回复Di初始值
  184. foreach (var diCnd in TriggerDiCnds)
  185. {
  186. diCnd.Reset();
  187. }
  188. InAction = true;
  189. Actions?.Invoke();
  190. InAction = false;
  191. stopwatch.Stop();
  192. log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]动作完成, 运行用时: {stopwatch.Elapsed.TotalMilliseconds}");
  193. }
  194. public void DoDefaults()
  195. {
  196. log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]等待超时...");
  197. InAction = true;
  198. //Defaults?.Invoke();
  199. InAction = false;
  200. log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]超时处理完成");
  201. }
  202. public void DoAlarms()
  203. {
  204. log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]告警开始...");
  205. foreach (var diCnd in TriggerDiCnds)
  206. {
  207. diCnd.Reset();
  208. }
  209. InAction = true;
  210. Alarms?.Invoke();
  211. InAction = false;
  212. log.Debug($"任务[{ProcessStation.Id}-{Id}:{Name}]告警处理完成");
  213. }
  214. public void DoStop()
  215. {
  216. IsStoped = true;
  217. if (OnStop != null) OnStop?.Invoke();
  218. InAction = false;
  219. }
  220. /// <summary>
  221. /// 停止
  222. /// </summary>
  223. public Action OnStop { get; set; }
  224. public void DoEmgStop()
  225. {
  226. IsStoped = true;
  227. OnEmgStop?.Invoke();
  228. }
  229. /// <summary>
  230. /// 急停
  231. /// </summary>
  232. public Action OnEmgStop { get; set; }
  233. public void DoPause()
  234. {
  235. IsSuspend = true;
  236. OnPause?.Invoke();
  237. }
  238. public Action OnPause { get; set; }
  239. public void DoResume()
  240. {
  241. IsSuspend = false;
  242. StartTicks = DateTime.Now.Ticks;
  243. OnResume?.Invoke();
  244. }
  245. public Action OnResume { get; set; }
  246. public override bool Equals(object obj)
  247. {
  248. return obj is ProcessStep step && Id == step.Id;
  249. }
  250. public override int GetHashCode()
  251. {
  252. return 2108858624 + Id.GetHashCode();
  253. }
  254. }
  255. }