From 1c4426810c71eead57084be8a18ade8d314dd8c4 Mon Sep 17 00:00:00 2001
From: patrick <patrick.xu@broconcentric.com>
Date: 星期二, 10 十二月 2019 14:24:31 +0800
Subject: [PATCH] 1. 重构项目

---
 src/Bro.Device.AuboRobot/AuboRobotDriver.cs |  369 +++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 276 insertions(+), 93 deletions(-)

diff --git a/src/Bro.Device.AuboRobot/AuboRobotDriver.cs b/src/Bro.Device.AuboRobot/AuboRobotDriver.cs
index 11f343f..54a3600 100644
--- a/src/Bro.Device.AuboRobot/AuboRobotDriver.cs
+++ b/src/Bro.Device.AuboRobot/AuboRobotDriver.cs
@@ -10,6 +10,7 @@
 using System.Net.Sockets;
 using System.Threading;
 using System.Threading.Tasks;
+using static Bro.Common.Helper.EnumHelper;
 
 namespace Bro.Device.AuboRobot
 {
@@ -38,7 +39,7 @@
 
             if (string.IsNullOrWhiteSpace(IConfig.EndChar))
             {
-                throw new ProcessException("鍗忚鏂囨湰鐨勭粨鏉熷瓧绗︿笉鍙负绌猴紝璇锋鏌ラ厤缃�", null);
+                throw new ProcessException("鍗忚鏂囨湰鐨勭粨鏉熷瓧绗︿笉鍙负绌猴紝璇锋鏌ラ厤缃�");
             }
 
             client = new TcpClient();
@@ -46,6 +47,10 @@
             client.Client.Blocking = true;
             client.NoDelay = true;
             client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null);
+
+            replyHandleDict = new Dictionary<int, AutoResetEvent>();
+            replyErrorCodeDict = new Dictionary<int, int>();
+            taskHandleDict = new Dictionary<int, ManualResetEvent>();
         }
 
         protected override void Pause()
@@ -63,8 +68,7 @@
             //SendMsg(RobotMsgType.Send, 0, true, RobotMsgAction.IO, RobotMsgParas.Query, new List<string>());
 
             scanMsg = new RobotMsg();
