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 |  464 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 401 insertions(+), 63 deletions(-)

diff --git a/src/Bro.Device.AuboRobot/AuboRobotDriver.cs b/src/Bro.Device.AuboRobot/AuboRobotDriver.cs
index 26e7324..54a3600 100644
--- a/src/Bro.Device.AuboRobot/AuboRobotDriver.cs
+++ b/src/Bro.Device.AuboRobot/AuboRobotDriver.cs
@@ -1,6 +1,8 @@
 锘縰sing Bro.Common.Base;
 using Bro.Common.Helper;
 using Bro.Common.Interface;
+using Bro.Common.Model;
+using Bro.Common.Model.Interface;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -8,13 +10,14 @@
 using System.Net.Sockets;
 using System.Threading;
 using System.Threading.Tasks;
+using static Bro.Common.Helper.EnumHelper;
 
 namespace Bro.Device.AuboRobot
 {
     [Device("AuboRobot", "濂ュ崥鏈哄櫒浜�", EnumHelper.DeviceAttributeType.Device)]
-    public class AuboRobotDriver : DeviceBase
+    public class AuboRobotDriver : DeviceBase, IMonitor
     {
-        public Action<RobotMsg> OnMsgReceived { get; set; }
+        public Action<DateTime, AuboRobotDriver, RobotMsg> OnMsgReceived { get; set; }
 
         AuboRobotInitialConfig IConfig
         {
@@ -32,9 +35,11 @@
 
         protected override void Init()
         {
+            oldValues = new List<int>();
+
             if (string.IsNullOrWhiteSpace(IConfig.EndChar))
             {
-                throw new ProcessException("鍗忚鏂囨湰鐨勭粨鏉熷瓧绗︿笉鍙负绌猴紝璇锋鏌ラ厤缃�", null);
+                throw new ProcessException("鍗忚鏂囨湰鐨勭粨鏉熷瓧绗︿笉鍙负绌猴紝璇锋鏌ラ厤缃�");
             }
 
             client = new TcpClient();
@@ -42,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()
@@ -52,19 +61,38 @@
         {
         }
 
+        RobotMsg scanMsg = new RobotMsg();
         protected override void Start()
         {
             //Query Robot IOs
             //SendMsg(RobotMsgType.Send, 0, true, RobotMsgAction.IO, RobotMsgParas.Query, new List<string>());
+
+            scanMsg = new RobotMsg();
+            scanMsg.Action = RobotMsgAction.IOQuery;
+
+            Task.Run(() =>
+            {
+                Monitor();
+            });
         }
 
         protected override void Stop()
         {
-            client.Close();
+            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();
+            }
         }
         #endregion
 
         TcpClient client = new TcpClient();
+        NetworkStream stream = null;
         byte[] buffer = new byte[1024];
 
         private void OnConnect(IAsyncResult ar)
@@ -72,41 +100,56 @@
             try
             {
                 client.EndConnect(ar);
-                client.GetStream().BeginRead(buffer, 0, buffer.Length, OnDateReceived, null);
+                stream = client.GetStream();
+                stream.BeginRead(buffer, 0, buffer.Length, OnDataReceived, null);
             }
             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)
+                {
+                    client.Close();
+                }
                 client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null);
             }
         }
 
-        private void OnDateReceived(IAsyncResult ar)
+        private void OnDataReceived(IAsyncResult ar)
         {
-            int dataLength = client.GetStream().EndRead(ar);
-
-            if (dataLength > 0)
+            try
             {
-                byte[] data = buffer.Take(dataLength).ToArray();
-
-                string dataStr = System.Text.Encoding.ASCII.GetString(data).Trim();
-                AnalyzeData(dataStr);
-
-                client.GetStream().BeginRead(buffer, 0, buffer.Length, OnDateReceived, null);
-            }
-            else
-            {
-                if (!client.Connected)
+                int dataLength = stream.EndRead(ar);
+                if (dataLength > 0)
                 {
-                    OnLog?.Invoke(DateTime.Now, this, "杩斿洖绌烘暟鎹紝杩炴帴涓柇");
-                    client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null);
+                    byte[] data = buffer.Take(dataLength).ToArray();
+
+                    string dataStr = System.Text.Encoding.ASCII.GetString(data).Trim();
+
+                    AnalyzeData(dataStr);
+
+                    stream.BeginRead(buffer, 0, buffer.Length, OnDataReceived, null);
                 }
+                else
+                {
+                    if (!client.Connected)
+                    {
+                        //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()}");
+                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(() =>
@@ -137,25 +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
-                     {
-                         SendMsg(RobotMsgType.Rec, msg.ID, false);
-                         OnMsgReceived?.Invoke(msg);                         
-                     }
-                 });
+                            for (int i = msg.Para1.ToString().Length - 1; i >= 0; i--)
+                            {
+                                newValues.Add((msg.Para1 >> i) & 1);
+                            }
+
+                            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;
+                            }
+
+                            if (taskHandleDict.ContainsKey(msg.ID))
+                            {
+                                taskHandleDict[msg.ID].Set();
+                            }
+
+                            LogAsync(DateTime.Now, "鎸囦护鍙嶉", msg.GetDisplayText());
+                            OnMsgReceived?.BeginInvoke(DateTime.Now, this, msg, null, null);
+                        }
+                    }
+                });
             });
         }
 
