| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671 | using System;using System.Collections.Generic;using System.IO.Ports;using System.Net.Sockets;using System.Threading;using Aitex.Core.RT.Event;using Aitex.Core.RT.Log;using Aitex.Core.Util;namespace MECF.Framework.Common.Communications{    public abstract class SerialPortConnectionBase : IConnection    {        public string Address        {            get { return _address; }        }        public bool IsConnected        {            get { return _port.IsOpen(); }        }        public bool Connect()        {            return _port.Open();        }        public bool Disconnect()        {            _port.Close();            return true;        }        public void TerminateCom()        {            _port.Dispose();        }        public bool IsBusy        {            get { return _activeHandler != null; }        }        public HandlerBase ActiveHandler => _activeHandler;        public bool IsCommunicationError { get; private set; }        public string LastCommunicationError { get; private set; }        private AsyncSerialPort _port;        protected HandlerBase _activeHandler; //set, control,         private object _lockerActiveHandler = new object();        private string _address;        private bool _isAsciiMode;        public int retryTime = 0;        public int MaxTryTime = 5;        private PeriodicJob _thread;        private object _locker = new object();        private LinkedList<string> _lstAsciiMsgs = new LinkedList<string>();        private LinkedList<byte[]> _lstBinsMsgs = new LinkedList<byte[]>();        private string _newLine;        public SerialPortConnectionBase(string port, int baudRate = 9600, int dataBits = 8, Parity parity = Parity.None, StopBits stopBits = StopBits.One, string newline = "\r", bool isAsciiMode = true)        {            _address = port;            _isAsciiMode = isAsciiMode;            _newLine = newline;            _port = new AsyncSerialPort(port, baudRate, dataBits, parity, stopBits, newline, isAsciiMode);            _port.OnDataChanged += _port_OnAsciiDataReceived;            _port.OnBinaryDataChanged += _port_OnBinaryDataChanged;            _port.OnErrorHappened += _port_OnErrorHappened;            _thread = new PeriodicJob(2, OnTimer, $"{port}.MonitorHandler", true);        }        private bool OnTimer()        {            lock (_locker)            {                if (_isAsciiMode)                {                    while (_lstAsciiMsgs.Count > 0)                    {                        string asciiMsg = _lstAsciiMsgs.First.Value;                        _port_HandleAsciiData(asciiMsg);                        _lstAsciiMsgs.RemoveFirst();                    }                }                else                {                    while (_lstBinsMsgs.Count > 0)                    {                        byte[] binMsg = _lstBinsMsgs.First.Value;                        _port_HandleBinarayData(binMsg);                        _lstBinsMsgs.RemoveFirst();                    }                }            }            return true;        }        public void SetPortAddress(string portName)        {            _port.PortName = portName;        }        private void _port_OnErrorHappened(string obj)        {            LOG.Error(obj);        }        public virtual bool SendMessage(string message)        {            if (_port != null && _port.IsOpen())                return _port.Write(message);            LOG.Error($"No connection writing message {message}");            return false;        }        public virtual bool SendMessage(byte[] message)        {            if (_port != null && _port.IsOpen())                return _port.Write(message);            LOG.Error($"No connection writing message {string.Join(" ", Array.ConvertAll(message, x => x.ToString("X2")))}");            return false;        }        public void ForceClear()        {            lock (_lockerActiveHandler)            {                IsCommunicationError = false;                _activeHandler = null;            }        }        public void Execute(HandlerBase handler)        {            if (_activeHandler != null)                return;            if (handler == null)                return;            if (_port.IsOpen())            {                lock (_lockerActiveHandler)                {                    retryTime = 0;                    _activeHandler = handler;                    _activeHandler.SetState(EnumHandlerState.Sent);                }                bool sendResult = _isAsciiMode ? SendMessage(handler.SendText) : SendMessage(handler.SendBinary);                if (!sendResult)                {                    lock (_lockerActiveHandler)                    {                        _activeHandler = null;                    }                }            }        }        protected virtual MessageBase ParseResponse(string rawMessage)        {            return null;        }        protected virtual MessageBase ParseResponse(byte[] rawMessage)        {            return null;        }        protected virtual void OnEventArrived(MessageBase msg)        {        }        protected virtual void ActiveHandlerProceedMessage(MessageBase msg)        {            lock (_lockerActiveHandler)            {                if (_activeHandler != null)                {                    if (msg.IsFormatError || (_activeHandler.HandleMessage(msg, out bool transactionComplete) && transactionComplete))                    {                        _activeHandler = null;                    }                }            }        }        public void EnableLog(bool enable)        {            _port.EnableLog = enable;        }        private void ProceedTransactionMessage(MessageBase msg)        {            if (msg == null || msg.IsFormatError)            {                SetCommunicationError(true, "received invalid response message.");                return;            }            if (msg.IsEvent)            {                OnEventArrived(msg);                //return;            }            //当前活动交互会话,继续执行            ActiveHandlerProceedMessage(msg);        }        private void _port_OnBinaryDataChanged(byte[] binaryData)        {            lock (_locker)            {                _lstBinsMsgs.AddLast(binaryData);            }        }        private void _port_HandleBinarayData(byte[] binaryData)        {            MessageBase msg = ParseResponse(binaryData);            ProceedTransactionMessage(msg);        }        private void _port_OnAsciiDataReceived(string oneLineMessage)        {            lock (_locker)            {                if (string.IsNullOrEmpty(_newLine))                {                    _lstAsciiMsgs.AddLast(oneLineMessage);                    if (_port.EnableLog)                        LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, oneLineMessage));                }                else                {                    foreach (var message in oneLineMessage.Split(_newLine.ToCharArray()))                    {                        if (!string.IsNullOrEmpty(message))                        {                            _lstAsciiMsgs.AddLast(message + _newLine);                            if (_port.EnableLog)                                LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, message + _newLine));                        }                    }                }            }        }        private void _port_HandleAsciiData(string oneLineMessage)        {            MessageBase msg = ParseResponse(oneLineMessage);            ProceedTransactionMessage(msg);        }        public HandlerBase MonitorTimeout()        {            HandlerBase result = null;            lock (_lockerActiveHandler)            {                if (_activeHandler != null && _activeHandler.CheckTimeout())                {                    if (retryTime < MaxTryTime)                    {                        retryTime += 1;                        Retry();                        return result;                    }                    string strSubfix = retryTime > 0 ? $"after retry {retryTime}" : string.Empty;                    EV.PostWarningLog("System", $"{Address} receive {_activeHandler.Name} timeout {strSubfix}");                    result = _activeHandler;                    _activeHandler = null;                    SetCommunicationError(true, "receive response timeout");                    //}                }            }            return result;        }        public void Retry()        {            if (_activeHandler == null)                return;            if (_port.IsOpen())            {                //_activeHandler = handler;                _activeHandler.SetState(EnumHandlerState.Sent);                bool sendResult = _isAsciiMode ? SendMessage(_activeHandler.SendText) : SendMessage(_activeHandler.SendBinary);                if (_isAsciiMode)                {                    if (_port.EnableLog)                        LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, _activeHandler.SendText));                }                else                {                    if (_port.EnableLog)                        LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, string.Join(" ", Array.ConvertAll(_activeHandler.SendBinary, x => x.ToString("X2")))));                }                if (!sendResult) _activeHandler = null;            }        }        public void SetCommunicationError(bool isError, string reason)        {            IsCommunicationError = isError;            LastCommunicationError = reason;        }    }    public abstract class TCPPortConnectionBase : IConnection    {        public string Address        {            get { return _address; }        }        public bool IsConnected        {            get { return _socket.IsConnected; }        }        public bool Connect()        {            _socket.Connect();            int iCount = 0;            while (!IsConnected && iCount < 25)            {                Thread.Sleep(200);                iCount++;            }            if (IsConnected)            {                return true;            }            else            {                Disconnect();                return false;            }        }        public bool Disconnect()        {            _socket.Dispose();            return true;        }        public bool IsBusy        {            get { return _activeHandler != null; }        }        public HandlerBase ActiveHandler => _activeHandler;        public bool IsCommunicationError { get; private set; }        public string LastCommunicationError { get; private set; }        private AsynSocketClient _socket;        protected HandlerBase _activeHandler; //set, control,         public HandlerBase HandlerInError;        protected object _lockerActiveHandler = new object();        private string _address;        private bool _isAsciiMode;        public int retryTime = 0;        public int MaxTryTime = 1;        private PeriodicJob _thread;        private object _locker = new object();        private LinkedList<string> _lstAsciiMsgs = new LinkedList<string>();        private LinkedList<byte[]> _lstBinsMsgs = new LinkedList<byte[]>();        private string _newLine;        public TCPPortConnectionBase(string address, string newline = "\r", bool isAsciiMode = true, ProtocolType protocolType= ProtocolType.Tcp)        {            _address = address;            _newLine = newline;            _isAsciiMode = isAsciiMode;            _socket = new AsynSocketClient(address, isAsciiMode, newline, protocolType);            _socket.OnDataChanged += _port_OnAsciiDataReceived;            _socket.OnBinaryDataChanged += _port_OnBinaryDataChanged;            _socket.OnErrorHappened += _port_OnErrorHappened;            _thread = new PeriodicJob(1, OnTimer, $"{address}.MonitorHandler", true);        }        private bool OnTimer()        {            lock (_locker)            {                if (_isAsciiMode)                {                    while (_lstAsciiMsgs.Count > 0)                    {                        string asciiMsg = _lstAsciiMsgs.First.Value;                        if (!string.IsNullOrEmpty(asciiMsg))                        {                            if (_socket.NeedLog)                            {                                LOG.Write($"Start handler message:{asciiMsg}");                            }                            _port_HandleAsciiData(asciiMsg);                        }                        _lstAsciiMsgs.RemoveFirst();                    }                }                else                {                    while (_lstBinsMsgs.Count > 0)                    {                        byte[] binMsg = _lstBinsMsgs.First.Value;                        _port_HandleBinarayData(binMsg);                        _lstBinsMsgs.RemoveFirst();                    }                }            }            return true;        }        //public void SetPortAddress(string portName)        //{        //    _port.PortName = portName;        //}        private void _port_OnErrorHappened(TCPErrorEventArgs obj)        {            LOG.Error(obj.Reason);        }        public virtual bool SendMessage(string message)        {            if (_socket != null && _socket.IsConnected)                return _socket.Write(message);            LOG.Error($"No connection writing message {message}");            return false;        }        public virtual bool SendMessage(byte[] message)        {            if (_socket != null && _socket.IsConnected)                return _socket.Write(message);            LOG.Error($"No connection writing message {string.Join(" ", Array.ConvertAll(message, x => x.ToString("X2")))}");            return false;        }        public void ForceClear()        {            lock (_lockerActiveHandler)            {                _activeHandler = null;                IsCommunicationError = false;            }        }        public void Execute(HandlerBase handler)        {            if (_activeHandler != null)                return;            if (handler == null)                return;            if (_socket.IsConnected)            {                lock (_lockerActiveHandler)                {                    retryTime = 0;                    _activeHandler = handler;                    _activeHandler.SetState(EnumHandlerState.Sent);                }                bool sendResult = _isAsciiMode ? SendMessage(handler.SendText) : SendMessage(handler.SendBinary);                if (!sendResult)                {                    lock (_lockerActiveHandler)                    {                        _activeHandler = null;                    }                }            }        }        protected virtual MessageBase ParseResponse(string rawMessage)        {            return null;        }        protected virtual MessageBase ParseResponse(byte[] rawMessage)        {            return null;        }        protected virtual void OnEventArrived(MessageBase msg)        {        }        protected virtual void ActiveHandlerProceedMessage(MessageBase msg)        {            lock (_lockerActiveHandler)            {                if (_activeHandler != null)                {                    if (msg.IsFormatError || (_activeHandler.HandleMessage(msg, out bool transactionComplete) && transactionComplete))                    {                        _activeHandler = null;                    }                }            }        }        public void EnableLog(bool enable)        {            _socket.NeedLog = enable;        }        private void ProceedTransactionMessage(MessageBase msg)        {            if (msg == null || msg.IsFormatError)            {                SetCommunicationError(true, "received invalid response message.");                return;            }            if (msg.IsEvent)            {                OnEventArrived(msg);                //return;            }            //当前活动交互会话,继续执行            ActiveHandlerProceedMessage(msg);        }        private void _port_OnBinaryDataChanged(byte[] binaryData)        {            lock (_locker)            {                _lstBinsMsgs.AddLast(binaryData);            }        }        private void _port_HandleBinarayData(byte[] binaryData)        {            MessageBase msg = ParseResponse(binaryData);            ProceedTransactionMessage(msg);        }        private void _port_OnAsciiDataReceived(string oneLineMessage)        {            lock (_locker)            {                if (string.IsNullOrEmpty(_newLine))                {                    _lstAsciiMsgs.AddLast(oneLineMessage);                }                else                {                    foreach (var message in oneLineMessage.Split(_newLine.ToCharArray()))                    {                        if (!string.IsNullOrEmpty(message))                            _lstAsciiMsgs.AddLast(message + _newLine);                    }                }            }            //lock (_locker)            //{            //    _lstAsciiMsgs.AddLast(oneLineMessage);            //}        }        private void _port_HandleAsciiData(string oneLineMessage)        {            MessageBase msg = ParseResponse(oneLineMessage);            ProceedTransactionMessage(msg);        }        public HandlerBase MonitorTimeout()        {            HandlerBase result = null;            lock (_lockerActiveHandler)            {                if (_activeHandler != null && _activeHandler.CheckTimeout())                {                    if (retryTime < MaxTryTime)                    {                        retryTime += 1;                        EV.PostWarningLog("System", $"{Address} receive {_activeHandler.Name} timeout in {retryTime} times");                        Retry();                        return result;                    }                    string strSubfix = retryTime > 0 ? $"after retry {retryTime}" : string.Empty;                    EV.PostWarningLog("System", $"{Address} receive {_activeHandler.Name} timeout {strSubfix}");                    result = _activeHandler;                    HandlerInError = _activeHandler;                    _activeHandler = null;                    SetCommunicationError(true, "receive response timeout");                    //}                }            }            return result;        }        public void Retry()        {            if (_activeHandler == null)                return;            if (_socket.IsConnected)            {                //_activeHandler = handler;                _activeHandler.SetState(EnumHandlerState.Sent);                bool sendResult = _isAsciiMode ? SendMessage(_activeHandler.SendText) : SendMessage(_activeHandler.SendBinary);                if (!sendResult) _activeHandler = null;            }        }        public void SetCommunicationError(bool isError, string reason)        {            IsCommunicationError = isError;            LastCommunicationError = reason;        }    }}
 |