| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 | using System;using System.Collections.Generic;using System.Runtime.InteropServices;using Aitex.Core.RT.Fsm;using Aitex.Core.RT.IOCore;using Aitex.Core.Util;using Aitex.Core.RT.Log;namespace Aitex.Core.RT.PLC{    public class PLCEntityT<T, TBuffer, TInput, TOutput> : Entity        where T : IDataDevice, new()        where TBuffer : IDataBuffer<TInput, TOutput>, new()        where TInput : struct        where TOutput : struct    {        private T device = default(T);        private Dictionary<string, TBuffer> _buffers = new Dictionary<string,TBuffer>();         //retry         private int error = 0;        private int retryWaitTime = 100;        private int retryTimes = 10;        private R_TRIG errTrig = new R_TRIG();                     public enum STATE        {            INIT,            RUNNING,            ERROR,       //                   };        public enum MSG        {            INIT,            ERROR,            RECOVERY,            RESET,        };        public PLCEntityT()        {            Running = false;            device = new T();            foreach (var type in device.GetTypes())            {                _buffers[type] = new TBuffer();            }            fsm = new StateMachine<PLCEntityT<T, TBuffer, TInput, TOutput>>("PLC", (int)STATE.INIT, 37);            EnterExitTransition<STATE, MSG>(STATE.INIT, null, MSG.INIT, null);              Transition(STATE.INIT, MSG.INIT, OpenDevice, STATE.RUNNING);            Transition(STATE.RUNNING, FSM_MSG.TIMER, Run, STATE.RUNNING);            Transition(STATE.RUNNING, MSG.RESET, Reset, STATE.RUNNING);                       Transition(STATE.ERROR, FSM_MSG.TIMER, Retry, STATE.RUNNING);            Transition(STATE.ERROR, MSG.RECOVERY, Recovery, STATE.INIT);            AnyStateTransition(MSG.ERROR, Error, STATE.ERROR);            errTrig.CLK = false;                  }        #region FSM Function        private bool OpenDevice(object[] objs)        {            Running = false;            if (!device.Open())            {                PostMsg<MSG>(MSG.ERROR);                return false;                  //don't change state            }                      return true;        }        private bool Run(object[] objs)        {            try            {                foreach (var type in device.GetTypes())                {                    try                    {                        if (!device.IsOpen(type))                        {                            device.Open(type);                            continue;                        }                        object obj = device.Read<TInput>(type);                        if (obj == null)                        {                            throw new Exception();                        }                        _buffers[type].Input = (TInput)obj;                        //Singleton<IOGroupManager>.Instance.Update(type, _buffers[type]);                        if (device.Write(type, _buffers[type].Output))                        {                            errTrig.CLK = false;                            error = 0;                        }                    }                    catch (Exception ex)                    {                        device.Close(type);                        LOG.WriteExeption(ex);                    }                                }            }            catch (Exception ex)            {                errTrig.CLK = true;                if (errTrig.Q)                {                    LOG.WriteExeption(ex);                }            }            Running = true;            return true;        }                        private bool Error(object[] objs)        {            //add log            if (error++ > retryTimes || !device.IsOpened)            {                PostMsg(MSG.RECOVERY);            }            return true;        }        private bool Retry(object[] objs)        {            //add log            int elapsed = fsm.ElapsedTime;            if (elapsed > retryWaitTime)            {                return true;            }            return false;        }        //关闭连接        private bool Recovery(object[] objs)        {            device.Close();            return true;        }        private bool Reset(object[] objs)        {            errTrig.RST = true;            return true;        }               #endregion    }  }
 |