StateMachine.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. using System;
  2. using System.Diagnostics;
  3. using System.Threading;
  4. using System.Collections.Generic;
  5. using System.Collections.Concurrent;
  6. using Aitex.Core.RT.Log;
  7. using Aitex.Core.Utilities;
  8. using System.Linq;
  9. namespace Aitex.Core.RT.Fsm
  10. {
  11. /// <summary>
  12. /// FSM transition function
  13. /// 返回值: true 需要转换状态
  14. /// false 保持状态不变
  15. /// </summary>
  16. /// <param name="param"></param>
  17. /// <returns></returns>
  18. public enum FSM_MSG
  19. {
  20. TIMER = 0x0FFFFFF0,
  21. NONE,
  22. WARNING,
  23. ALARM,
  24. }
  25. public enum FSM_STATE
  26. {
  27. UNDEFINE = 0x0FFFFFF0,
  28. SAME,
  29. ANY,
  30. }
  31. public class StateMachine : StateMachine<object>
  32. {
  33. public StateMachine(string name = "FSM", int initState = (int)FSM_STATE.UNDEFINE, int interval = 100) : base(name, initState, interval)
  34. {
  35. }
  36. }
  37. public class StateMachine<T> : IStateMachine
  38. {
  39. public string Name { get; set; }
  40. public int ElapsedTime
  41. {
  42. get
  43. {
  44. int ticket = Environment.TickCount;
  45. return ticket > enterTime ? ticket - enterTime : 0x7FFFFFFF + ticket - enterTime;
  46. }
  47. }
  48. public int EnterTime { set { enterTime = value; } }
  49. public int State { get; set; }
  50. public int PrevState { get; set; }
  51. public int LastMsg { get; private set; }
  52. private int enterTime;
  53. public int MaxMsgInQueue { get; set; }
  54. private int interval;
  55. private bool _enableRepeatedMsg;
  56. private CancellationTokenSource cancelToken;
  57. private BlockingCollection<KeyValuePair<int, object[]>> _msgQueue;
  58. private object _lockerMsgQueue = new object();
  59. private KeyValuePair<int, object[]> timeoutMsg = new KeyValuePair<int, object[]>((int)FSM_MSG.TIMER, null);
  60. /// <summary>
  61. /// 状态迁移表 当前状态, 消息, 函数, 迁移状态
  62. /// AnyState迁移表 消息, 函数, 迁移状态
  63. /// 状态进入/退出迁移表 状态,进入函数,进入消息,退出函数,
  64. /// </summary>
  65. private Dictionary<int, Dictionary<int, Tuple<FsmFunc, int>>> transition;
  66. private Dictionary<int, Tuple<FsmFunc, int>> anyStateTransition;
  67. private Dictionary<int, Tuple<FsmFunc, int, FsmFunc>> enterExitTransition;
  68. private Dictionary<int, string> _stringState = new Dictionary<int, string>();
  69. private Dictionary<int, string> _stringMessage = new Dictionary<int, string>();
  70. private KeyValuePair<int, object[]> _msgInProcess = new KeyValuePair<int, object[]>((int)FSM_MSG.TIMER, null);
  71. private long _msgCounter = 0;
  72. List<FsmFunc> fsmFuncs = new List<FsmFunc>();
  73. public StateMachine(string name, int initState = (int)FSM_STATE.UNDEFINE, int interval = 100)
  74. {
  75. Name = name + " FSM";
  76. MaxMsgInQueue = 500;
  77. this.State = initState;
  78. this.PrevState = initState;
  79. this.interval = interval;
  80. cancelToken = new CancellationTokenSource();
  81. _msgQueue = new BlockingCollection<KeyValuePair<int, object[]>>();
  82. transition = new Dictionary<int, Dictionary<int, Tuple<FsmFunc, int>>>();
  83. anyStateTransition = new Dictionary<int, Tuple<FsmFunc, int>>();
  84. enterExitTransition = new Dictionary<int, Tuple<FsmFunc, int, FsmFunc>>();
  85. EnumLoop<FSM_STATE>.ForEach((item) =>
  86. {
  87. MapState((int)item, item.ToString());
  88. });
  89. EnumLoop<FSM_MSG>.ForEach((item) =>
  90. {
  91. MapMessage((int)item, item.ToString());
  92. });
  93. }
  94. #region Interface
  95. public void Init(int initState, int intervalTimeMs)
  96. {
  97. State = initState;
  98. interval = intervalTimeMs;
  99. }
  100. public void Start()
  101. {
  102. OnEnterState(this.State);
  103. }
  104. public void Loop()
  105. {
  106. while (!cancelToken.IsCancellationRequested)
  107. {
  108. //_msgInProcess = timeoutMsg;
  109. try
  110. {
  111. KeyValuePair<int, object[]> msg = timeoutMsg;
  112. lock (_lockerMsgQueue)
  113. {
  114. if (!_msgQueue.TryTake(out msg, interval, cancelToken.Token))
  115. _msgInProcess = timeoutMsg;
  116. else
  117. {
  118. _msgInProcess = msg;
  119. }
  120. }
  121. //Loop AnyState迁移表
  122. if (anyStateTransition.ContainsKey(_msgInProcess.Key))
  123. {
  124. //if (anyStateTransition[_msgInProcess.Key].Item3 != null && !fsmFuncs.Keys.Contains(_msgInProcess.Key))
  125. //{
  126. // fsmFuncs.Add(_msgInProcess.Key,anyStateTransition[_msgInProcess.Key].Item3);
  127. //}
  128. if (anyStateTransition[_msgInProcess.Key].Item1 != null)
  129. {
  130. if (anyStateTransition[_msgInProcess.Key].Item1(_msgInProcess.Value)) //need ChangeState
  131. {
  132. if (anyStateTransition[_msgInProcess.Key].Item2 != State && anyStateTransition[_msgInProcess.Key].Item2 != (int)FSM_STATE.SAME)
  133. {
  134. OnExitState((int)FSM_STATE.ANY);
  135. OnExitState(State);
  136. enterTime = Environment.TickCount;
  137. LastMsg = msg.Key;
  138. PrevState = State;
  139. State = anyStateTransition[_msgInProcess.Key].Item2;
  140. ///add log
  141. //if (Name == "EFEM FSM")
  142. {
  143. LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, $"状态机 {Name}收到消息 {GetStringMessage(_msgInProcess.Key)}, 状态 {GetStringState(PrevState)}==>{GetStringState(State)}");
  144. }
  145. OnEnterState((int)FSM_STATE.ANY);
  146. OnEnterState((int)State);
  147. }
  148. }
  149. }
  150. if (_msgInProcess.Key != timeoutMsg.Key)
  151. {
  152. Interlocked.Decrement(ref _msgCounter);
  153. //System.Diagnostics.Trace.WriteLine($"message out1: {Name}--> {_msgCounter}");
  154. }
  155. continue;
  156. }
  157. foreach (var func in fsmFuncs)
  158. {
  159. func.Invoke(null);
  160. }
  161. if (!transition.ContainsKey(State))
  162. {
  163. if (_msgInProcess.Key != (int)FSM_MSG.TIMER)
  164. {
  165. LOG.Write(eEvent.WARN_FSM_WARN, MECF.Framework.Common.Equipment.ModuleName.System, $"StateMachine [{Name}] no definition of state [{GetStringState(State)}] ");
  166. }
  167. if (_msgInProcess.Key != timeoutMsg.Key)
  168. {
  169. Interlocked.Decrement(ref _msgCounter);
  170. //System.Diagnostics.Trace.WriteLine($"message out2: {Name} --> {_msgCounter}");
  171. }
  172. continue;
  173. }
  174. if (!transition[State].ContainsKey(_msgInProcess.Key))
  175. {
  176. if (_msgInProcess.Key != (int)FSM_MSG.TIMER)
  177. {
  178. LOG.Write(eEvent.WARN_FSM_WARN, MECF.Framework.Common.Equipment.ModuleName.System, $"StateMachine {Name} no definition of [state={GetStringState(State)}], [message={GetStringMessage(_msgInProcess.Key)}]");
  179. }
  180. if (_msgInProcess.Key != timeoutMsg.Key)
  181. {
  182. Interlocked.Decrement(ref _msgCounter);
  183. // System.Diagnostics.Trace.WriteLine($"message out3:{Name}--> {_msgCounter}");
  184. }
  185. continue;
  186. }
  187. //Loop Transition
  188. //if fun is null or fun return true need change
  189. if (transition[State][_msgInProcess.Key].Item1 == null || transition[State][_msgInProcess.Key].Item1(_msgInProcess.Value))
  190. {
  191. if (transition[State][_msgInProcess.Key].Item2 != State && transition[State][_msgInProcess.Key].Item2 != (int)FSM_STATE.SAME)
  192. {
  193. OnExitState((int)FSM_STATE.ANY);
  194. OnExitState(State);
  195. enterTime = Environment.TickCount;
  196. PrevState = State;
  197. State = transition[State][_msgInProcess.Key].Item2;
  198. ///add log
  199. //if (Name == "EFEM FSM")
  200. {
  201. LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, $"状态机 {Name}收到消息 {GetStringMessage(_msgInProcess.Key)}, 状态 {GetStringState(PrevState)}==>{GetStringState(State)}");
  202. }
  203. OnEnterState((int)FSM_STATE.ANY);
  204. OnEnterState((int)State);
  205. }
  206. }
  207. if (_msgInProcess.Key != timeoutMsg.Key)
  208. {
  209. Interlocked.Decrement(ref _msgCounter);
  210. //System.Diagnostics.Trace.WriteLine($"message out4: {Name}--> {_msgCounter}");
  211. }
  212. _msgInProcess = timeoutMsg;
  213. }
  214. catch (OperationCanceledException)
  215. {
  216. LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, $"FSM {Name} is canceled");
  217. }
  218. catch (Exception ex)
  219. {
  220. LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, ex.StackTrace + ex.Message);
  221. }
  222. }
  223. }
  224. public void Stop()
  225. {
  226. cancelToken.Cancel();
  227. }
  228. string GetStringState(int state)
  229. {
  230. if (_stringState.ContainsKey(state))
  231. return _stringState[state];
  232. return state.ToString();
  233. }
  234. string GetStringMessage(int message)
  235. {
  236. if (_stringMessage.ContainsKey(message))
  237. return _stringMessage[message];
  238. return message.ToString();
  239. }
  240. public void MapState(int state, string stringState)
  241. {
  242. System.Diagnostics.Debug.Assert(!_stringState.ContainsKey(state));
  243. _stringState[state] = stringState;
  244. }
  245. public void MapMessage(int message, string stringMessage)
  246. {
  247. System.Diagnostics.Debug.Assert(!_stringMessage.ContainsKey(message));
  248. _stringMessage[message] = stringMessage;
  249. }
  250. public bool FindTransition(int state, int msg)
  251. {
  252. if (anyStateTransition.ContainsKey(msg))
  253. return true;
  254. if (transition.ContainsKey(state) && transition[state] != null)
  255. {
  256. Dictionary<int, Tuple<FsmFunc, int>> table = transition[state];
  257. if (table.ContainsKey(msg))
  258. return true;
  259. }
  260. return false;
  261. }
  262. public void Transition(int state, int msg, FsmFunc func, int next)
  263. {
  264. if (!transition.ContainsKey(state) || transition[state] == null)
  265. {
  266. transition[state] = new Dictionary<int, Tuple<FsmFunc, int>>();
  267. }
  268. transition[state][msg] = new Tuple<FsmFunc, int>(func, next);
  269. }
  270. public void AnyStateTransition(int msg, FsmFunc func, int next)
  271. {
  272. if (msg != timeoutMsg.Key)
  273. {
  274. anyStateTransition[msg] = new Tuple<FsmFunc, int>(func, next);
  275. }
  276. else
  277. {
  278. fsmFuncs.Add(func);
  279. }
  280. }
  281. //public void AnyStateTransition(int msg, FsmFunc func, int next, FsmFunc monitorFunc)
  282. //{
  283. // anyStateTransition[msg] = new Tuple<FsmFunc, int,FsmFunc>(func, next,monitorFunc);
  284. //}
  285. public void EnterExitTransition(int state, FsmFunc enter, int msg, FsmFunc exit)
  286. {
  287. enterExitTransition[state] = new Tuple<FsmFunc, int, FsmFunc>(enter, msg, exit);
  288. }
  289. public void EnableRepeatedMsg(bool enable)
  290. {
  291. _enableRepeatedMsg = enable;
  292. }
  293. public void PostMsg(int msg, params object[] args)
  294. {
  295. Interlocked.Increment(ref _msgCounter);
  296. //lock (_lockerMsgQueue)
  297. {
  298. _msgQueue.Add(new KeyValuePair<int, object[]>(msg, args));
  299. }
  300. //System.Diagnostics.Trace.WriteLine($"PostMsg: {msg}--> {_msgCounter}");
  301. }
  302. public void PostMsgWithoutLock(int msg, params object[] args)
  303. {
  304. Interlocked.Increment(ref _msgCounter);
  305. _msgQueue.Add(new KeyValuePair<int, object[]>(msg, args));
  306. //System.Diagnostics.Trace.WriteLine($"PostMsgWithoutLock: {msg}--> {_msgCounter}");
  307. }
  308. #endregion
  309. private void OnEnterState(int state)
  310. {
  311. if (enterExitTransition.ContainsKey(state))
  312. {
  313. if (enterExitTransition[state].Item1 != null)
  314. {
  315. enterExitTransition[state].Item1(null);
  316. }
  317. if (enterExitTransition[state].Item2 != (int)FSM_MSG.NONE)
  318. {
  319. PostMsg(enterExitTransition[state].Item2, null);
  320. }
  321. }
  322. }
  323. private void OnExitState(int state)
  324. {
  325. if (enterExitTransition.ContainsKey(state))
  326. {
  327. if (enterExitTransition[state].Item3 != null)
  328. {
  329. enterExitTransition[state].Item3(null);
  330. }
  331. }
  332. }
  333. public bool CheckExecuted(int msg)
  334. {
  335. return _msgCounter == 0;
  336. //lock (_lockerMsgQueue)
  337. //{
  338. // foreach (var keyValuePair in _msgQueue)
  339. // {
  340. // if (keyValuePair.Key == msg)
  341. // return false;
  342. // }
  343. // if (_msgInProcess.Key == msg)
  344. // return false;
  345. //}
  346. //return true;
  347. }
  348. public bool CheckExecuted()
  349. {
  350. //System.Diagnostics.Trace.WriteLine($"CheckExecuted: --> {_msgCounter}");
  351. return _msgCounter == 0;
  352. //return Interlocked.CompareExchange(ref _msgCounter, 0, 0) == 0;
  353. ////lock (_lockerMsgQueue)
  354. //{
  355. // return _msgQueue.Count == 0 && _msgInProcess.Key==(int)FSM_MSG.TIMER;
  356. //}
  357. }
  358. public bool CheckExecuted(int msg, out int currentMsg, out List<int> msgQueue)
  359. {
  360. currentMsg = 0;
  361. msgQueue = new List<int>();
  362. return _msgCounter == 0;
  363. //lock (_lockerMsgQueue)
  364. //{
  365. // currentMsg = 0;
  366. // msgQueue = new List<int>();
  367. // foreach (var keyValuePair in _msgQueue)
  368. // {
  369. // if (keyValuePair.Key == msg)
  370. // return false;
  371. // msgQueue.Add(keyValuePair.Key);
  372. // }
  373. // if (_msgInProcess.Key == msg)
  374. // {
  375. // return false;
  376. // }
  377. // currentMsg = _msgInProcess.Key;
  378. //}
  379. //return true;
  380. }
  381. }
  382. }