src/Bro.Device.AuboRobot/AuboRobotDriver.cs
@@ -1,6 +1,8 @@
using 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;
@@ -12,9 +14,9 @@
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,6 +34,8 @@
        protected override void Init()
        {
            oldValues = new List<int>();
            if (string.IsNullOrWhiteSpace(IConfig.EndChar))
            {
                throw new ProcessException("协议文本的结束字符不可为空,请检查配置", null);
@@ -52,19 +56,33 @@
        {
        }
        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.IO;
            scanMsg.Para1 = RobotMsgParas.Query;
            Task.Run(() =>
            {
                Monitor();
            });
        }
        protected override void Stop()
        {
            client.Close();
            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,36 +90,49 @@
            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());
                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();
                int dataLength = stream.EndRead(ar);
                string dataStr = System.Text.Encoding.ASCII.GetString(data).Trim();
                AnalyzeData(dataStr);
                client.GetStream().BeginRead(buffer, 0, buffer.Length, OnDateReceived, null);
            }
            else
            {
                if (!client.Connected)
                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();
                    //OnLog?.BeginInvoke(DateTime.Now, this, $"{Name}接收数据:{dataStr}", null, null);
                    AnalyzeData(dataStr);
                    stream.BeginRead(buffer, 0, buffer.Length, OnDataReceived, null);
                }
                else
                {
                    if (!client.Connected)
                    {
                        OnLog?.Invoke(DateTime.Now, this, "返回空数据,连接中断");
                        client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null);
                    }
                }
            }
            catch (Exception ex)
            {
                OnLog?.Invoke(DateTime.Now, this, $"{Name}数据接收异常:{ex.GetExceptionMessage()}");
            }
        }
@@ -152,8 +183,24 @@
                     }
                     else
                     {
                         SendMsg(RobotMsgType.Rec, msg.ID, false);
                         OnMsgReceived?.Invoke(msg);
                         canMonitor = true;
                         if (msg.Action == RobotMsgAction.IO && msg.Para1 == RobotMsgParas.Query)
                         {
                             string resultStr = msg.Datas[0];
                             newValues = new List<int>();
                             for (int i = resultStr.Length - 1; i >= 0; i--)
                             {
                                 newValues.Add(int.Parse(resultStr[i].ToString()));
                             }
                             MonitorHandle.Set();
                         }
                         else
                         {
                             OnMsgReceived?.BeginInvoke(DateTime.Now, this, msg, null, null);
                         }
                     }
                 });
            });
@@ -164,7 +211,7 @@
        {
            get
            {
                if (sid > 999)
                if (sid > 99)
                {
                    sid = 1;
                }
@@ -176,27 +223,35 @@
        List<int> replyHandleList = new List<int>();
        Dictionary<int, AutoResetEvent> replyHandleDict = new Dictionary<int, AutoResetEvent>();
        public void SendMsg(RobotMsgType type, int replyId, bool isWaitReply = true, RobotMsgAction action = RobotMsgAction.Move, RobotMsgParas para1 = RobotMsgParas.None, List<string> paras = null)
        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);
        }
        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)
        {
            if (isWaitReply)
            {
@@ -205,7 +260,22 @@
            }
            byte[] bytes = msg.GetMsgBytes(IConfig.Seperator, IConfig.EndChar);
            client.GetStream().Write(bytes, 0, bytes.Length);
            lock (monitorLock)
            {
                if (!isMonitorMsg)
                {
                    canMonitor = false;
                }
                if (isMonitorMsg && !canMonitor)
                    return;
                //lock (this)
                {
                    stream.Write(bytes, 0, bytes.Length);
                }
            }
            if (isWaitReply)
            {
@@ -217,5 +287,90 @@
                }
            }
        }
        #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 ManualResetEvent IOChangedHandle { get; set; } = new ManualResetEvent(true);
        public List<int> GetMonitorValues(int startAddress, int length)
        {
            MonitorHandle.Reset();
            scanMsg.ID = SID;
            SendMsg(scanMsg, true, true);
            MonitorHandle.WaitOne(IConfig.ReplyTimeout);
            return newValues;
        }
        public virtual void Monitor()
        {
            while (CurrentState != EnumHelper.DeviceState.DSClose && CurrentState != EnumHelper.DeviceState.DSExcept)
            {
                try
                {
                    List<int> newValues = GetMonitorValues(0, 0);
                    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)
                {
                    OnLog?.Invoke(DateTime.Now, this, $"{Name}监听异常:{ex.GetExceptionMessage()}");
                }
            }
        }
        protected virtual void MonitorCheckAndInvoke(List<int> tempNew, List<int> tempOld)
        {
            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);
                    }
                }
            });
        }
        #endregion
    }
}