| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 | using System;using System.Diagnostics;using System.Threading;using System.Collections.Generic;using System.Collections.Concurrent;using Aitex.Core.RT.Log;using Aitex.Core.Utilities;using System.Linq;namespace Aitex.Core.RT.Fsm{    /// <summary>    /// FSM transition function    /// 返回值: true  需要转换状态    ///          false 保持状态不变    /// </summary>    /// <param name="param"></param>    /// <returns></returns>    public enum FSM_MSG    {        TIMER = 0x0FFFFFF0,        NONE,        WARNING,        ALARM,          }    public enum FSM_STATE    {        UNDEFINE = 0x0FFFFFF0,        SAME,        ANY,    }    public class StateMachine : StateMachine<object>    {        public StateMachine(string name = "FSM", int initState = (int)FSM_STATE.UNDEFINE, int interval = 100) : base(name, initState, interval)        {        }    }    public class StateMachine<T> : IStateMachine    {        public string Name { get; set; }        public int ElapsedTime        {            get            {                int ticket = Environment.TickCount;                return ticket > enterTime ? ticket - enterTime : 0x7FFFFFFF + ticket - enterTime;            }        }        public int EnterTime { set { enterTime = value; } }        public int State { get; set; }        public int PrevState { get; set; }        public int LastMsg { get; private set; }        private int enterTime;        public int MaxMsgInQueue { get; set; }        private int interval;        private bool _enableRepeatedMsg;        private CancellationTokenSource cancelToken;        private BlockingCollection<KeyValuePair<int, object[]>> _msgQueue;        private object _lockerMsgQueue = new object();        private KeyValuePair<int, object[]> timeoutMsg = new KeyValuePair<int, object[]>((int)FSM_MSG.TIMER, null);        /// <summary>        /// 状态迁移表           当前状态, 消息, 函数, 迁移状态        /// AnyState迁移表       消息, 函数, 迁移状态        /// 状态进入/退出迁移表  状态,进入函数,进入消息,退出函数,         /// </summary>        private Dictionary<int, Dictionary<int, Tuple<FsmFunc, int>>> transition;        private Dictionary<int, Tuple<FsmFunc, int>> anyStateTransition;        private Dictionary<int, Tuple<FsmFunc, int, FsmFunc>> enterExitTransition;        private Dictionary<int, string> _stringState = new Dictionary<int, string>();        private Dictionary<int, string> _stringMessage = new Dictionary<int, string>();        private KeyValuePair<int, object[]> _msgInProcess = new KeyValuePair<int, object[]>((int)FSM_MSG.TIMER, null);        private long _msgCounter = 0;        List<FsmFunc> fsmFuncs = new List<FsmFunc>();        public StateMachine(string name, int initState = (int)FSM_STATE.UNDEFINE, int interval = 100)        {            Name = name + " FSM";            MaxMsgInQueue = 500;            this.State = initState;            this.PrevState = initState;            this.interval = interval;            cancelToken = new CancellationTokenSource();            _msgQueue = new BlockingCollection<KeyValuePair<int, object[]>>();            transition = new Dictionary<int, Dictionary<int, Tuple<FsmFunc, int>>>();            anyStateTransition = new Dictionary<int, Tuple<FsmFunc, int>>();            enterExitTransition = new Dictionary<int, Tuple<FsmFunc, int, FsmFunc>>();            EnumLoop<FSM_STATE>.ForEach((item) =>            {                MapState((int)item, item.ToString());            });            EnumLoop<FSM_MSG>.ForEach((item) =>            {                MapMessage((int)item, item.ToString());            });        }        #region Interface        public void Init(int initState, int intervalTimeMs)        {            State = initState;            interval = intervalTimeMs;        }        public void Start()        {            OnEnterState(this.State);        }        public void Loop()        {            while (!cancelToken.IsCancellationRequested)            {                //_msgInProcess = timeoutMsg;                try                {                    KeyValuePair<int, object[]> msg = timeoutMsg;                    lock (_lockerMsgQueue)                    {                        if (!_msgQueue.TryTake(out msg, interval, cancelToken.Token))                            _msgInProcess = timeoutMsg;                        else                        {                            _msgInProcess = msg;                        }                    }                    //Loop AnyState迁移表                                        if (anyStateTransition.ContainsKey(_msgInProcess.Key))                    {                        //if (anyStateTransition[_msgInProcess.Key].Item3 != null && !fsmFuncs.Keys.Contains(_msgInProcess.Key))                        //{                        //    fsmFuncs.Add(_msgInProcess.Key,anyStateTransition[_msgInProcess.Key].Item3);                        //}                        if (anyStateTransition[_msgInProcess.Key].Item1 != null)                        {                            if (anyStateTransition[_msgInProcess.Key].Item1(_msgInProcess.Value))  //need ChangeState                            {                                if (anyStateTransition[_msgInProcess.Key].Item2 != State && anyStateTransition[_msgInProcess.Key].Item2 != (int)FSM_STATE.SAME)                                {                                    OnExitState((int)FSM_STATE.ANY);                                    OnExitState(State);                                    enterTime = Environment.TickCount;                                    LastMsg = msg.Key;                                    PrevState = State;                                    State = anyStateTransition[_msgInProcess.Key].Item2;                                    ///add log                                    //if (Name == "EFEM FSM")                                    {                                        LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, $"状态机 {Name}收到消息 {GetStringMessage(_msgInProcess.Key)}, 状态 {GetStringState(PrevState)}==>{GetStringState(State)}");                                    }                                    OnEnterState((int)FSM_STATE.ANY);                                    OnEnterState((int)State);                                }                            }                        }                        if (_msgInProcess.Key != timeoutMsg.Key)                        {                            Interlocked.Decrement(ref _msgCounter);                            //System.Diagnostics.Trace.WriteLine($"message out1: {Name}--> {_msgCounter}");                        }                        continue;                    }                    foreach (var func in fsmFuncs)                    {                        func.Invoke(null);                    }                    if (!transition.ContainsKey(State))                    {                        if (_msgInProcess.Key != (int)FSM_MSG.TIMER)                        {                            LOG.Write(eEvent.WARN_FSM_WARN, MECF.Framework.Common.Equipment.ModuleName.System, $"StateMachine [{Name}] no definition of state [{GetStringState(State)}] ");                        }                        if (_msgInProcess.Key != timeoutMsg.Key)                        {                            Interlocked.Decrement(ref _msgCounter);                            //System.Diagnostics.Trace.WriteLine($"message out2: {Name} --> {_msgCounter}");                        }                        continue;                    }                    if (!transition[State].ContainsKey(_msgInProcess.Key))                    {                        if (_msgInProcess.Key != (int)FSM_MSG.TIMER)                        {                            LOG.Write(eEvent.WARN_FSM_WARN, MECF.Framework.Common.Equipment.ModuleName.System, $"StateMachine {Name} no definition of [state={GetStringState(State)}], [message={GetStringMessage(_msgInProcess.Key)}]");                        }                        if (_msgInProcess.Key != timeoutMsg.Key)                        {                            Interlocked.Decrement(ref _msgCounter);                            // System.Diagnostics.Trace.WriteLine($"message out3:{Name}--> {_msgCounter}");                        }                        continue;                    }                    //Loop Transition                     //if fun is null or fun return true need change                    if (transition[State][_msgInProcess.Key].Item1 == null || transition[State][_msgInProcess.Key].Item1(_msgInProcess.Value))                    {                        if (transition[State][_msgInProcess.Key].Item2 != State && transition[State][_msgInProcess.Key].Item2 != (int)FSM_STATE.SAME)                        {                            OnExitState((int)FSM_STATE.ANY);                            OnExitState(State);                            enterTime = Environment.TickCount;                            PrevState = State;                            State = transition[State][_msgInProcess.Key].Item2;                            ///add log                            //if (Name == "EFEM FSM")                            {                                LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, $"状态机 {Name}收到消息 {GetStringMessage(_msgInProcess.Key)}, 状态 {GetStringState(PrevState)}==>{GetStringState(State)}");                            }                            OnEnterState((int)FSM_STATE.ANY);                            OnEnterState((int)State);                        }                    }                    if (_msgInProcess.Key != timeoutMsg.Key)                    {                        Interlocked.Decrement(ref _msgCounter);                        //System.Diagnostics.Trace.WriteLine($"message out4: {Name}--> {_msgCounter}");                    }                    _msgInProcess = timeoutMsg;                }                catch (OperationCanceledException)                {                    LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, $"FSM {Name} is canceled");                }                catch (Exception ex)                {                    LOG.Write(eEvent.EV_FSM_NOTIFY, MECF.Framework.Common.Equipment.ModuleName.System, ex.StackTrace + ex.Message);                }            }        }        public void Stop()        {            cancelToken.Cancel();        }        string GetStringState(int state)        {            if (_stringState.ContainsKey(state))                return _stringState[state];            return state.ToString();        }        string GetStringMessage(int message)        {            if (_stringMessage.ContainsKey(message))                return _stringMessage[message];            return message.ToString();                  }        public void MapState(int state, string stringState)        {            System.Diagnostics.Debug.Assert(!_stringState.ContainsKey(state));            _stringState[state] = stringState;        }        public  void MapMessage(int message, string stringMessage)        {            System.Diagnostics.Debug.Assert(!_stringMessage.ContainsKey(message));            _stringMessage[message] = stringMessage;        }        public bool FindTransition(int state, int msg)        {            if (anyStateTransition.ContainsKey(msg))                return true;            if (transition.ContainsKey(state) && transition[state] != null)            {                Dictionary<int, Tuple<FsmFunc, int>> table = transition[state];                if (table.ContainsKey(msg))                    return true;            }            return false;        }        public void Transition(int state, int msg, FsmFunc func, int next)        {            if (!transition.ContainsKey(state) || transition[state] == null)            {                transition[state] = new Dictionary<int, Tuple<FsmFunc, int>>();            }            transition[state][msg] = new Tuple<FsmFunc, int>(func, next);        }        public void AnyStateTransition(int msg, FsmFunc func, int next)        {            if (msg != timeoutMsg.Key)            {                anyStateTransition[msg] = new Tuple<FsmFunc, int>(func, next);            }            else            {                fsmFuncs.Add(func);            }        }        //public void AnyStateTransition(int msg, FsmFunc func, int next, FsmFunc monitorFunc)        //{        //    anyStateTransition[msg] = new Tuple<FsmFunc, int,FsmFunc>(func, next,monitorFunc);        //}        public void EnterExitTransition(int state, FsmFunc enter, int msg, FsmFunc exit)        {            enterExitTransition[state] = new Tuple<FsmFunc, int, FsmFunc>(enter, msg, exit);        }        public void EnableRepeatedMsg(bool enable)        {            _enableRepeatedMsg = enable;        }        public void PostMsg(int msg, params object[] args)        {            Interlocked.Increment(ref _msgCounter);            //lock (_lockerMsgQueue)            {                _msgQueue.Add(new KeyValuePair<int, object[]>(msg, args));            }            //System.Diagnostics.Trace.WriteLine($"PostMsg: {msg}--> {_msgCounter}");        }        public void PostMsgWithoutLock(int msg, params object[] args)        {            Interlocked.Increment(ref _msgCounter);            _msgQueue.Add(new KeyValuePair<int, object[]>(msg, args));            //System.Diagnostics.Trace.WriteLine($"PostMsgWithoutLock: {msg}--> {_msgCounter}");        }        #endregion        private void OnEnterState(int state)        {            if (enterExitTransition.ContainsKey(state))            {                if (enterExitTransition[state].Item1 != null)                {                    enterExitTransition[state].Item1(null);                }                if (enterExitTransition[state].Item2 != (int)FSM_MSG.NONE)                {                    PostMsg(enterExitTransition[state].Item2, null);                }            }        }        private void OnExitState(int state)        {            if (enterExitTransition.ContainsKey(state))            {                if (enterExitTransition[state].Item3 != null)                {                    enterExitTransition[state].Item3(null);                }            }        }        public bool CheckExecuted(int msg)        {            return _msgCounter == 0;            //lock (_lockerMsgQueue)            //{            //    foreach (var keyValuePair in _msgQueue)            //    {            //        if (keyValuePair.Key == msg)            //            return false;            //    }            //    if (_msgInProcess.Key == msg)            //        return false;            //}            //return true;        }        public bool CheckExecuted()        {            //System.Diagnostics.Trace.WriteLine($"CheckExecuted: --> {_msgCounter}");            return _msgCounter == 0;            //return Interlocked.CompareExchange(ref _msgCounter, 0, 0) == 0;            ////lock (_lockerMsgQueue)            //{            //    return _msgQueue.Count == 0 && _msgInProcess.Key==(int)FSM_MSG.TIMER;            //}        }        public bool CheckExecuted(int msg, out int currentMsg, out List<int> msgQueue)        {            currentMsg = 0;            msgQueue = new List<int>();            return _msgCounter == 0;            //lock (_lockerMsgQueue)            //{            //    currentMsg = 0;            //    msgQueue = new List<int>();            //    foreach (var keyValuePair in _msgQueue)            //    {            //        if (keyValuePair.Key == msg)            //            return false;            //        msgQueue.Add(keyValuePair.Key);            //    }            //    if (_msgInProcess.Key == msg)            //    {            //        return false;            //    }            //    currentMsg = _msgInProcess.Key;            //}            //return true;        }    }}
 |