RoutineRunner.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. using Aitex.Core.RT.Event;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.Routine;
  4. using MECF.Framework.Common.Equipment;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace MECF.Framework.Common.Routine
  12. {
  13. public class RoutineRunner
  14. {
  15. public RState Status => _runnerState;
  16. private bool IsSubStepRunning(Enum id) => _runnerState == RState.Running && _subState == RState.Running && (_curStep != null && _curStep.GetHashCode() == id.GetHashCode());
  17. private bool bAllowSubStepStart(Enum id) => _runnerState == RState.Running && _subState == RState.End && !_steps.Contains(id) && _isLoopMode == false;
  18. private bool bAllowLoopSubStepStart(Enum id) => _runnerState == RState.Running && _subState == RState.End && !_steps.Contains(id) && _isLoopMode;
  19. public int LoopCounter => _loopCounter;
  20. public long StepElapsedMS => _subStepTimer.ElapsedMilliseconds;
  21. private RState _subState = RState.Init;
  22. private Stack<Enum> _steps = new Stack<Enum>();
  23. private Stack<Enum> _loopSteps = new Stack<Enum>();
  24. enum InvalidStep { Invalid = 0x7FFFFFFF, };
  25. private Enum _curStep = InvalidStep.Invalid;
  26. private RState _runnerState = RState.Init;
  27. private string _name;
  28. private string _loopName;
  29. private string _module;
  30. // 缺省最大超时 10 分钟, delay 5 秒
  31. private const int _defaultTimeout = 600000;
  32. private const int _defaultDelay = 200;
  33. private const int _defaultDelay_5s = 5000;
  34. Stopwatch _subStepTimer = new Stopwatch();
  35. private bool _isLoopMode = false;
  36. private int _loopCounterSP = 0;
  37. private int _loopCounter = 0;
  38. static private int _RunnerToken = 0;
  39. public RoutineRunner()
  40. {
  41. _runnerState = RState.Init;
  42. }
  43. public void Reset()
  44. {
  45. _runnerState = RState.Init;
  46. _subState = RState.Init;
  47. _isLoopMode = false;
  48. _steps.Clear();
  49. _loopSteps.Clear();
  50. _subStepTimer.Reset();
  51. }
  52. public RState Start(string module, string name)
  53. {
  54. Reset();
  55. _module = module;
  56. _name = $"{name} (Token:{_RunnerToken++})";
  57. _runnerState = RState.Running;
  58. _subState = RState.End;
  59. Notify("开始");
  60. return _runnerState;
  61. }
  62. public void Stop(string reason)
  63. {
  64. Alarm(reason);
  65. _runnerState = _subState = RState.Failed;
  66. }
  67. public RoutineRunner Run(Enum id, Func<bool> action, Func<bool> condition, int timeout = _defaultTimeout)
  68. {
  69. if (bAllowSubStepStart(id))
  70. {
  71. startNewStep(id, action);
  72. }
  73. else if (IsSubStepRunning(id))
  74. {
  75. if (condition())
  76. {
  77. _subState = RState.End;
  78. }
  79. else if (_subStepTimer.ElapsedMilliseconds >= timeout)
  80. {
  81. Alarm($"Step:{id} 超时");
  82. _runnerState = _subState = RState.Timeout;
  83. _subStepTimer.Reset();
  84. }
  85. }
  86. return this;
  87. }
  88. public RoutineRunner RunIf(Enum id, bool bRun, Func<bool> action, Func<bool> condition, int timeout = _defaultTimeout)
  89. {
  90. if (bRun)
  91. {
  92. return Run(id, action, condition, timeout);
  93. }
  94. return this;
  95. }
  96. public RoutineRunner Run(Enum id, Func<bool> action, int delayMS = _defaultDelay)
  97. {
  98. if (bAllowSubStepStart(id))
  99. {
  100. startNewStep(id, action);
  101. }
  102. else if (IsSubStepRunning(id))
  103. {
  104. if (_subStepTimer.ElapsedMilliseconds > delayMS)
  105. {
  106. _subState = RState.End;
  107. }
  108. }
  109. return this;
  110. }
  111. public RoutineRunner RunIf(Enum id, bool bRun, Func<bool> action, int delayMS = _defaultDelay)
  112. {
  113. if (bRun)
  114. {
  115. return Run(id, action, delayMS);
  116. }
  117. return this;
  118. }
  119. public RoutineRunner End(Enum id, Func<bool> action, Func<bool> condition, int timeout = _defaultTimeout)
  120. {
  121. if (bAllowSubStepStart(id))
  122. {
  123. startNewStep(id, action);
  124. }
  125. else if (IsSubStepRunning(id))
  126. {
  127. if (condition())
  128. {
  129. Notify($"结束");
  130. _runnerState = RState.End;
  131. _subState = RState.End;
  132. }
  133. else
  134. {
  135. if (_subStepTimer.ElapsedMilliseconds > timeout)
  136. {
  137. Alarm($"Step:{id} 超时");
  138. _runnerState = RState.Failed;
  139. _subState = RState.Timeout;
  140. }
  141. }
  142. }
  143. return this;
  144. }
  145. public RoutineRunner End(Enum id, Func<bool> action, int delayMS = _defaultDelay)
  146. {
  147. if (bAllowSubStepStart(id))
  148. {
  149. startNewStep(id, action);
  150. }
  151. else if (IsSubStepRunning(id))
  152. {
  153. if (_subStepTimer.ElapsedMilliseconds > delayMS)
  154. {
  155. Notify($"结束");
  156. _runnerState = RState.End;
  157. _subState = RState.End;
  158. }
  159. }
  160. return this;
  161. }
  162. public RoutineRunner Delay(Enum id, int delayMS = _defaultDelay_5s)
  163. {
  164. return Run(id, () => { return true; }, delayMS);
  165. }
  166. public RoutineRunner Wait(Enum id, Func<bool> condition, int timeout = _defaultTimeout)
  167. {
  168. return Run(id, () => { return true; }, condition, timeout);
  169. }
  170. public RoutineRunner LoopStart(Enum id, string name, int cycleCount, Func<bool> action, Func<bool> condition, int timeout = _defaultTimeout)
  171. {
  172. if (bAllowSubStepStart(id))
  173. {
  174. _loopName = name;
  175. _loopCounterSP = cycleCount;
  176. _loopCounter = 0;
  177. _isLoopMode = true;
  178. startNewLoopStep(id, action);
  179. }
  180. else if (bAllowLoopSubStepStart(id))
  181. {
  182. startNewLoopStep(id, action);
  183. }
  184. else if (IsSubStepRunning(id))
  185. {
  186. if (condition())
  187. {
  188. _subState = RState.End;
  189. }
  190. else if (_subStepTimer.ElapsedMilliseconds >= timeout)
  191. {
  192. Alarm($"Step:{id} 超时");
  193. _runnerState = _subState = RState.Timeout;
  194. _subStepTimer.Reset();
  195. }
  196. }
  197. return this;
  198. }
  199. public RoutineRunner LoopStart(Enum id, string name, int cycleCount, Func<bool> action, int delayMS = _defaultDelay)
  200. {
  201. if (bAllowSubStepStart(id))
  202. {
  203. _loopName = name;
  204. _loopCounterSP = cycleCount;
  205. _loopCounter = 0;
  206. _isLoopMode = true;
  207. startNewLoopStep(id, action);
  208. }
  209. else if (bAllowLoopSubStepStart(id))
  210. {
  211. startNewLoopStep(id, action);
  212. }
  213. else if (IsSubStepRunning(id))
  214. {
  215. if (_subStepTimer.ElapsedMilliseconds > delayMS)
  216. {
  217. _subState = RState.End;
  218. }
  219. }
  220. return this;
  221. }
  222. public RoutineRunner LoopRun(Enum id, Func<bool> action, Func<bool> condition, int timeout = _defaultTimeout)
  223. {
  224. if (bAllowLoopSubStepStart(id))
  225. {
  226. startNewLoopStep(id, action);
  227. }
  228. else if (IsSubStepRunning(id))
  229. {
  230. if (condition())
  231. {
  232. _subState = RState.End;
  233. }
  234. else if (_subStepTimer.ElapsedMilliseconds >= timeout)
  235. {
  236. Alarm($"Step:{id} 超时");
  237. _runnerState = _subState = RState.Timeout;
  238. _subStepTimer.Reset();
  239. }
  240. }
  241. return this;
  242. }
  243. public RoutineRunner LoopRunIf(Enum id, bool bRun, Func<bool> action, Func<bool> condition, int timeout = _defaultTimeout)
  244. {
  245. if (bRun)
  246. {
  247. return LoopRun(id, action, condition, timeout);
  248. }
  249. return this;
  250. }
  251. public RoutineRunner LoopRun(Enum id, Func<bool> action, int delayMS = _defaultDelay)
  252. {
  253. if (bAllowLoopSubStepStart(id))
  254. {
  255. startNewLoopStep(id, action);
  256. }
  257. else if (IsSubStepRunning(id))
  258. {
  259. if (_subStepTimer.ElapsedMilliseconds > delayMS)
  260. {
  261. _subState = RState.End;
  262. }
  263. }
  264. return this;
  265. }
  266. public RoutineRunner LoopRunIf(Enum id, bool bRun, Func<bool> action, int delayMS = _defaultDelay)
  267. {
  268. if (bRun)
  269. {
  270. return LoopRun(id, action, delayMS);
  271. }
  272. return this;
  273. }
  274. public RoutineRunner LoopEnd(Enum id, Func<bool> action, Func<bool> condition, int timeout = _defaultTimeout)
  275. {
  276. if (bAllowLoopSubStepStart(id))
  277. {
  278. startNewLoopStep(id, action);
  279. }
  280. else if (IsSubStepRunning(id))
  281. {
  282. if (condition())
  283. {
  284. Notify($"{_loopCounter + 1}th [{_loopName}] Loop End");
  285. _subState = RState.End;
  286. _loopCounter++;
  287. if (_loopCounter >= _loopCounterSP)
  288. {
  289. foreach (var lid in _loopSteps)
  290. _steps.Push(lid);
  291. _loopSteps.Clear();
  292. _isLoopMode = false;
  293. }
  294. }
  295. else if (_subStepTimer.ElapsedMilliseconds >= timeout)
  296. {
  297. Alarm($"Step:{id} 超时");
  298. _runnerState = _subState = RState.Timeout;
  299. _subStepTimer.Reset();
  300. }
  301. }
  302. return this;
  303. }
  304. public RoutineRunner LoopEnd(Enum id, Func<bool> action, int delayMS = _defaultDelay)
  305. {
  306. if (bAllowLoopSubStepStart(id))
  307. {
  308. startNewLoopStep(id, action);
  309. }
  310. else if (IsSubStepRunning(id))
  311. {
  312. if (_subStepTimer.ElapsedMilliseconds > delayMS)
  313. {
  314. Notify($"{_loopCounter + 1}th [{_loopName}] Loop End");
  315. _subState = RState.End;
  316. _loopCounter++;
  317. if (_loopCounter >= _loopCounterSP)
  318. {
  319. foreach (var lid in _loopSteps)
  320. _steps.Push(lid);
  321. _loopSteps.Clear();
  322. _isLoopMode = false;
  323. }
  324. }
  325. }
  326. return this;
  327. }
  328. public RoutineRunner LoopDelay(Enum id, int delayMS)
  329. {
  330. return LoopRun(id, () => { return true; }, delayMS);
  331. }
  332. public RoutineRunner LoopWait(Enum id, Func<bool> condition, int timeout = _defaultTimeout)
  333. {
  334. return LoopRun(id, () => { return true; }, condition, timeout);
  335. }
  336. private void startNewStep(Enum id, Func<bool> action)
  337. {
  338. if (action())
  339. {
  340. Notify($"Step: {id} start ---");
  341. _steps.Push(id);
  342. _curStep = id;
  343. _subState = RState.Running;
  344. _subStepTimer.Restart();
  345. }
  346. else
  347. {
  348. Alarm($"Step: {id} failed ");
  349. _runnerState = RState.Failed;
  350. }
  351. }
  352. private void startNewLoopStep(Enum id, Func<bool> action)
  353. {
  354. if (action())
  355. {
  356. Notify($"{_loopCounter + 1}th [{_loopName}] Loop Step: {id} start ---");
  357. if (!_loopSteps.Contains(id))
  358. _loopSteps.Push(id);
  359. _curStep = id;
  360. _subState = RState.Running;
  361. _subStepTimer.Restart();
  362. }
  363. else
  364. {
  365. Alarm($"{_loopCounter + 1}th [{_loopName}] Loop Step: {id} failed");
  366. _runnerState = RState.Failed;
  367. }
  368. }
  369. protected void Notify(string message)
  370. {
  371. EV.PostInfoLog(_module, $"{_module} {_name}, {message}");
  372. }
  373. protected void Alarm(string failReason)
  374. {
  375. EV.PostAlarmLog(_module, $"{_module} {_name} failed, {failReason}");
  376. }
  377. }
  378. static public class HOFs
  379. {
  380. public static Func<R> Apply<T1, R>(this Func<T1, R> func, T1 t1)
  381. => () => func(t1);
  382. public static Func<R> Apply<T1, T2, R>(this Func<T1, T2, R> func, T1 t1, T2 t2)
  383. => () => func(t1, t2);
  384. public static Func<R> Apply<T1, T2, T3, R>(this Func<T1, T2, T3, R> func, T1 t1, T2 t2, T3 t3)
  385. => () => func(t1, t2, t3);
  386. public static Func<bool> WrapAction(this Action action)
  387. => () => { action(); return true; };
  388. public static Func<bool> WrapAction<T1>(this Action<T1> action, T1 t1)
  389. => () => { action(t1); return true; };
  390. public static Func<bool> WrapAction<T1, T2>(this Action<T1, T2> action, T1 t1, T2 t2)
  391. => () => { action(t1, t2); return true; };
  392. public static Func<bool> WrapAction<T1, T2, T3>(this Action<T1, T2, T3> action, T1 t1, T2 t2, T3 t3)
  393. => () => { action(t1, t2, t3); return true; };
  394. }
  395. }