@@ -164,7 +240,7 @@
         {
             get
             {
-                if (sid > 999)
+                if (sid > 99)
                 {
                     sid = 1;
                 }
@@ -173,49 +249,311 @@
             }
         }
 
-        List<int> replyHandleList = new List<int>();
         Dictionary<int, AutoResetEvent> replyHandleDict = new Dictionary<int, AutoResetEvent>();
+        Dictionary<int, int> replyErrorCodeDict = new Dictionary<int, int>();
+        Dictionary<int, ManualResetEvent> taskHandleDict = new Dictionary<int, ManualResetEvent>();
 
-        public void SendMsg(RobotMsgType type, int replyId, bool isWaitReply = true, RobotMsgAction action = RobotMsgAction.Move, RobotMsgParas para1 = RobotMsgParas.None, List<string> paras = null)
+        public void SendReplyMsg(int replyId)
         {
             RobotMsg msg = new RobotMsg();
 
-            msg.Type = type;
-            if (msg.Type == RobotMsgType.Send)
-            {
-                msg.ID = SID;
-            }
-            else
-            {
-                msg.ID = replyId;
-            }
+            msg.Type = RobotMsgType.Rec;
+            msg.ID = replyId;
 
-            msg.Para1 = para1;
-            msg.Paras = new List<string>(paras ?? new List<string>());
-
-            SendMsg(msg, isWaitReply);
+            SendMsg(msg, false);
         }
 
-        public void SendMsg(RobotMsg msg, bool isWaitReply = true)
+        bool canMonitor = true;
+        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);
-            client.GetStream().Write(bytes, 0, bytes.Length);
+            byte[] bytes = msg.GetMsgBytes(IConfig.Seperator, IConfig.EndChar, out string dataStr);
+            if (!isMonitorMsg)
+            {
+                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);
                 }
             }
         }
+
+        #region IMonitor
+        public event OnMonitorInvokeDelegate OnMonitorInvoke;
+        public event OnMonitorAlarmDelegate OnMonitorAlarm;
+
+        protected List<int> oldValues = new List<int>();
+        List<int> newValues = new List<int>();
+        public ManualResetEvent MonitorHandle { get; set; } = new ManualResetEvent(false);
+        public List<int> GetIOValues()
+        {
+            MonitorHandle.Reset();
+            scanMsg.ID = SID;
+            SendMsg(scanMsg, true, true);
+
+            var isNotTimeout = MonitorHandle.WaitOne(IConfig.ReplyTimeout * 3);
+
+            if (!isNotTimeout)
+                throw new ProcessException($"{Name}鐩戝惉鎿嶄綔瓒呮椂");
+
+            return newValues;
+        }
+
+        public virtual void Monitor()
+        {
+            while (CurrentState != EnumHelper.DeviceState.DSClose && CurrentState != EnumHelper.DeviceState.DSExcept)
+            {
+                try
+                {
+                    if (IConfig.IsEnableMonitor)
+                    {
+                        List<int> newValues = GetIOValues();
+
+                        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);
+                    }
+
+                    Thread.Sleep(IConfig.ScanInterval);
+                }
+                catch (Exception ex)
+                {
+                    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)
+                {
+                    return;
+                }
+
+                int newValue = tempNew[m.TriggerIndex];
+                int oldValue = tempOld[m.TriggerIndex];
+
+                if (newValue != oldValue)
+                {
+                    if (m.TriggerValue == -999 || newValue == m.TriggerValue)
+                    {
+                        if (m.OpConfig == null)
+                        {
+                            m.OpConfig = new OperationConfigBase();
+                        }
+
+                        m.OpConfig.InputPara = m.InputDataIndex.ConvertAll(index =>
+                        {
+                            return tempNew[index];
+                        }).ToList();
+
+                        OnMonitorInvoke?.BeginInvoke(DateTime.Now, this, m, null, null);
+                    }
+                }
+            });
+        }
+
+        public virtual void ResetAlarm()
+        {
+            IConfig.WarningSetCollection.ForEach(u => u.CurrentStatus = !u.TriggerValue);
+        }
+        #endregion
     }
 }

--
Gitblit v1.8.0