using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace Bro.Device.AuboRobot { [Device("AuboRobot", "奥博机器人", EnumHelper.DeviceAttributeType.Device)] public class AuboRobotDriver : DeviceBase { public Action OnMsgReceived { get; set; } AuboRobotInitialConfig IConfig { get => InitialConfig as AuboRobotInitialConfig; } #region DeviceBase protected override void DeviceRun(IOperationConfig config) { } protected override void DeviceSet(IDeviceConfig config) { } protected override void Init() { if (string.IsNullOrWhiteSpace(IConfig.EndChar)) { throw new ProcessException("协议文本的结束字符不可为空,请检查配置", null); } client = new TcpClient(); client.SendBufferSize = client.ReceiveBufferSize = 0; client.Client.Blocking = true; client.NoDelay = true; client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null); } protected override void Pause() { } protected override void Resume() { } protected override void Start() { //Query Robot IOs //SendMsg(RobotMsgType.Send, 0, true, RobotMsgAction.IO, RobotMsgParas.Query, new List()); } protected override void Stop() { client.Close(); } #endregion TcpClient client = new TcpClient(); byte[] buffer = new byte[1024]; private void OnConnect(IAsyncResult ar) { try { client.EndConnect(ar); client.GetStream().BeginRead(buffer, 0, buffer.Length, OnDateReceived, null); } catch (Exception ex) { OnLog?.Invoke(DateTime.Now, this, ex.GetExceptionMessage()); client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null); } } private void OnDateReceived(IAsyncResult ar) { int dataLength = client.GetStream().EndRead(ar); if (dataLength > 0) { 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) { OnLog?.Invoke(DateTime.Now, this, "返回空数据,连接中断"); client.BeginConnect(IPAddress.Parse(IConfig.RobotIP), IConfig.RobotPort, OnConnect, null); } } } string msg = ""; static object analyzeLock = new object(); private async void AnalyzeData(string data) { await Task.Run(() => { lock (analyzeLock) { msg += data; var datas = msg.Split(new string[] { IConfig.EndChar }, StringSplitOptions.RemoveEmptyEntries); if (msg.EndsWith(IConfig.EndChar)) { msg = ""; } else { msg = datas[datas.Length - 1]; datas = datas.Take(datas.Length - 1).ToArray(); } AnalyzeDataList(datas); } }); } private async void AnalyzeDataList(string[] datas) { await Task.Run(() => { Array.ForEach(datas, data => { RobotMsg msg = RobotMsg.GetRobotMsg(data, IConfig.Seperator); if (msg.Type == RobotMsgType.Rec) { if (replyHandleDict.ContainsKey(msg.ID)) { replyHandleList.Remove(msg.ID); replyHandleDict[msg.ID].Set(); replyHandleDict.Remove(msg.ID); } } else { SendMsg(RobotMsgType.Rec, msg.ID, false); OnMsgReceived?.Invoke(msg); } }); }); } int sid = 1; int SID { get { if (sid > 999) { sid = 1; } return sid++; } } List replyHandleList = new List(); Dictionary replyHandleDict = new Dictionary(); public void SendMsg(RobotMsgType type, int replyId, bool isWaitReply = true, RobotMsgAction action = RobotMsgAction.Move, RobotMsgParas para1 = RobotMsgParas.None, List paras = null) { RobotMsg msg = new RobotMsg(); msg.Type = type; if (msg.Type == RobotMsgType.Send) { msg.ID = SID; } else { msg.ID = replyId; } msg.Para1 = para1; msg.Paras = new List(paras ?? new List()); SendMsg(msg, isWaitReply); } public void SendMsg(RobotMsg msg, bool isWaitReply = true) { 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); if (isWaitReply) { replyHandleDict[msg.ID].WaitOne(IConfig.ReplyTimeout); if (replyHandleList.Contains(msg.ID)) { throw new ProcessException("反馈数据超时\r\n" + msg.GetDisplayText(), null); } } } } }