ModuleRoutine.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. using Aitex.Core.RT.Event;
  2. using Aitex.Core.RT.Log;
  3. using System;
  4. namespace Aitex.Core.RT.Routine
  5. {
  6. public class ModuleRoutine : SeqenecRoutine
  7. {
  8. public string Module { get; set; }
  9. public string Name { get; set; }
  10. public string StepName
  11. {
  12. get
  13. {
  14. return _stepName;
  15. }
  16. }
  17. protected string _stepName;
  18. public TimeSpan StepLeftTime
  19. {
  20. get
  21. {
  22. if (_stepSpan.TotalMilliseconds < 1)
  23. return _stepSpan;
  24. return (_stepSpan - (DateTime.Now - _stepStartTime));
  25. }
  26. }
  27. protected TimeSpan _stepSpan = new TimeSpan(0, 0, 0, 0);
  28. protected DateTime _stepStartTime;
  29. private int _timeoutMS;
  30. protected Result RoutineStepResult { get; set; }
  31. protected void Notify(string message)
  32. {
  33. EV.PostInfoLog(Module, $"{Module} {Name}, {message}");
  34. }
  35. protected void Stop(string failReason)
  36. {
  37. EV.PostAlarmLog(Module, $"{Module} {Name} failed, {failReason}");
  38. }
  39. public void Abort(string failReason)
  40. {
  41. EV.PostAlarmLog(Module, $"{Module} {Name} {failReason}");
  42. }
  43. public void TimeDelay(int id, string stepName, double time)
  44. {
  45. Tuple<bool, Result> ret = Delay(id, () =>
  46. {
  47. Notify($"Delay {time} seconds");
  48. _stepSpan = new TimeSpan(0, 0, 0, (int)time);
  49. _stepStartTime = DateTime.Now;
  50. _stepName = stepName;
  51. return true;
  52. }, time * 1000);
  53. if (ret.Item1)
  54. {
  55. if (ret.Item2 == Result.RUN)
  56. {
  57. throw (new RoutineBreakException());
  58. }
  59. }
  60. }
  61. public void TimeDelay(int id, double time)
  62. {
  63. Tuple<bool, Result> ret = Delay(id, () =>
  64. {
  65. Notify($"Delay {time} seconds");
  66. _stepSpan = new TimeSpan(0, 0, 0, (int)time);
  67. _stepStartTime = DateTime.Now;
  68. return true;
  69. }, time * 1000);
  70. if (ret.Item1)
  71. {
  72. if (ret.Item2 == Result.RUN)
  73. {
  74. throw (new RoutineBreakException());
  75. }
  76. }
  77. }
  78. protected void ExecuteRoutine(int id, IRoutine routine)
  79. {
  80. Tuple<bool, Result> ret = ExecuteAndWait(id, routine);
  81. if (ret.Item1)
  82. {
  83. if (ret.Item2 == Result.FAIL)
  84. {
  85. throw (new RoutineFaildException());
  86. }
  87. else if (ret.Item2 == Result.RUN)
  88. {
  89. throw (new RoutineBreakException());
  90. }
  91. }
  92. }
  93. public void Loop(int id, int count)
  94. {
  95. Tuple<bool, Result> ret = Loop(id, () =>
  96. {
  97. Notify($"Start loop {LoopCounter + 1}/{count}");
  98. return true;
  99. }, count);
  100. if (ret.Item1)
  101. {
  102. if (ret.Item2 == Result.FAIL)
  103. throw new RoutineFaildException();
  104. }
  105. }
  106. public void EndLoop(int id)
  107. {
  108. Tuple<bool, Result> ret = EndLoop(id, () =>
  109. {
  110. Notify($"Loop finished");
  111. return true;
  112. });
  113. if (ret.Item1)
  114. {
  115. throw new RoutineBreakException();
  116. }
  117. }
  118. public virtual Result Monitor()
  119. {
  120. RoutineStart();
  121. MonitorStep();
  122. RoutineStop();
  123. return RoutineStepResult;
  124. }
  125. protected virtual void MonitorStep()
  126. {
  127. }
  128. protected void RoutineStart()
  129. {
  130. if (_historySteps.Count == 0 && _currentStepId == -1)
  131. {
  132. Notify($"begin");
  133. RoutineStepResult = Result.RUN;
  134. }
  135. _waitSteps.Clear();
  136. }
  137. protected void RoutineStop()
  138. {
  139. if (_waitSteps.Count == 0 && _historySteps.Contains(_currentStepId) && RoutineStepResult == Result.RUN)
  140. {
  141. RoutineStepResult = Result.DONE;
  142. Notify($"end");
  143. return;
  144. }
  145. //中间没有任何步骤
  146. if (_waitSteps.Count == 0 && _currentStepId == -1 && _historySteps.Count == 0 && RoutineStepResult == Result.RUN)
  147. {
  148. RoutineStepResult = Result.DONE;
  149. Notify($"end");
  150. return;
  151. }
  152. }
  153. /// <summary>
  154. ///
  155. /// </summary>
  156. /// <typeparam name="T"></typeparam>
  157. /// <param name="stepName"></param>
  158. /// <param name="stepAction"></param>
  159. /// <param name="timeoutAction">这里描述具体的错误信息和提示,以及超时错误后的安全收尾动作</param>
  160. /// <param name="failedAction">这里描述具体的错误信息和提示,以及超时错误后的安全收尾动作</param>
  161. protected void RoutineStep<T>(T stepName, Func<Result> stepAction, Action timeoutAction=null ,
  162. Action failedAction=null )
  163. {
  164. //如果超时,或者失败,避免重入;只有reset之后才能继续
  165. if (RoutineStepResult != Result.RUN)
  166. return;
  167. int id = Convert.ToInt32(stepName);
  168. //已经执行过的步骤,跳过去
  169. if (_historySteps.Contains(id))
  170. return;
  171. //上一步执行完毕,继续执行下一步
  172. if (_currentStepId == -1 || (_historySteps.Contains(_currentStepId) && _currentStepId != id))
  173. {
  174. _currentStepId = id;
  175. if (_waitSteps.Contains(id))
  176. {
  177. _waitSteps.Remove(id);
  178. }
  179. LOG.Write($"{Module} {Name}, start step {id}={stepName}");
  180. }
  181. //待执行的步骤
  182. if (_currentStepId != id)
  183. {
  184. if (!_waitSteps.Contains(id))
  185. {
  186. _waitSteps.Add(id);
  187. }
  188. return;
  189. }
  190. try
  191. {
  192. RoutineStepResult = stepAction.Invoke();
  193. if (RoutineStepResult == Result.TIMEOUT )
  194. {
  195. if (timeoutAction != null)
  196. {
  197. timeoutAction();
  198. }
  199. else
  200. {
  201. Stop($"timeout, can not complete {stepName} in {_timeoutMS} ms.");
  202. }
  203. RoutineStepResult = Result.FAIL;
  204. }
  205. if (RoutineStepResult == Result.FAIL )
  206. {
  207. if (failedAction != null)
  208. {
  209. failedAction();
  210. }
  211. else
  212. {
  213. Stop($"failed to do {stepName}");
  214. }
  215. }
  216. }
  217. catch (Exception ex)
  218. {
  219. LOG.Write(ex);
  220. }
  221. }
  222. public Result ExecuteAndWait(Func<bool> execute, Func<bool?> check, double timeout = int.MaxValue)
  223. {
  224. bool? bExecute = false;
  225. if (_stepState == STATE.IDLE)
  226. {
  227. if (!execute())
  228. {
  229. return Result.FAIL; //执行错误
  230. }
  231. _timeoutMS = (int)timeout;
  232. _timer.Start(timeout);
  233. _stepState = STATE.WAIT;
  234. }
  235. bExecute = check();
  236. if (bExecute == null)
  237. {
  238. return Result.FAIL; //Terminate
  239. }
  240. else
  241. {
  242. if (bExecute.Value) //检查Success, next
  243. {
  244. NextStep();
  245. return Result.RUN;
  246. }
  247. }
  248. if (_timer.IsTimeout())
  249. return Result.TIMEOUT;
  250. return Result.RUN;
  251. }
  252. public Result ExecuteAndWait(IRoutine routine)
  253. {
  254. if (_stepState == STATE.IDLE)
  255. {
  256. Result startRet = routine.Start();
  257. if (startRet == Result.FAIL)
  258. {
  259. return Result.FAIL; //执行错误
  260. }
  261. else if (startRet == Result.DONE)
  262. {
  263. NextStep();
  264. return Result.RUN;
  265. }
  266. _stepState = STATE.WAIT;
  267. }
  268. Result ret = routine.Monitor();
  269. if (ret == Result.DONE)
  270. {
  271. NextStep();
  272. return Result.RUN;
  273. }
  274. else if (ret == Result.FAIL || ret == Result.TIMEOUT)
  275. {
  276. return Result.FAIL;
  277. }
  278. else
  279. {
  280. return Result.RUN;
  281. }
  282. }
  283. public Result Delay(Func<bool> func, double timeMS)
  284. {
  285. if (_stepState == STATE.IDLE)
  286. {
  287. if ((func != null) && !func())
  288. {
  289. return Result.FAIL;
  290. }
  291. _timer.Start(timeMS);
  292. _stepState = STATE.WAIT;
  293. }
  294. if (_timer.IsTimeout())
  295. {
  296. NextStep();
  297. }
  298. return Result.RUN;
  299. }
  300. public Result Loop(int count)
  301. {
  302. _loopStepStartId = _currentStepId;
  303. _loopTotalCountSetting = count;
  304. NextStep();
  305. EV.PostInfoLog(Module, $"{Name} loop begin, {_loopCounter + 1}/{_loopTotalCountSetting}");
  306. return Result.RUN;
  307. }
  308. public void RoutineLoop<T>(T stepId, int count)
  309. {
  310. RoutineStep(stepId, () => Loop(count), null, null);
  311. }
  312. public Result EndLoop()
  313. {
  314. EV.PostInfoLog(Module, $"{Name} loop end, {_loopCounter + 1}/{_loopTotalCountSetting}");
  315. ++_loopCounter;
  316. if (_loopCounter >= _loopTotalCountSetting) //Loop 结束
  317. {
  318. _loopCounter = 0;
  319. _loopTotalCountSetting = 0; // Loop 结束时,当前loop和loop总数都清零
  320. NextStep();
  321. return Result.RUN;
  322. }
  323. //继续下一LOOP
  324. NextStep(_loopStepStartId);
  325. return Result.RUN;
  326. }
  327. public void RoutineEndLoop<T>(T stepId)
  328. {
  329. RoutineStep(stepId, () => EndLoop(), null, null);
  330. }
  331. protected Result ExecuteRoutine(IRoutine routine)
  332. {
  333. return ExecuteAndWait(routine);
  334. }
  335. }
  336. }