WistonAgvClientcs.cs 9.3 KB
using log4net;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Timers;

namespace DeviceLibrary
{
    public class WistonAgvClient
    {
        Socket client;
        IPEndPoint ipe;
        Timer timer;
        static readonly ILog LOGGER = LogManager.GetLogger("WistonAgvClient");
        object conn = new object();
        Dictionary<string, bool> commandConfirm;
        List<(DateTime, string)> OutCommandHistroy;
        List<(DateTime, string)> InCommandHistroy;
        public WistonAgvClient()
        {
            ConfigHelper.Config.Get("wiston_disable_agv_NeedEnter", false);
            commandLoad();
            //端口及IP
            ipe = new IPEndPoint(IPAddress.Parse(ConfigHelper.Config.Get("WistonAgvServerIP")), ConfigHelper.Config.Get<int>("WistonAgvServerPort"));
            log(ipe.ToString());
            timer = new Timer(10000);
            timer.Elapsed += Timer_Elapsed;
            timer.AutoReset = true;
            connect();
            timer.Start();
        }
        void commandLoad() {
            commandConfirm = new Dictionary<string, bool>();
            commandConfirm.Add("Y1", true);
            commandConfirm.Add("Y2", true);
            commandConfirm.Add("Y5", true);
            commandConfirm.Add("Y6", true);
        }
        DateTime lastnoopRequest = DateTime.MinValue;
        DateTime lastnoopResponse = DateTime.MaxValue;
        int waitTimes = 0;
        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (client != null && client.Connected)
            {
                return;
                if (waitTimes > 5) {
                    try
                    {
                        log($"服务器心跳包超时,超过次数,断开连接,稍后重新连接");
                        client.Close();
                    }
                    catch { }
                    return;
                }

                if (lastnoopRequest != DateTime.MinValue)
                {
                    var s = lastnoopResponse - lastnoopRequest;
                    if (s.TotalSeconds < -5)
                    {
                        waitTimes++;
                        log($"服务器心跳包超时,times:{waitTimes}");
                    }
                    else
                    {
                        waitTimes = 0;
                    }
                }
                lastnoopRequest = DateTime.Now;
                AsynSend("noop");
            }
            else if (client != null && !client.Connected)
            {                
                connect();
            }
        }
        void CloseConnect() {
            if (client != null)
            {
                if (client.Connected)
                    client.Close();
                //client.Dispose();
                //client = null;
            }
        }
        void connect() {
            lock (conn)
            {
                if (client != null && client.Connected)
                {
                    return;
                }
                //创建套接字
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //开始连接到服务器
                client.BeginConnect(ipe, asyncResult =>
                {
                    if (!client.Connected)
                    {
                        log("连接失败,稍后后再次连接");
                        //Task.Delay(10000).Wait();
                        CloseConnect();
                        return;
                    }
                    client.EndConnect(asyncResult);

                    //向服务器发送消息
                    //AsynSend("noop");
                    log("服务器连接成功");
                    //接受消息
                    AsynRecive(client);

                }, null);
            }
        }
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="message"></param>
        public void AsynSend(string message)
        {
            if (client == null || message == string.Empty) return;

            //编码
            byte[] data = Encoding.UTF8.GetBytes(message);
            try
            {
                client.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
                {
                    try
                    {
                        if (!client.Connected)
                        {
                            log("连接失败,等待5秒后再次连接");
                            //Task.Delay(5000).Wait();
                            CloseConnect();
                            return;
                        }
                        //完成发送消息
                        int length = client.EndSend(asyncResult);
                        log(string.Format("客户端发送消息:{0}", message));
                    }
                    catch { }
                }, null);
            }
            catch (Exception ex)
            {
                log(string.Format("异常信息:{0}", ex.Message));
            }
        }


        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="socket"></param>
        void AsynRecive(Socket socket)
        {
            byte[] data = new byte[1024];
            try
            {
                //开始接收数据
                socket.BeginReceive(data, 0, data.Length, SocketFlags.None,
                asyncResult =>
                {
                    try
                    {
                        if (!socket.Connected)
                        {
                            CloseConnect();
                            log("连接断开了,稍后再次连接,AsynRecive");
                            return;
                        }
                        int length = socket.EndReceive(asyncResult);
                        var msg = Encoding.UTF8.GetString(data, 0, length);
                        MsgProcess(msg);
                        log(string.Format("收到服务器消息:{0}", msg));
                        AsynRecive(socket);
                    }
                    catch (Exception ex)
                    {
                        log(string.Format("异常信息:{0}", ex.Message));
                        CloseConnect();
                        log("连接断开了,稍后再次连接,AsynRecive");
                    }
                }, null);
            }
            catch (Exception ex)
            {
                log(string.Format("异常信息:{0}", ex.Message));
            }

        }
        public event EventHandler EmptyShelfInReady;
        public event EventHandler FullShelfOutReady;
        void MsgProcess(string msg)
        {
            msg = msg.Trim();
            if (msg.Contains("noop"))
            {
                lastnoopResponse = DateTime.Now;
            }
            else if (msg.Contains("X1"))
            {
                AsynSend("X1");
                EmptyShelfInReady?.Invoke(this, EventArgs.Empty);
            }
            else if (msg.Contains("X5"))
            {
                AsynSend("X5");
                FullShelfOutReady?.Invoke(this, EventArgs.Empty);
            }
            else if (msg.StartsWith("Y"))
            {
                var command = msg.Substring(0, 2);
                if (commandConfirm.ContainsKey(command)) {
                    commandConfirm[command] = true;
                }
            }
        }
        public void NeedEnter() {
            SendCommand("Y1");
        }
        public void FinishEnter()
        {
            SendCommand("Y2");
        }
        public void NeedLeave()
        {
            SendCommand("Y5");
        }
        public void FinishLeave()
        {
            SendCommand("Y6");
        }
        Task SendCommand(string cmd) {
            return Task.Run(new Action(() =>
                {
                    if (!commandConfirm[cmd])
                    {
                        log($"指令{cmd}正在执行中.");
                        return;
                    }

                    AsynSend(cmd);
                    commandConfirm[cmd] = false;
                    int retry = 0;
                    Task.Delay(5000).Wait();
                    while (!commandConfirm[cmd] && retry<5) {
                        retry++;
                        AsynSend(cmd);
                        log($"指令:{cmd}发送失败,重试:{retry}");
                        Task.Delay(5000);
                    }
                    if (commandConfirm[cmd]) {
                        log($"指令:{cmd}发送成功.");
                    }
                    else
                    {
                        commandConfirm[cmd] = true;
                        log($"指令:{cmd}发送失败,停止重试.");
                    }
                }
                ));
        }
        void log(string msg) {
            LOGGER.Info(msg);
            Console.WriteLine(msg);
        }
        void AddOutCommandHistroy(string cmd) {
            OutCommandHistroy.Add((DateTime.Now, cmd));
            if (OutCommandHistroy.Count>10)
                OutCommandHistroy.RemoveAt(0);
        }
    }
}