-            scanMsg.Action = RobotMsgAction.IO;
-            scanMsg.Para1 = RobotMsgParas.Query;
+            scanMsg.Action = RobotMsgAction.IOQuery;
 
             Task.Run(() =>
             {
@@ -74,6 +78,12 @@
 
         protected override void Stop()
         {
+            replyHandleDict.Values.ToList().ForEach(h => h.Set());
+            replyHandleDict.Clear();
+
+            taskHandleDict.Values.ToList().ForEach(h => h.Set());
+            taskHandleDict.Clear();
+
             if (client != null && client.Connected)
             {
                 client.Close();
@@ -95,7 +105,8 @@
             }
             catch (Exception ex)
             {
-                OnLog?.Invoke(DateTime.Now, this, ex.GetExceptionMessage());
+                //OnLog?.Invoke(DateTime.Now, this, ex.GetExceptionMessage());
+                LogAsync(DateTime.Now, "杩炴帴寮傚父", ex.GetExceptionMessage());
 
                 if (client != null && client.Connected)
                 {
@@ -110,13 +121,12 @@
             try
             {
                 int dataLength = stream.EndRead(ar);
-
                 if (dataLength > 0)
                 {
                     byte[] data = buffer.Take(dataLength).ToArray();
 
                     string dataStr = System.Text.Encoding.ASCII.GetString(data).Trim();
-                    //OnLog?.BeginInvoke(DateTime.Now, this, $"{Name}鎺ユ敹鏁版嵁锛歿dataStr}", null, null);
+
                     AnalyzeData(dataStr);
 
                     stream.BeginRead(buffer, 0, buffer.Length, OnDataReceived, null);
@@ -125,19 +135,21 @@
                 {
                     if (!client.Connected)
                     {
-                        OnLog?.Invoke(DateTime.Now, this, "杩斿洖绌烘暟鎹紝杩炴帴涓柇");
+                        //OnLog?.Invoke(DateTime.Now, this, "杩斿洖绌烘暟鎹紝杩炴帴涓柇");
+                        LogAsync(DateTime.Now, "杩炴帴涓柇", "杩斿洖绌烘暟鎹紝杩炴帴涓柇");
                         client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null);
                     }
                 }
             }
             catch (Exception ex)
             {
-                OnLog?.Invoke(DateTime.Now, this, $"{Name}鏁版嵁鎺ユ敹寮傚父锛歿ex.GetExceptionMessage()}");
+                //OnLog?.Invoke(DateTime.Now, this, $"{Name}锛歿ex.GetExceptionMessage()}");
+                LogAsync(DateTime.Now, "鏁版嵁鎺ユ敹寮傚父", ex.GetExceptionMessage());
             }
         }
 
         string msg = "";
-        static object analyzeLock = new object();
+        object analyzeLock = new object();
         private async void AnalyzeData(string data)
         {
             await Task.Run(() =>
@@ -168,41 +180,58 @@
             await Task.Run(() =>
             {
                 Array.ForEach(datas, data =>
-                 {
-                     RobotMsg msg = RobotMsg.GetRobotMsg(data, IConfig.Seperator);
+                {
+                    RobotMsg msg = RobotMsg.GetRobotMsg(data, IConfig.Seperator);
 
-                     if (msg.Type == RobotMsgType.Rec)
-                     {
-                         if (replyHandleDict.ContainsKey(msg.ID))
-                         {
-                             replyHandleList.Remove(msg.ID);
+                    if (msg.Type == RobotMsgType.Rec)
+                    {
+                        replyErrorCodeDict[msg.ID] = msg.Para1;
+                        if (replyHandleDict.ContainsKey(msg.ID))
+                        {
+                            replyHandleDict[msg.ID].Set();
+                        }
+                    }
+                    else
+                    {
+                        if (msg.Action == RobotMsgAction.IOQuery)
+                        {
+                            newValues = new List<int>();
 
-                             replyHandleDict[msg.ID].Set();
-                             replyHandleDict.Remove(msg.ID);
-                         }
-                     }
-                     else
-                     {
-                         canMonitor = true;
+                            for (int i = msg.Para1.ToString().Length - 1; i >= 0; i--)
+                            {
+                                newValues.Add((msg.Para1 >> i) & 1);
+                            }
 
-                         if (msg.Action == RobotMsgAction.IO && msg.Para1 == RobotMsgParas.Query)
-                         {
-                             string resultStr = msg.Datas[0];
-                             newValues = new List<int>();
+                            MonitorHandle.Set();
+                        }
+                        else
+                        {
+                            canMonitor = true;
+                            switch (msg.Action)
+                            {
+                                case RobotMsgAction.Move:
+                                    CurrentPoint = msg.Point;
+                                    break;
+                                //case RobotMsgAction.Load:
+                                //    //SlotIndex = msg.Para1;
+                                //    break;
+                                case RobotMsgAction.GetPosition:
+                                    CurrentPoint = msg.Point;
+                                    break;
+                                default:
+                                    break;
+                            }
 
-                             for (int i = resultStr.Length - 1; i >= 0; i--)
-                             {
-                                 newValues.Add(int.Parse(resultStr[i].ToString()));
-                             }
+                            if (taskHandleDict.ContainsKey(msg.ID))
+                            {
+                                taskHandleDict[msg.ID].Set();
+                            }
 
-                             MonitorHandle.Set();
-                         }
-                         else
-                         {
-                             OnMsgReceived?.BeginInvoke(DateTime.Now, this, msg, null, null);
-                         }
-                     }
-                 });
+                            LogAsync(DateTime.Now, "鎸囦护鍙嶉", msg.GetDisplayText());
+                            OnMsgReceived?.BeginInvoke(DateTime.Now, this, msg, null, null);
+                        }
+                    }
+                });
             });
         }
 
@@ -220,24 +249,9 @@
             }
         }
 
-        List<int> replyHandleList = new List<int>();
         Dictionary<int, AutoResetEvent> replyHandleDict = new Dictionary<int, AutoResetEvent>();
-
-        public void SendMsg(RobotMsgAction action, RobotMsgParas para1, int para2, List<float> paras = null)
-        {
-            RobotMsg msg = new RobotMsg();
-            msg.Type = RobotMsgType.Send;
-            msg.ID = SID;
-
-            msg.Action = action;
-            msg.Para1 = para1;
-            msg.Para2 = para2;
-
-            msg.Datas = new List<string>((paras ?? new List<float>()).ConvertAll(i => i.ToString()));
-
-            OnLog?.BeginInvoke(DateTime.Now, this, $"{Name}鍙戦�佹寚浠わ細{msg.GetDisplayText()}", null, null);
-            SendMsg(msg, true);
-        }
+        Dictionary<int, int> replyErrorCodeDict = new Dictionary<int, int>();
+        Dictionary<int, ManualResetEvent> taskHandleDict = new Dictionary<int, ManualResetEvent>();
 
         public void SendReplyMsg(int replyId)
         {
@@ -253,37 +267,183 @@
         object monitorLock = new object();
         public void SendMsg(RobotMsg msg, bool isWaitReply = true, bool isMonitorMsg = false)
         {
+            replyErrorCodeDict[msg.ID] = 0;
+
             if (isWaitReply)
             {
-                replyHandleList.Add(msg.ID);
                 replyHandleDict[msg.ID] = new AutoResetEvent(false);
             }
 
-            byte[] bytes = msg.GetMsgBytes(IConfig.Seperator, IConfig.EndChar);
-
-            lock (monitorLock)
+            byte[] bytes = msg.GetMsgBytes(IConfig.Seperator, IConfig.EndChar, out string dataStr);
+            if (!isMonitorMsg)
             {
-                if (!isMonitorMsg)
-                {
-                    canMonitor = false;
-                }
-
-                if (isMonitorMsg && !canMonitor)
-                    return;
-
-                //lock (this)
-                {
-                    stream.Write(bytes, 0, bytes.Length);
-                }
+                LogAsync(DateTime.Now, "鎸囦护鍙戦��", dataStr);
             }
+
+            bool isNotTimeout = true;
+            int reTryTime = IConfig.TimeoutRetryTimes;
+            do
+            {
+                lock (monitorLock)
+                {
+                    if (!isMonitorMsg)
+                    {
+                        canMonitor = false;
+                    }
+
+                    if (isMonitorMsg && !canMonitor)
+                        return;
+
+                    stream.Write(bytes, 0, bytes.Length);
+
+                    if (!isMonitorMsg)
+                    {
+                        LogAsync(DateTime.Now, "鏁版嵁鍙戦��", BitConverter.ToString(bytes));
+                    }
+                }
+
+                if (isWaitReply)
+                {
+                    int errorCode = replyErrorCodeDict[msg.ID];
+
+                    if (errorCode != 0)
+                    {
+                        var desc = IConfig.RobotReplyWarnings.FirstOrDefault(u => u.WarningCode == errorCode);
+                        throw new ProcessException($"{Name}{msg.ID}浠诲姟鍙嶉寮傚父{errorCode},寮傚父鎻忚堪锛歿(desc == null ? "鏃�" : desc.WarningDescription)}");
+                    }
+
+                    isNotTimeout = replyHandleDict[msg.ID].WaitOne(IConfig.ReplyTimeout);
+
+                    if (!isNotTimeout)
+                    {
+                        reTryTime--;
+                    }
+                }
+            } while (reTryTime > 0 && !isNotTimeout);
 
             if (isWaitReply)
             {
-                replyHandleDict[msg.ID].WaitOne(IConfig.ReplyTimeout);
+                replyHandleDict.Remove(msg.ID);
+            }
 
-                if (replyHandleList.Contains(msg.ID))
+            if (!isNotTimeout)
+            {
+                throw new ProcessException($"{Name}鍙嶉鏁版嵁瓒呮椂\r\n" + msg.GetDisplayText());
+            }
+        }
+
+        #region 鎵ц缁撴灉灞炴��
+        public RobotPoint CurrentPoint { get; set; } = null;
+        //public int SlotIndex { get; set; } = 0;
+        #endregion
+
+        public void Move(RobotPoint point, MoveType isAbs, bool isWaitFinished)
+        {
+            CurrentPoint = null;
+
+            RobotMsg msg = new RobotMsg();
+            msg.Type = RobotMsgType.Send;
+            msg.ID = SID;
+
+            msg.Action = RobotMsgAction.Move;
+            msg.Para1 = (int)isAbs;
+
+            msg.Point = point ?? new RobotPoint();
+
+            SendMsg(msg, true);
+
+            TaskTimeoutCheck(isWaitFinished, msg.ID, $"{Name}{(isAbs.GetEnumDescription())}鑷硔point.GetDisplayText()}鍔ㄤ綔瓒呮椂");
+        }
+
+        public void Load(RobotPoint point, TrayType trayType, bool isWaitFinished)
+        {
+            //SlotIndex = 0;
+
+            RobotMsg msg = new RobotMsg();
+            msg.Type = RobotMsgType.Send;
+            msg.ID = SID;
+
+            msg.Action = RobotMsgAction.Load;
+            msg.Para1 = (int)trayType;
+            msg.Point = point;
+
+            SendMsg(msg, true);
+
+            TaskTimeoutCheck(isWaitFinished, msg.ID, $"{Name}鍙杮trayType.ToString()}{point.GetDisplayText()}鍔ㄤ綔瓒呮椂");
+
+            //if (isWaitFinished && SlotIndex <= 0)
+            //{
+            //    throw new ProcessException($"{Name}娌℃湁鍙敤鐨勭┖鐧芥牸浣�,鏃犳硶鏀剧疆鍗峰畻");
+            //}
+        }
+
+        public void UnLoad(RobotPoint point, TrayType trayType, bool isWaitFinished)
+        {
+            RobotMsg msg = new RobotMsg();
+            msg.Type = RobotMsgType.Send;
+            msg.ID = SID;
+
+            msg.Action = RobotMsgAction.Unload;
+            msg.Para1 = (int)trayType;
+            msg.Point = point;
+
+            SendMsg(msg, true);
+
+            TaskTimeoutCheck(isWaitFinished, msg.ID, $"{Name}鍗竰trayType.ToString()}{point.GetDisplayText()}鍔ㄤ綔瓒呮椂");
+        }
+
+        public void GetPosition(bool isWaitFinished)
+        {
+            CurrentPoint = null;
+
+            RobotMsg msg = new RobotMsg();
+            msg.Type = RobotMsgType.Send;
+            msg.ID = SID;
+
+            msg.Action = RobotMsgAction.GetPosition;
+
+            SendMsg(msg, true);
+
+            TaskTimeoutCheck(isWaitFinished, msg.ID, $"{Name}鑾峰彇褰撳墠鍧愭爣瓒呮椂");
+        }
+
+        public void SetBasePoint()
+        {
+            RobotMsg msg = new RobotMsg();
+            msg.Type = RobotMsgType.Send;
+            msg.ID = SID;
+
+            msg.Action = RobotMsgAction.BasePoint;
+
+            SendMsg(msg, true);
+        }
+
+        public void SetIO(int outputIndex, bool isOn)
+        {
+            RobotMsg msg = new RobotMsg();
+            msg.Type = RobotMsgType.Send;
+            msg.ID = SID;
+
+            msg.Action = RobotMsgAction.IOSet;
+            msg.Para1 = outputIndex;
+            msg.Para2 = isOn ? 1 : 0;
+
+            SendMsg(msg, true);
+        }
+
+        private void TaskTimeoutCheck(bool isWaitFinished, int msgId, string errorMsg)
+        {
+            if (isWaitFinished)
+            {
+                taskHandleDict[msgId] = new ManualResetEvent(false);
+                taskHandleDict[msgId].Reset();
+                bool isNotTimeout = taskHandleDict[msgId].WaitOne((int)(IConfig.OperationTimeout * 60 * 1000));
+
+                taskHandleDict.Remove(msgId);
+
+                if (!isNotTimeout)
                 {
-                    throw new ProcessException("鍙嶉鏁版嵁瓒呮椂\r\n" + msg.GetDisplayText(), null);
+                    throw new ProcessException(errorMsg);
                 }
             }
         }
@@ -295,14 +455,16 @@
         protected List<int> oldValues = new List<int>();
         List<int> newValues = new List<int>();
         public ManualResetEvent MonitorHandle { get; set; } = new ManualResetEvent(false);
-        //public ManualResetEvent IOChangedHandle { get; set; } = new ManualResetEvent(true);
-        public List<int> GetMonitorValues(int startAddress, int length)
+        public List<int> GetIOValues()
         {
             MonitorHandle.Reset();
             scanMsg.ID = SID;
             SendMsg(scanMsg, true, true);
 
-            MonitorHandle.WaitOne(IConfig.ReplyTimeout);
+            var isNotTimeout = MonitorHandle.WaitOne(IConfig.ReplyTimeout * 3);
+
+            if (!isNotTimeout)
+                throw new ProcessException($"{Name}鐩戝惉鎿嶄綔瓒呮椂");
 
             return newValues;
         }
@@ -313,35 +475,51 @@
             {
                 try
                 {
-                    List<int> newValues = GetMonitorValues(0, 0);
-
-                    if (newValues == null || newValues.Count == 0)
-                        continue;
-
-                    if (oldValues.Count == 0)
+                    if (IConfig.IsEnableMonitor)
                     {
-                        oldValues = newValues.ConvertAll(s => -1).ToList();
-                    }
+                        List<int> newValues = GetIOValues();
 
-                    if (oldValues.Count == newValues.Count)
-                    {
-                        var tempNew = new List<int>(newValues);
-                        var tempOld = new List<int>(oldValues);
-                        MonitorCheckAndInvoke(tempNew, tempOld);
+                        if (newValues == null || newValues.Count == 0)
+                            continue;
+
+                        if (oldValues.Count == 0)
+                        {
+                            oldValues = newValues.ConvertAll(s => -1).ToList();
+                        }
+
+                        if (oldValues.Count == newValues.Count)
+                        {
+                            var tempNew = new List<int>(newValues);
+                            var tempOld = new List<int>(oldValues);
+                            MonitorCheckAndInvoke(tempNew, tempOld);
+                        }
+                        oldValues = new List<int>(newValues);
                     }
-                    oldValues = new List<int>(newValues);
 
                     Thread.Sleep(IConfig.ScanInterval);
                 }
                 catch (Exception ex)
                 {
-                    OnLog?.Invoke(DateTime.Now, this, $"{Name}鐩戝惉寮傚父:{ex.GetExceptionMessage()}");
+                    LogAsync(DateTime.Now, "鐩戝惉寮傚父", ex.GetExceptionMessage());
                 }
             }
         }
 
         protected virtual void MonitorCheckAndInvoke(List<int> tempNew, List<int> tempOld)
         {
+            IConfig.WarningSetCollection.ForEach(w =>
+            {
+                if (w.WarningIndex_Word < 0 || w.WarningIndex_Word >= tempNew.Count)
+                    return;
+
+                bool isOn = tempNew[w.WarningIndex_Word] == 1;
+                if (w.CurrentStatus != isOn)
+                {
+                    w.CurrentStatus = isOn;
+                    OnMonitorAlarm?.BeginInvoke(DateTime.Now, this, w, null, null);
+                }
+            });
+
             IConfig.MonitorSetCollection.ForEach(m =>
             {
                 if (m.TriggerIndex < 0 || m.TriggerIndex >= tempNew.Count)
@@ -371,6 +549,11 @@
                 }
             });
         }
+
+        public virtual void ResetAlarm()
+        {
+            IConfig.WarningSetCollection.ForEach(u => u.CurrentStatus = !u.TriggerValue);
+        }
         #endregion
     }
 }

--
Gitblit v1.8.0