| | |
| | | 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; |
| | |
| | | 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 |
| | | { |
| | |
| | | |
| | | protected override void Init() |
| | | { |
| | | oldValues = new List<int>(); |
| | | |
| | | if (string.IsNullOrWhiteSpace(IConfig.EndChar)) |
| | | { |
| | | throw new ProcessException("协议文本的结束字符不可为空,请检查配置", null); |
| | |
| | | { |
| | | } |
| | | |
| | | 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) |
| | |
| | | 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()}"); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | 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); |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | |
| | | { |
| | | get |
| | | { |
| | | if (sid > 999) |
| | | if (sid > 99) |
| | | { |
| | | sid = 1; |
| | | } |
| | |
| | | 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) |
| | | { |
| | |
| | | } |
| | | |
| | | 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) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | #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 |
| | | } |
| | | } |