From 6428fad15dbe79e30a48ffc9aabe31e03a45426c Mon Sep 17 00:00:00 2001 From: patrick <patrick.xu@broconcentric.com> Date: 星期四, 05 十二月 2019 12:50:13 +0800 Subject: [PATCH] 1. 添加部分log信息 2. 修改部分机器人动作流程 3. 开放OperationConfig的InputData参数 --- src/Bro.Device.AuboRobot/AuboRobotDriver.cs | 41 ++++++++----- src/Bro.Device.SeerAGV/SeerAGVConfig.cs | 9 ++ src/A032.Config/ConfigFrm.cs | 2 src/A032.Process/AGVBindUnit.cs | 10 ++ src/Bro.Device.SeerAGV/SeerAGVDriver.cs | 7 + src/A032.Process/ProcessControl.cs | 5 + src/Bro.Common.Model/Base/OperationConfigBase.cs | 6 + src/A032.Process/ProcessControl_Method.cs | 47 ++++++++++++--- 8 files changed, 92 insertions(+), 35 deletions(-) diff --git a/src/A032.Config/ConfigFrm.cs b/src/A032.Config/ConfigFrm.cs index 388f59d..edefec0 100644 --- a/src/A032.Config/ConfigFrm.cs +++ b/src/A032.Config/ConfigFrm.cs @@ -227,7 +227,7 @@ private void OnProcessLog(DateTime dt, string prefix, string msg) { - RecordMsg(dt.ToString("yyyyMMdd HH:mm:ss") + "\r\n" + prefix + "\r\n" + msg + "\r\n"); + RecordMsg(dt.ToString("yyyyMMdd HH:mm:ss.fff") + "\r\n" + prefix + "\r\n" + (string.IsNullOrWhiteSpace(msg) ? "" : (msg + "\r\n"))); } private void btnStopProcess_Click(object sender, EventArgs e) diff --git a/src/A032.Process/AGVBindUnit.cs b/src/A032.Process/AGVBindUnit.cs index 4aa8d0b..5d843f3 100644 --- a/src/A032.Process/AGVBindUnit.cs +++ b/src/A032.Process/AGVBindUnit.cs @@ -182,8 +182,14 @@ [JsonIgnore] public bool IsEmptyTrayTaskAssigned { get; set; } - [Browsable(false)] - [JsonIgnore] + //[Browsable(false)] + //[JsonIgnore] + //public ManualResetEvent FullTrayFullHandle { get; set; } = new ManualResetEvent(false); + + //[Browsable(false)] + //[JsonIgnore] + //public ManualResetEvent FullTrayEmptyHandle { get; set; } = new ManualResetEvent(false); + public ManualResetEvent RobotIOHandle { get; set; } = new ManualResetEvent(false); public AGVBindUnit() diff --git a/src/A032.Process/ProcessControl.cs b/src/A032.Process/ProcessControl.cs index dfd85ab..08cba1d 100644 --- a/src/A032.Process/ProcessControl.cs +++ b/src/A032.Process/ProcessControl.cs @@ -370,6 +370,8 @@ robot.InitialConfig = c; RobotDict[robot.InitialConfig.ID] = robot; + robot.OnLog = OnDeviceLog; + robot.OnMsgReceived = OnRobotMsgReceived; robot.OnMonitorAlarm -= OnMonitorAlarm; @@ -388,9 +390,10 @@ agv.InitialConfig = c; AGVDict[agv.InitialConfig.ID] = agv; + agv.OnLog = OnDeviceLog; agv.OnAGVPositoinChanged = OnAGVPositionChanged; agv.OnAGVTaskStatusChanged = OnAGVTaskStatusChanged; - agv.OnAGVBatteryLvlChanged = OnAGVBatterLvlChanged; + agv.OnAGVBatteryLvlChanged = OnAGVBatteryLvlChanged; }); } diff --git a/src/A032.Process/ProcessControl_Method.cs b/src/A032.Process/ProcessControl_Method.cs index 451d2bd..dc0d8c8 100644 --- a/src/A032.Process/ProcessControl_Method.cs +++ b/src/A032.Process/ProcessControl_Method.cs @@ -27,11 +27,11 @@ List<TaskAssignInfo> taskAssignedList = new List<TaskAssignInfo>(); #region AGV浜嬩欢 - private void OnAGVBatterLvlChanged(SeerAGVDriver agv, float batterLvl) + private void OnAGVBatteryLvlChanged(SeerAGVDriver agv, float preBatteryLvl, float batteryLvl) { var bind = Config.AGVBindCollection.FirstOrDefault(u => u.AGVId == agv.Id); SeerAGVInitialConfig iConfig = agv.InitialConfig as SeerAGVInitialConfig; - if (batterLvl <= iConfig.BatteryLvlToCharge) + if (batteryLvl <= iConfig.BatteryLvlToCharge && preBatteryLvl > iConfig.BatteryLvlToCharge) { Task.Run(() => { @@ -57,9 +57,14 @@ return; } - if (batterLvl >= iConfig.BatteryLvlChargeDone) + if (batteryLvl >= iConfig.BatteryLvlChargeDone && preBatteryLvl < iConfig.BatteryLvlChargeDone) { - bind.SetAGVStatus(TaskStatus.Available); + var position = Config.PositionCollection.FirstOrDefault(u => u.PositionCode == agv.CurrentPosition); + + if (position != null && position.Description == PathPositionDefinition.Charge) + { + bind.SetAGVStatus(TaskStatus.Available); + } return; } } @@ -105,19 +110,25 @@ //} bind.SetAGVStatus(TaskStatus.Available); + LogAsync(DateTime.Now, $"AGV鍒颁綅{positionCode}", ""); PathPosition position = Config.PositionCollection.FirstOrDefault(p => p.PositionCode == bind.AGVDest); switch (position.Description) { case PathPositionDefinition.LoadEmptyTray: + LogAsync(DateTime.Now, $"AGV瀹屾垚锛屽噯澶囦笂绌篢ray", ""); Robot_LoadEmptyTray(bind.Id, position); break; case PathPositionDefinition.LoadFullTray: + LogAsync(DateTime.Now, $"AGV瀹屾垚锛屽噯澶囦笂婊ray", ""); + Robot_LoadFullTraySnap(bind.Id, position); break; case PathPositionDefinition.UnloadEmptyTray: + LogAsync(DateTime.Now, $"AGV瀹屾垚锛屽噯澶囦笅绌篢ray", ""); Robot_UnloadEmptyTraySnap(bind.Id, position); break; case PathPositionDefinition.UnloadFullTray: + LogAsync(DateTime.Now, $"AGV瀹屾垚锛屽噯澶囦笅婊ray", ""); Robot_UnloadFullTraySnap(bind.Id, position); break; default: @@ -183,8 +194,11 @@ if (machineEmptyTrayDict[msg.Para2] < Config.Machine_EmptyTrayNum) { - bind.RobotIOHandle.Reset(); - bind.RobotIOHandle.WaitOne(); + //bind.RobotIOHandle.Reset(); + //bind.RobotIOHandle.WaitOne(); + bind.Robot.MonitorHandle.WaitOne(); + //bind.Robot.IOChangedHandle.WaitOne(); + Thread.Sleep((bind.Robot.InitialConfig as AuboRobotInitialConfig).ScanInterval); if (!bind.IsFullTrayFull) { @@ -206,12 +220,19 @@ { bind.CurrentFullTray = int.Parse(msg.Datas[1]); - bind.RobotIOHandle.Reset(); - bind.RobotIOHandle.WaitOne(); + //bind.RobotIOHandle.Reset(); + //bind.RobotIOHandle.WaitOne(); + bind.Robot.MonitorHandle.WaitOne(); + //bind.Robot.IOChangedHandle.WaitOne(); + Thread.Sleep((bind.Robot.InitialConfig as AuboRobotInitialConfig).ScanInterval); if (!bind.IsFullTrayEmpty) { Camera_UnloadFullTray(robot.Id, msg.Para2); + } + else + { + bind.RobotStatus = TaskStatus.Available; } } break; @@ -387,6 +408,7 @@ [ProcessMethod("", "Robot_Monitor_FullTrayFull", "鏈哄櫒浜虹洃鍚簨浠�-婊ray鍖哄煙鏀炬弧", true)] public ProcessResponse Robot_Monitor_FullTrayFull(IOperationConfig config, IDevice device) { + //(device as AuboRobotDriver).IOChangedHandle.Reset(); bool isFullTrayFull = config.InputPara[0] == 1; var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); if (isFullTrayFull) @@ -425,7 +447,9 @@ bind.IsFullTrayTaskAssigned = false; } - bind.RobotIOHandle.Set(); + //(device as AuboRobotDriver).IOChangedHandle.Set(); + + //bind.RobotIOHandle.Set(); return new ProcessResponse(true); } @@ -433,11 +457,13 @@ [ProcessMethod("", "Robot_Monitor_FullTrayEmpty", "鏈哄櫒浜虹洃鍚簨浠�-婊ray鍖哄煙娓呯┖", true)] public ProcessResponse Robot_Monitor_FullTrayEmpty(IOperationConfig config, IDevice device) { + //(device as AuboRobotDriver).IOChangedHandle.Reset(); bool isFullTrayEmpty = config.InputPara[0] == 0; var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); bind.IsFullTrayEmpty = isFullTrayEmpty; - bind.RobotIOHandle.Set(); + //(device as AuboRobotDriver).IOChangedHandle.Set(); + //bind.RobotIOHandle.Set(); return new ProcessResponse(true); } @@ -1194,6 +1220,7 @@ bind.RobotStatus = TaskStatus.Running; bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LineSnap, position.PositionNo); + //LogAsync(DateTime.Now, "Robot杩愬姩鑷充笅婊ray鎷嶇収", ""); } //[ProcessMethod("", "Camera_UnloadFullTray", "鐩告満鎿嶄綔鍗歌浇婊ray", true)] diff --git a/src/Bro.Common.Model/Base/OperationConfigBase.cs b/src/Bro.Common.Model/Base/OperationConfigBase.cs index 049798d..93cab91 100644 --- a/src/Bro.Common.Model/Base/OperationConfigBase.cs +++ b/src/Bro.Common.Model/Base/OperationConfigBase.cs @@ -35,8 +35,10 @@ /// 杈撳叆鍙傛暟 /// </summary> [JsonIgnore] - [Browsable(false)] - public List<int> InputPara { get; set; } + [Category("杈撳叆閰嶇疆")] + [Description("杈撳叆鍙傛暟閰嶇疆")] + [TypeConverter(typeof(SimpleCollectionConvert<int>))] + public List<int> InputPara { get; set; } = new List<int>(); [Category("鍚敤閰嶇疆")] diff --git a/src/Bro.Device.AuboRobot/AuboRobotDriver.cs b/src/Bro.Device.AuboRobot/AuboRobotDriver.cs index d2ae516..11f343f 100644 --- a/src/Bro.Device.AuboRobot/AuboRobotDriver.cs +++ b/src/Bro.Device.AuboRobot/AuboRobotDriver.cs @@ -82,6 +82,7 @@ #endregion TcpClient client = new TcpClient(); + NetworkStream stream = null; byte[] buffer = new byte[1024]; private void OnConnect(IAsyncResult ar) @@ -89,7 +90,8 @@ 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) { @@ -103,20 +105,21 @@ } } - private void OnDateReceived(IAsyncResult ar) + private void OnDataReceived(IAsyncResult ar) { try { - int dataLength = client.GetStream().EndRead(ar); + 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); - client.GetStream().BeginRead(buffer, 0, buffer.Length, OnDateReceived, null); + stream.BeginRead(buffer, 0, buffer.Length, OnDataReceived, null); } else { @@ -192,7 +195,7 @@ newValues.Add(int.Parse(resultStr[i].ToString())); } - monitorHandle.Set(); + MonitorHandle.Set(); } else { @@ -232,6 +235,7 @@ 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); } @@ -246,6 +250,7 @@ } bool canMonitor = true; + object monitorLock = new object(); public void SendMsg(RobotMsg msg, bool isWaitReply = true, bool isMonitorMsg = false) { if (isWaitReply) @@ -256,17 +261,20 @@ byte[] bytes = msg.GetMsgBytes(IConfig.Seperator, IConfig.EndChar); - if (!isMonitorMsg) + lock (monitorLock) { - canMonitor = false; - } + if (!isMonitorMsg) + { + canMonitor = false; + } - if (isMonitorMsg && !canMonitor) - return; + if (isMonitorMsg && !canMonitor) + return; - //lock (this) - { - client.GetStream().Write(bytes, 0, bytes.Length); + //lock (this) + { + stream.Write(bytes, 0, bytes.Length); + } } if (isWaitReply) @@ -286,12 +294,15 @@ protected List<int> oldValues = new List<int>(); List<int> newValues = new List<int>(); - AutoResetEvent monitorHandle = new AutoResetEvent(false); + 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); + + MonitorHandle.WaitOne(IConfig.ReplyTimeout); return newValues; } diff --git a/src/Bro.Device.SeerAGV/SeerAGVConfig.cs b/src/Bro.Device.SeerAGV/SeerAGVConfig.cs index a094f0c..3866776 100644 --- a/src/Bro.Device.SeerAGV/SeerAGVConfig.cs +++ b/src/Bro.Device.SeerAGV/SeerAGVConfig.cs @@ -76,7 +76,7 @@ } - public class SeerMessage + public class SeerMessage : IComplexDisplay { private byte[] frame = null; public byte[] Frame @@ -151,6 +151,11 @@ return msg; } + + public string GetDisplayText() + { + return ""; + } } //public enum RobotPort @@ -171,7 +176,7 @@ PauseTask = 0x0BB9, TaskOrder = 0x0BEB, - QueryBattery = 0x2AFF, + QueryBattery = 0x03EF, } public enum AGVTaskStatus diff --git a/src/Bro.Device.SeerAGV/SeerAGVDriver.cs b/src/Bro.Device.SeerAGV/SeerAGVDriver.cs index 635132e..b875bda 100644 --- a/src/Bro.Device.SeerAGV/SeerAGVDriver.cs +++ b/src/Bro.Device.SeerAGV/SeerAGVDriver.cs @@ -19,7 +19,7 @@ { public Action<SeerAGVDriver, string> OnAGVPositoinChanged; public Action<SeerAGVDriver, AGVTaskStatus> OnAGVTaskStatusChanged; - public Action<SeerAGVDriver, float> OnAGVBatteryLvlChanged; + public Action<SeerAGVDriver, float, float> OnAGVBatteryLvlChanged; SeerAGVInitialConfig IConfig { @@ -152,8 +152,9 @@ { if (batteryLvl != value) { + float pre = batteryLvl; batteryLvl = value; - OnAGVBatteryLvlChanged?.Invoke(this, batteryLvl); + OnAGVBatteryLvlChanged?.Invoke(this, pre, batteryLvl); } } } @@ -275,6 +276,8 @@ { CurrentPosition = ""; SeerMessage msg = new SeerMessage((int)AGVCode.TaskOrder, SID, JsonConvert.SerializeObject(new { id = dest })); + + OnLog?.BeginInvoke(DateTime.Now, this, $"{Name}琛岄┒鍚� {dest}", null, null); SendMsg(client_Guide, IConfig.GuidePort, msg); } } -- Gitblit v1.8.0