From 4e8bf084f8a04617a9f542099183b8d829fa7c4b Mon Sep 17 00:00:00 2001 From: patrick <patrick.xu@broconcentric.com> Date: 星期五, 18 十月 2019 19:07:51 +0800 Subject: [PATCH] 1. 修改机器人通信协议及相关流程触发和操作 --- src/A032.Process/Calibration/CalibrationConfig.cs | 87 + src/A032.Process/Calibration/FrmCalib9PDynamic.Designer.cs | 47 src/Bro.Device.SeerAGV/SeerAGVConfig.cs | 1 src/A032.Process/ProcessConfig.cs | 114 - src/A032.Process/A032.Process.csproj | 22 src/A032.Process/ProcessControl_Calibration.cs | 101 + src/Bro.Common.Model/Interface/IStationProcess.cs | 2 src/Bro.Device.SeerAGV/SeerAGVDriver.cs | 22 src/A032.Process/ProcessControl.cs | 113 + src/Bro.Device.AuboRobot/AuboRobotConfig.cs | 107 + src/A032.Process/Calibration/FrmCalib9PDynamic.resx | 120 ++ src/A032.Process/AGVPath.cs | 110 ++ src/A032.Process/ProcessControl_Method.cs | 1064 +++++++++++++++++++ src/A032.Process/Calibration/CtrlCalib9PDynamic.resx | 123 ++ src/Bro.Device.OmronFins/OmronFinsConfig.cs | 8 src/Bro.Common.Model/Interface/IMonitor.cs | 7 src/Bro.Device.AuboRobot/AuboRobotDriver.cs | 166 ++ src/Bro.Device.AuboRobot/Bro.Device.AuboRobot.csproj | 1 src/A032.Process/Calibration/CtrlCalib9PDynamic.Designer.cs | 378 +++++++ src/A032.Process/AGVBindUnit.cs | 295 +++++ src/Bro.Device.Common/DeviceBase/PLCBase.cs | 4 src/A032.Process/Calibration/FrmCalib9PDynamic.cs | 50 src/Bro.Common.Model/Helper/ExceptionHelper.cs | 2 src/A032.Process/Calibration/CtrlCalib9PDynamic.cs | 277 +++++ 24 files changed, 3,037 insertions(+), 184 deletions(-) diff --git a/src/A032.Process/A032.Process.csproj b/src/A032.Process/A032.Process.csproj index f644f1f..2a1c97b 100644 --- a/src/A032.Process/A032.Process.csproj +++ b/src/A032.Process/A032.Process.csproj @@ -55,6 +55,21 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="AGVBindUnit.cs" /> + <Compile Include="AGVPath.cs" /> + <Compile Include="Calibration\CalibrationConfig.cs" /> + <Compile Include="Calibration\CtrlCalib9PDynamic.cs"> + <SubType>UserControl</SubType> + </Compile> + <Compile Include="Calibration\CtrlCalib9PDynamic.Designer.cs"> + <DependentUpon>CtrlCalib9PDynamic.cs</DependentUpon> + </Compile> + <Compile Include="Calibration\FrmCalib9PDynamic.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Calibration\FrmCalib9PDynamic.Designer.cs"> + <DependentUpon>FrmCalib9PDynamic.cs</DependentUpon> + </Compile> <Compile Include="Forms\MonitorSetBindFrm.cs"> <SubType>Form</SubType> </Compile> @@ -75,6 +90,7 @@ </Compile> <Compile Include="Helper\PropertyConvertHelper.cs" /> <Compile Include="ProcessConfig.cs" /> + <Compile Include="ProcessControl_Calibration.cs" /> <Compile Include="ProcessControl_Method.cs" /> <Compile Include="ProcessControl.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> @@ -109,6 +125,12 @@ <None Include="packages.config" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="Calibration\CtrlCalib9PDynamic.resx"> + <DependentUpon>CtrlCalib9PDynamic.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Calibration\FrmCalib9PDynamic.resx"> + <DependentUpon>FrmCalib9PDynamic.cs</DependentUpon> + </EmbeddedResource> <EmbeddedResource Include="Forms\MonitorSetBindFrm.resx"> <DependentUpon>MonitorSetBindFrm.cs</DependentUpon> </EmbeddedResource> diff --git a/src/A032.Process/AGVBindUnit.cs b/src/A032.Process/AGVBindUnit.cs new file mode 100644 index 0000000..460c4f4 --- /dev/null +++ b/src/A032.Process/AGVBindUnit.cs @@ -0,0 +1,295 @@ +锘縰sing Autofac; +using Bro.Common.Base; +using Bro.Common.Helper; +using Bro.Common.Interface; +using Bro.Common.Model; +using Bro.Device.AuboRobot; +using Bro.Device.SeerAGV; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Threading; + +namespace A032.Process +{ + public enum TaskStatus + { + Available = 1, + Running = 2, + Warning = 3, + } + + public enum TaskAvailableLevel + { + Robot = 1, + AGV = 2, + Both = 3, + } + + public class AGVTaskModel + { + public TaskAvailableLevel Level { get; set; } = TaskAvailableLevel.Robot; + + public Func<IOperationConfig, IDevice, ProcessResponse> MethodFunc { get; set; } + + public IOperationConfig OpConfig { get; set; } + + public IDevice Device { get; set; } + + //public int Priority { get; set; } = 10; + + public AGVTaskModel() { } + + public AGVTaskModel(TaskAvailableLevel level, Func<IOperationConfig, IDevice, ProcessResponse> methodFunc, IOperationConfig opConfig = null, IDevice device = null) + { + Level = level; + MethodFunc = methodFunc; + OpConfig = opConfig ?? new OperationConfigBase(); + Device = device; + } + } + + public class AGVBindUnit : IComplexDisplay + { + #region 鍙紪杈戦」鐩� + [Category("璁惧缁戝畾")] + [Description("缁戝畾Id")] + [ReadOnly(true)] + public string Id { get; set; } = Guid.NewGuid().ToString(); + + [Category("璁惧缁戝畾")] + [Description("缁戝畾AGV")] + [TypeConverter(typeof(AGVDeviceConverter))] + public string AGVId { get; set; } + + [Category("璁惧缁戝畾")] + [Description("缁戝畾Robot")] + [TypeConverter(typeof(RobotDeviceConverter))] + public string RobotId { get; set; } + + [Category("璁惧缁戝畾")] + [Description("缁戝畾Camera")] + [TypeConverter(typeof(CameraDeviceConverter))] + public string CameraId { get; set; } + + public string GetDisplayText() + { + using (var scope = GlobalVar.Container.BeginLifetimeScope()) + { + ProcessConfig config = scope.Resolve<ProcessConfig>(); + + string agv = config.AGVConfigCollection.FirstOrDefault(u => u.ID == AGVId)?.Name ?? "鏈粦瀹欰GV"; + string robot = config.RobotConfigCollection.FirstOrDefault(u => u.ID == RobotId)?.Name ?? "鏈粦瀹氭満鍣ㄤ汉"; + string camera = config.CameraConfigCollection.FirstOrDefault(u => u.ID == CameraId)?.Name ?? "鏈粦瀹氱浉鏈�"; + + return agv + "-" + robot + "-" + camera; + } + } + #endregion + + [Browsable(false)] + [JsonIgnore] + public Action<AGVBindUnit> OnMethodInvoke { get; set; } + + public string AGVDest { get; set; } = ""; + + private TaskStatus agvStatus = TaskStatus.Available; + [Browsable(false)] + [JsonIgnore] + public TaskStatus AGVStatus + { + get => agvStatus; + set + { + agvStatus = value; + InvokeTaskCheck(); + } + } + + private TaskStatus robotStatus = TaskStatus.Available; + [Browsable(false)] + [JsonIgnore] + public TaskStatus RobotStatus + { + get => robotStatus; + set + { + robotStatus = value; + InvokeTaskCheck(); + } + } + + [Browsable(false)] + [JsonIgnore] + public TaskStatus UnitStatus + { + get + { + if (AGVStatus == TaskStatus.Warning || RobotStatus == TaskStatus.Warning) + { + return TaskStatus.Warning; + } + else + { + if (AGVStatus == TaskStatus.Available && RobotStatus == TaskStatus.Available) + { + return TaskStatus.Available; + } + } + + return TaskStatus.Running; + } + } + + [Browsable(false)] + [JsonIgnore] + public SeerAGVDriver AGV { get; set; } = null; + [Browsable(false)] + [JsonIgnore] + public AuboRobotDriver Robot { get; set; } = null; + [Browsable(false)] + [JsonIgnore] + public CameraBase Camera { get; set; } = null; + [Browsable(false)] + [JsonIgnore] + public ObservableCollection<AGVTaskModel> TaskList { get; set; } = new ObservableCollection<AGVTaskModel>(); + + [Browsable(false)] + [JsonIgnore] + public int CurrentEmptyTray { get; set; } + [Browsable(false)] + [JsonIgnore] + public int CurrentFullTray { get; set; } + [Browsable(false)] + [JsonIgnore] + public bool IsFullTrayFull { get; set; } + [Browsable(false)] + [JsonIgnore] + public bool IsFullTrayEmpty { get; set; } + [Browsable(false)] + [JsonIgnore] + public bool IsEmptyTrayEmpty { get; set; } + + [Browsable(false)] + [JsonIgnore] + public ManualResetEvent RobotIOHandle { get; set; } = new ManualResetEvent(false); + + public AGVBindUnit() + { + TaskList.CollectionChanged += TaskList_CollectionChanged; + } + + private void TaskList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) + { + InvokeTaskCheck(); + } + } + + private void InvokeTaskCheck() + { + for (int i = 0; i < TaskList.Count; i++) + { + var task = TaskList[i]; + + bool isAgvOK = false; + bool isRobotOK = false; + + if ((task.Level & TaskAvailableLevel.AGV) == TaskAvailableLevel.AGV) + { + isAgvOK = AGVStatus == TaskStatus.Available; + } + else + { + isAgvOK = true; + } + + if ((task.Level & TaskAvailableLevel.Robot) == TaskAvailableLevel.Robot) + { + isRobotOK = RobotStatus == TaskStatus.Available; + } + else + { + isRobotOK = true; + } + + if (isRobotOK && isAgvOK) + { + OnMethodInvoke?.Invoke(this); + TaskList.RemoveAt(i); + break; + } + } + } + } + + public class AGVDeviceConverter : ComboBoxItemTypeConvert + { + public override void GetConvertHash() + { + using (var scope = GlobalVar.Container.BeginLifetimeScope()) + { + ProcessConfig config = scope.Resolve<ProcessConfig>(); + + config.AGVConfigCollection.ForEach(plc => + { + _hash[plc.ID] = plc.Name; + }); + } + } + } + + public class RobotDeviceConverter : ComboBoxItemTypeConvert + { + public override void GetConvertHash() + { + using (var scope = GlobalVar.Container.BeginLifetimeScope()) + { + ProcessConfig config = scope.Resolve<ProcessConfig>(); + + config.RobotConfigCollection.ForEach(plc => + { + _hash[plc.ID] = plc.Name; + }); + } + } + } + + public class CameraDeviceConverter : ComboBoxItemTypeConvert + { + public override void GetConvertHash() + { + using (var scope = GlobalVar.Container.BeginLifetimeScope()) + { + ProcessConfig config = scope.Resolve<ProcessConfig>(); + + config.CameraConfigCollection.ForEach(plc => + { + _hash[plc.ID] = plc.Name; + }); + } + } + } + + public class PLCDeviceConverter : ComboBoxItemTypeConvert + { + public override void GetConvertHash() + { + using (var scope = GlobalVar.Container.BeginLifetimeScope()) + { + _hash[""] = "鏈寚瀹�"; + + ProcessConfig config = scope.Resolve<ProcessConfig>(); + + config.PLCConfigCollection.ForEach(plc => + { + _hash[plc.ID] = plc.Name; + }); + } + } + } +} diff --git a/src/A032.Process/AGVPath.cs b/src/A032.Process/AGVPath.cs new file mode 100644 index 0000000..1bfb3e0 --- /dev/null +++ b/src/A032.Process/AGVPath.cs @@ -0,0 +1,110 @@ +锘縰sing Autofac; +using Bro.Common.Helper; +using Bro.Common.Model; +using Bro.Common.Model.Interface; +using Bro.Device.HikCamera; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing.Design; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace A032.Process +{ + public enum PathPositionDefinition + { + [Description("鏃犲湴鐐�")] + None = 0, + [Description("涓婄┖Tray鍦扮偣")] + LoadEmptyTray = 1, + [Description("鍗歌浇绌篢ray鍦扮偣")] + UnloadEmptyTray = 2, + [Description("涓婃弧Tray鍦扮偣")] + LoadFullTray = 3, + [Description("鍗歌浇婊ray鍦扮偣")] + UnloadFullTray = 4, + } + + public class PathPosition : IComplexDisplay + { + [Category("瀵艰埅璺緞")] + [Description("AGV璺緞鑺傜偣浠g爜")] + public string PositionCode { get; set; } + + [Category("瀵艰埅璺緞")] + [Description("Robot璺緞鑺傜偣鏁板瓧")] + public int PositionNo { get; set; } + + [Category("瀵艰埅璺緞")] + [Description("璺緞鑺傜偣鎻忚堪")] + public PathPositionDefinition Description { get; set; } = PathPositionDefinition.None; + + [Category("褰掑睘璁惧")] + [Description("褰掑睘璁惧缂栧彿")] + [TypeConverter(typeof(PLCDeviceConverter))] + public string DeviceOwner { get; set; } + + public string GetDisplayText() + { + return $"{PositionCode}-{Description}"; + } + } + + public class PositionVisionConfig : IComplexDisplay, IHalconToolPath + { + [Category("鍏宠仈閰嶇疆")] + [Description("浣嶇疆浠g爜")] + [TypeConverter(typeof(PositionCodeConverter))] + public string PositionCode { get; set; } + + [Category("鍏宠仈閰嶇疆")] + [Description("閫傜敤鐩告満缂栧彿")] + [TypeConverter(typeof(CameraDeviceConverter))] + public string CameraId { get; set; } + + [Category("瑙嗚閰嶇疆")] + [Description("璇ヤ綅缃爣瀹氱煩闃碉紝鐢ㄤ簬浠庣浉鏈哄儚绱犲潗鏍囪浆鎹㈠埌鏈哄櫒浜虹殑杩愬姩浜岀淮鍧愭爣绯伙紝鍙绠楀亸绉�")] + [TypeConverter(typeof(SimpleCollectionConvert<double>))] + public List<double> Matrix { get; set; } = new List<double>(); + + [Category("瑙嗚閰嶇疆")] + [Description("璇ヤ綅缃爣鍑嗙偣浣嶄俊鎭�")] + [TypeConverter(typeof(ComplexObjectConvert))] + [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] + public CustomizedPoint StandardPoint { get; set; } = new CustomizedPoint(); + + [Category("瑙嗚閰嶇疆")] + [Description("璇ヤ綅缃媿鎽勯厤缃�")] + [TypeConverter(typeof(ComplexObjectConvert))] + [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] + public HikCameraOperationConfig CameraOpConfig { get; set; } = new HikCameraOperationConfig(); + + public string GetDisplayText() + { + return $"{PositionCode}:鏇濆厜锛歿CameraOpConfig.Exposure};鏍囧畾鐭╅樀锛歿string.Join(",", Matrix)}"; + } + + public List<string> GetHalconToolPathList() + { + return new List<string>() { CameraOpConfig.AlgorithemPath }; + } + } + + public class PositionCodeConverter : ComboBoxItemTypeConvert + { + public override void GetConvertHash() + { + using (var scope = GlobalVar.Container.BeginLifetimeScope()) + { + var config = scope.Resolve<ProcessConfig>(); + + config.PositionCollection.ForEach(p => + { + _hash[p.PositionCode] = $"{p.PositionCode}-{p.Description.GetEnumDescription()}"; + }); + } + } + } +} diff --git a/src/A032.Process/Calibration/CalibrationConfig.cs b/src/A032.Process/Calibration/CalibrationConfig.cs new file mode 100644 index 0000000..8c0d7fe --- /dev/null +++ b/src/A032.Process/Calibration/CalibrationConfig.cs @@ -0,0 +1,87 @@ +锘縰sing Bro.Common.Base; +using Bro.Common.Helper; +using Bro.Common.Model; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Design; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace A032.Process.Calibration +{ + [Device("CalibrationCollection", "澶氭鏍囧畾閰嶇疆", EnumHelper.DeviceAttributeType.OperationConfig)] + public class CalibrationConfigCollection : OperationConfigBase + { + [Category("鍏宠仈閰嶇疆")] + [Description("浣嶇疆浠g爜")] + [TypeConverter(typeof(PositionCodeConverter))] + public string PositionCode { get; set; } + + [Category("鍏宠仈閰嶇疆")] + [Description("閫傜敤鐩告満缂栧彿")] + [TypeConverter(typeof(CameraDeviceConverter))] + public string CameraId { get; set; } + + [Category("鏍囧畾閰嶇疆")] + [Description("鏍囧畾閰嶇疆闆嗗悎")] + [TypeConverter(typeof(CollectionCountConvert))] + [Editor(typeof(ComplexCollectionEditor<CalibrationConfig>), typeof(UITypeEditor))] + public List<CalibrationConfig> Configs { get; set; } = new List<CalibrationConfig>(); + } + + //[Device("Calibration", "鍗曟鏍囧畾閰嶇疆", EnumHelper.DeviceAttributeType.OperationConfig)] + public class CalibrationConfig : OperationConfigBase, IComplexDisplay, INotifyPropertyChanged + { + private Bitmap image = null; + [JsonIgnore] + [Browsable(false)] + public Bitmap Image + { + get => image; + set + { + image = value; + + if (value != null) + { + //PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs("Image"), null, null); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Image")); + } + } + } + + [Category("瑙嗚淇℃伅")] + [Description("绂荤嚎鍥剧墖璺緞")] + [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] + public string OfflineImagePath { get; set; } + + [Category("瑙嗚淇℃伅")] + [Description("鍥惧儚鏍囧噯鐐瑰潗鏍�")] + [TypeConverter(typeof(ComplexObjectConvert))] + [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] + public CustomizedPoint ImageMarkPoint { get; set; } = new CustomizedPoint(); + + [Category("鐩告満閰嶇疆")] + [Description("鐩告満鎿嶄綔閰嶇疆")] + [TypeConverter(typeof(ComplexObjectConvert))] + [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] + public HalconRelatedCameraOprerationConfigBase CameraOpConfig { get; set; } = new HalconRelatedCameraOprerationConfigBase(); + + [Category("杩愬姩骞冲彴璁剧疆")] + [Description("骞冲彴褰撳墠鍧愭爣")] + [TypeConverter(typeof(ComplexObjectConvert))] + [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] + public CustomizedPoint CurrentPlatPoint { get; set; } = new CustomizedPoint(); + + public event PropertyChangedEventHandler PropertyChanged; + + public string GetDisplayText() + { + return JsonConvert.SerializeObject(this); + } + } +} diff --git a/src/A032.Process/Calibration/CtrlCalib9PDynamic.Designer.cs b/src/A032.Process/Calibration/CtrlCalib9PDynamic.Designer.cs new file mode 100644 index 0000000..b876f22 --- /dev/null +++ b/src/A032.Process/Calibration/CtrlCalib9PDynamic.Designer.cs @@ -0,0 +1,378 @@ +锘縩amespace A032.Process.Calibration +{ + partial class CtrlCalib9PDynamic + { + /// <summary> + /// 蹇呴渶鐨勮璁″櫒鍙橀噺銆� + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// 娓呯悊鎵�鏈夋鍦ㄤ娇鐢ㄧ殑璧勬簮銆� + /// </summary> + /// <param name="disposing">濡傛灉搴旈噴鏀炬墭绠¤祫婧愶紝涓� true锛涘惁鍒欎负 false銆�</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 缁勪欢璁捐鍣ㄧ敓鎴愮殑浠g爜 + + /// <summary> + /// 璁捐鍣ㄦ敮鎸佹墍闇�鐨勬柟娉� - 涓嶈淇敼 + /// 浣跨敤浠g爜缂栬緫鍣ㄤ慨鏀规鏂规硶鐨勫唴瀹广�� + /// </summary> + private void InitializeComponent() + { + this.splitMain = new System.Windows.Forms.SplitContainer(); + this.plOpBtns = new System.Windows.Forms.Panel(); + this.chkManualConfirm = new System.Windows.Forms.CheckBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.chkContinueMode = new System.Windows.Forms.CheckBox(); + this.chkOfflineRun = new System.Windows.Forms.CheckBox(); + this.chkOfflineCalib = new System.Windows.Forms.CheckBox(); + this.btnCalcuMatrix = new System.Windows.Forms.Button(); + this.btnContinueCalib = new System.Windows.Forms.Button(); + this.btnSnap = new System.Windows.Forms.Button(); + this.btnLoadOfflineImages = new System.Windows.Forms.Button(); + this.btnStepRun = new System.Windows.Forms.Button(); + this.btnStartCalib = new System.Windows.Forms.Button(); + this.splitConfig = new System.Windows.Forms.SplitContainer(); + this.lvConfigs = new System.Windows.Forms.ListView(); + this.clIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.clConfigData = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.propGridConfig = new System.Windows.Forms.PropertyGrid(); + this.plImage = new System.Windows.Forms.Panel(); + this.stspStatus = new System.Windows.Forms.StatusStrip(); + this.tsslStepHint = new System.Windows.Forms.ToolStripStatusLabel(); + this.tsslInfo = new System.Windows.Forms.ToolStripStatusLabel(); + ((System.ComponentModel.ISupportInitialize)(this.splitMain)).BeginInit(); + this.splitMain.Panel1.SuspendLayout(); + this.splitMain.Panel2.SuspendLayout(); + this.splitMain.SuspendLayout(); + this.plOpBtns.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitConfig)).BeginInit(); + this.splitConfig.Panel1.SuspendLayout(); + this.splitConfig.Panel2.SuspendLayout(); + this.splitConfig.SuspendLayout(); + this.stspStatus.SuspendLayout(); + this.SuspendLayout(); + // + // splitMain + // + this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitMain.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitMain.Location = new System.Drawing.Point(0, 0); + this.splitMain.Name = "splitMain"; + // + // splitMain.Panel1 + // + this.splitMain.Panel1.Controls.Add(this.plOpBtns); + this.splitMain.Panel1.Controls.Add(this.splitConfig); + // + // splitMain.Panel2 + // + this.splitMain.Panel2.Controls.Add(this.plImage); + this.splitMain.Panel2.Controls.Add(this.stspStatus); + this.splitMain.Size = new System.Drawing.Size(836, 514); + this.splitMain.SplitterDistance = 278; + this.splitMain.TabIndex = 0; + // + // plOpBtns + // + this.plOpBtns.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.plOpBtns.Controls.Add(this.chkManualConfirm); + this.plOpBtns.Controls.Add(this.label3); + this.plOpBtns.Controls.Add(this.label2); + this.plOpBtns.Controls.Add(this.label1); + this.plOpBtns.Controls.Add(this.chkContinueMode); + this.plOpBtns.Controls.Add(this.chkOfflineRun); + this.plOpBtns.Controls.Add(this.chkOfflineCalib); + this.plOpBtns.Controls.Add(this.btnCalcuMatrix); + this.plOpBtns.Controls.Add(this.btnContinueCalib); + this.plOpBtns.Controls.Add(this.btnSnap); + this.plOpBtns.Controls.Add(this.btnLoadOfflineImages); + this.plOpBtns.Controls.Add(this.btnStepRun); + this.plOpBtns.Controls.Add(this.btnStartCalib); + this.plOpBtns.Location = new System.Drawing.Point(3, 354); + this.plOpBtns.Name = "plOpBtns"; + this.plOpBtns.Size = new System.Drawing.Size(272, 158); + this.plOpBtns.TabIndex = 1; + // + // chkManualConfirm + // + this.chkManualConfirm.AutoSize = true; + this.chkManualConfirm.Location = new System.Drawing.Point(11, 132); + this.chkManualConfirm.Name = "chkManualConfirm"; + this.chkManualConfirm.Size = new System.Drawing.Size(72, 16); + this.chkManualConfirm.TabIndex = 3; + this.chkManualConfirm.Text = "浜哄伐纭"; + this.chkManualConfirm.UseVisualStyleBackColor = true; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(6, 117); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(257, 12); + this.label3.TabIndex = 2; + this.label3.Text = "------------------------------------------"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 76); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(257, 12); + this.label2.TabIndex = 2; + this.label2.Text = "------------------------------------------"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(7, 35); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(257, 12); + this.label1.TabIndex = 2; + this.label1.Text = "------------------------------------------"; + // + // chkContinueMode + // + this.chkContinueMode.AutoSize = true; + this.chkContinueMode.Location = new System.Drawing.Point(90, 95); + this.chkContinueMode.Name = "chkContinueMode"; + this.chkContinueMode.Size = new System.Drawing.Size(72, 16); + this.chkContinueMode.TabIndex = 1; + this.chkContinueMode.Text = "杩炵画鎷嶇収"; + this.chkContinueMode.UseVisualStyleBackColor = true; + this.chkContinueMode.CheckedChanged += new System.EventHandler(this.chkContinueMode_CheckedChanged); + // + // chkOfflineRun + // + this.chkOfflineRun.AutoSize = true; + this.chkOfflineRun.Location = new System.Drawing.Point(90, 56); + this.chkOfflineRun.Name = "chkOfflineRun"; + this.chkOfflineRun.Size = new System.Drawing.Size(72, 16); + this.chkOfflineRun.TabIndex = 1; + this.chkOfflineRun.Text = "绂荤嚎妯″紡"; + this.chkOfflineRun.UseVisualStyleBackColor = true; + // + // chkOfflineCalib + // + this.chkOfflineCalib.AutoSize = true; + this.chkOfflineCalib.Location = new System.Drawing.Point(90, 15); + this.chkOfflineCalib.Name = "chkOfflineCalib"; + this.chkOfflineCalib.Size = new System.Drawing.Size(72, 16); + this.chkOfflineCalib.TabIndex = 1; + this.chkOfflineCalib.Text = "绂荤嚎妯″紡"; + this.chkOfflineCalib.UseVisualStyleBackColor = true; + // + // btnCalcuMatrix + // + this.btnCalcuMatrix.Location = new System.Drawing.Point(168, 50); + this.btnCalcuMatrix.Name = "btnCalcuMatrix"; + this.btnCalcuMatrix.Size = new System.Drawing.Size(93, 23); + this.btnCalcuMatrix.TabIndex = 0; + this.btnCalcuMatrix.Text = "鏍囧畾缁撴灉杩愮畻"; + this.btnCalcuMatrix.UseVisualStyleBackColor = true; + this.btnCalcuMatrix.Click += new System.EventHandler(this.btnCalcuMatrix_Click); + // + // btnContinueCalib + // + this.btnContinueCalib.Location = new System.Drawing.Point(87, 128); + this.btnContinueCalib.Name = "btnContinueCalib"; + this.btnContinueCalib.Size = new System.Drawing.Size(75, 23); + this.btnContinueCalib.TabIndex = 0; + this.btnContinueCalib.Text = "缁х画鏍囧畾"; + this.btnContinueCalib.UseVisualStyleBackColor = true; + this.btnContinueCalib.Visible = false; + this.btnContinueCalib.Click += new System.EventHandler(this.btnContinueCalib_Click); + // + // btnSnap + // + this.btnSnap.Location = new System.Drawing.Point(8, 91); + this.btnSnap.Name = "btnSnap"; + this.btnSnap.Size = new System.Drawing.Size(75, 23); + this.btnSnap.TabIndex = 0; + this.btnSnap.Text = "閲嶆柊鎷嶇収"; + this.btnSnap.UseVisualStyleBackColor = true; + this.btnSnap.Click += new System.EventHandler(this.btnSnap_Click); + // + // btnLoadOfflineImages + // + this.btnLoadOfflineImages.Location = new System.Drawing.Point(168, 9); + this.btnLoadOfflineImages.Name = "btnLoadOfflineImages"; + this.btnLoadOfflineImages.Size = new System.Drawing.Size(93, 23); + this.btnLoadOfflineImages.TabIndex = 0; + this.btnLoadOfflineImages.Text = "杞藉叆绂荤嚎鍥剧墖"; + this.btnLoadOfflineImages.UseVisualStyleBackColor = true; + this.btnLoadOfflineImages.Click += new System.EventHandler(this.btnLoadOfflineImages_Click); + // + // btnStepRun + // + this.btnStepRun.Location = new System.Drawing.Point(8, 50); + this.btnStepRun.Name = "btnStepRun"; + this.btnStepRun.Size = new System.Drawing.Size(75, 23); + this.btnStepRun.TabIndex = 0; + this.btnStepRun.Text = "鍗曟杩愮畻"; + this.btnStepRun.UseVisualStyleBackColor = true; + this.btnStepRun.Click += new System.EventHandler(this.btnStepRun_Click); + // + // btnStartCalib + // + this.btnStartCalib.Location = new System.Drawing.Point(8, 9); + this.btnStartCalib.Name = "btnStartCalib"; + this.btnStartCalib.Size = new System.Drawing.Size(75, 23); + this.btnStartCalib.TabIndex = 0; + this.btnStartCalib.Text = "寮�濮嬫爣瀹�"; + this.btnStartCalib.UseVisualStyleBackColor = true; + this.btnStartCalib.Click += new System.EventHandler(this.btnStartCalib_Click); + // + // splitConfig + // + this.splitConfig.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitConfig.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitConfig.Location = new System.Drawing.Point(3, 0); + this.splitConfig.Name = "splitConfig"; + this.splitConfig.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitConfig.Panel1 + // + this.splitConfig.Panel1.Controls.Add(this.lvConfigs); + // + // splitConfig.Panel2 + // + this.splitConfig.Panel2.Controls.Add(this.propGridConfig); + this.splitConfig.Size = new System.Drawing.Size(272, 348); + this.splitConfig.SplitterDistance = 61; + this.splitConfig.TabIndex = 0; + // + // lvConfigs + // + this.lvConfigs.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.clIndex, + this.clConfigData}); + this.lvConfigs.Dock = System.Windows.Forms.DockStyle.Fill; + this.lvConfigs.FullRowSelect = true; + this.lvConfigs.Location = new System.Drawing.Point(0, 0); + this.lvConfigs.MultiSelect = false; + this.lvConfigs.Name = "lvConfigs"; + this.lvConfigs.Size = new System.Drawing.Size(272, 61); + this.lvConfigs.TabIndex = 0; + this.lvConfigs.UseCompatibleStateImageBehavior = false; + this.lvConfigs.View = System.Windows.Forms.View.Details; + this.lvConfigs.SelectedIndexChanged += new System.EventHandler(this.lvConfigs_SelectedIndexChanged); + // + // clIndex + // + this.clIndex.Text = "搴忓彿"; + // + // clConfigData + // + this.clConfigData.Text = "閰嶇疆"; + this.clConfigData.Width = 200; + // + // propGridConfig + // + this.propGridConfig.Dock = System.Windows.Forms.DockStyle.Fill; + this.propGridConfig.Location = new System.Drawing.Point(0, 0); + this.propGridConfig.Name = "propGridConfig"; + this.propGridConfig.Size = new System.Drawing.Size(272, 283); + this.propGridConfig.TabIndex = 0; + this.propGridConfig.ToolbarVisible = false; + // + // plImage + // + this.plImage.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.plImage.Location = new System.Drawing.Point(-1, 0); + this.plImage.Name = "plImage"; + this.plImage.Size = new System.Drawing.Size(555, 489); + this.plImage.TabIndex = 1; + // + // stspStatus + // + this.stspStatus.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tsslStepHint, + this.tsslInfo}); + this.stspStatus.Location = new System.Drawing.Point(0, 492); + this.stspStatus.Name = "stspStatus"; + this.stspStatus.Size = new System.Drawing.Size(554, 22); + this.stspStatus.TabIndex = 0; + this.stspStatus.Text = "statusStrip1"; + // + // tsslStepHint + // + this.tsslStepHint.Name = "tsslStepHint"; + this.tsslStepHint.Size = new System.Drawing.Size(28, 17); + this.tsslStepHint.Text = " "; + // + // tsslInfo + // + this.tsslInfo.Name = "tsslInfo"; + this.tsslInfo.Size = new System.Drawing.Size(28, 17); + this.tsslInfo.Text = " "; + // + // CtrlCalib9PDynamic + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitMain); + this.Name = "CtrlCalib9PDynamic"; + this.Size = new System.Drawing.Size(836, 514); + this.Load += new System.EventHandler(this.CtrlCalib9PDynamic_Load); + this.splitMain.Panel1.ResumeLayout(false); + this.splitMain.Panel2.ResumeLayout(false); + this.splitMain.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitMain)).EndInit(); + this.splitMain.ResumeLayout(false); + this.plOpBtns.ResumeLayout(false); + this.plOpBtns.PerformLayout(); + this.splitConfig.Panel1.ResumeLayout(false); + this.splitConfig.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitConfig)).EndInit(); + this.splitConfig.ResumeLayout(false); + this.stspStatus.ResumeLayout(false); + this.stspStatus.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitMain; + private System.Windows.Forms.Panel plOpBtns; + private System.Windows.Forms.SplitContainer splitConfig; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.CheckBox chkContinueMode; + private System.Windows.Forms.CheckBox chkOfflineRun; + private System.Windows.Forms.CheckBox chkOfflineCalib; + private System.Windows.Forms.Button btnCalcuMatrix; + private System.Windows.Forms.Button btnSnap; + private System.Windows.Forms.Button btnLoadOfflineImages; + private System.Windows.Forms.Button btnStepRun; + private System.Windows.Forms.Button btnStartCalib; + private System.Windows.Forms.Panel plImage; + private System.Windows.Forms.StatusStrip stspStatus; + private System.Windows.Forms.ToolStripStatusLabel tsslStepHint; + private System.Windows.Forms.ToolStripStatusLabel tsslInfo; + private System.Windows.Forms.ListView lvConfigs; + private System.Windows.Forms.ColumnHeader clIndex; + private System.Windows.Forms.ColumnHeader clConfigData; + private System.Windows.Forms.PropertyGrid propGridConfig; + private System.Windows.Forms.CheckBox chkManualConfirm; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button btnContinueCalib; + } +} diff --git a/src/A032.Process/Calibration/CtrlCalib9PDynamic.cs b/src/A032.Process/Calibration/CtrlCalib9PDynamic.cs new file mode 100644 index 0000000..dcf6c73 --- /dev/null +++ b/src/A032.Process/Calibration/CtrlCalib9PDynamic.cs @@ -0,0 +1,277 @@ +锘縰sing System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Bro.Common.Helper; +using Bro.Common.Interface; +using Bro.Common.Base; +using Bro.Common.UI; +using Bro.Common.PubSub; +using static Bro.Common.Helper.EnumHelper; +using Bro.Common.Model; +using HalconDotNet; +using System.Threading; + +namespace A032.Process.Calibration +{ + [Device("Calibration_9P_Dynamic", "鍔ㄦ��9鐐规爣瀹�", EnumHelper.DeviceAttributeType.OperationConfigCtrl)] + public partial class CtrlCalib9PDynamic : UserControl, IConfigCtrl<CameraBase, CalibrationConfigCollection> + { + PubSubCenter PubSubCenter = PubSubCenter.GetInstance(); + AutoResetEvent _confirmHandle = new AutoResetEvent(false); + + public CtrlCalib9PDynamic() + { + InitializeComponent(); + } + + public CtrlCalib9PDynamic(ProcessControl process, IDevice device, IOperationConfig config, Action<List<CalibrationConfig>> finalCalculation) + { + InitializeComponent(); + + ProcessControl = process; + Camera = device as CameraBase; + Config = config as CalibrationConfigCollection; + FinalCalculation = finalCalculation; + } + + public CalibrationConfigCollection Config { get; set; } + public CameraBase Camera { get; set; } + public ProcessControl ProcessControl { get; set; } + public Action<List<CalibrationConfig>> FinalCalculation { get; set; } + + public CalibrationConfigCollection GetConfig() + { + return null; + } + + public void LoadConfig(CalibrationConfigCollection config) + { + lvConfigs.Items.Clear(); + + for (int i = 0; i < Config.Configs.Count; i++) + { + ListViewItem item = new ListViewItem((i + 1).ToString()); + item.SubItems.Add(Config.Configs[i].GetDisplayText()); + + lvConfigs.Items.Add(item); + + Config.Configs[i].PropertyChanged -= CtrlCalib9PDynamic_PropertyChanged; + Config.Configs[i].PropertyChanged += CtrlCalib9PDynamic_PropertyChanged; + } + + if (lvConfigs.Items.Count > 0) + { + lvConfigs.Items[0].Selected = true; + } + } + + private void CtrlCalib9PDynamic_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + OnCalibPropertyChanged(); + } + + private void OnCalibPropertyChanged() + { + if (this.InvokeRequired) + { + this.Invoke(new Action(() => OnCalibPropertyChanged())); + } + else + { + for (int i = 0; i < Config.Configs.Count; i++) + { + if (Config.Configs[i].Image != null) + { + lvConfigs.Items[i].BackColor = Color.GreenYellow; + } + else + { + lvConfigs.Items[i].BackColor = Color.Transparent; + } + } + } + } + + Canvas _canvas = new Canvas(); + private void CtrlCalib9PDynamic_Load(object sender, EventArgs e) + { + _canvas.IsShowElementList = true; + _canvas.Dock = DockStyle.Fill; + plImage.Controls.Add(_canvas); + + RemoveHandles(); + + if (Camera != null) + { + Camera.UpdateShowImage -= Camera_UpdateShowImage; + Camera.UpdateShowImage += Camera_UpdateShowImage; + } + + LoadConfig(Config); + + PubSubCenter.Subscribe(PubTag.CalibStepDone.ToString(), CalibStepDone); + PubSubCenter.Subscribe(PubTag.CalibAllDone.ToString(), CalibAllDone); + } + + public void RemoveHandles() + { + if (Camera != null) + { + Camera.UpdateShowImage -= Camera_UpdateShowImage; + } + PubSubCenter.RemoveSubscriber(PubTag.CalibStepDone.ToString(), CalibStepDone); + PubSubCenter.RemoveSubscriber(PubTag.CalibAllDone.ToString(), CalibAllDone); + + chkContinueMode.Checked = false; + } + + AutoResetEvent _imageShowedHandle = new AutoResetEvent(false); + private void Camera_UpdateShowImage(CameraBase camera, Bitmap image, string imagePath) + { + _canvas.LoadImage(image); + _imageShowedHandle.Set(); + } + + private object CalibAllDone(ISubscriber arg1, object arg2, object arg3) + { + string msg = arg3.ToString(); + tsslInfo.Text = msg; + + return null; + } + + private object CalibStepDone(ISubscriber arg1, object arg2, object arg3) + { + int index = Convert.ToInt32(arg2); + + _canvas.LoadImage(Config.Configs[index].Image); + _canvas.Elements.Clear(); + CrossHair ch = new CrossHair(new CalibrationPoint(Config.Configs[index].ImageMarkPoint, Config.Configs[index].CurrentPlatPoint)); + _canvas.Elements.Add(ch); + + tsslInfo.Text = $"姝ラ{index + 1}瀹屾垚"; + + if (chkManualConfirm.Checked) + { + this.Invoke(new Action(() => btnContinueCalib.Visible = true)); ; + _confirmHandle.WaitOne(); + } + + return null; + } + + int _selectedStepIndex = -1; + private void lvConfigs_SelectedIndexChanged(object sender, EventArgs e) + { + if (lvConfigs.SelectedItems.Count <= 0) + return; + + _selectedStepIndex = lvConfigs.SelectedIndices[0]; + var stepConfig = Config.Configs[_selectedStepIndex]; + propGridConfig.SelectedObject = stepConfig; + + tsslStepHint.Text = $"{(_selectedStepIndex + 1).ToString()}/{Config.Configs.Count}"; + + if (stepConfig.Image != null) + { + _canvas.LoadImage(stepConfig.Image); + _canvas.Elements.Clear(); + _canvas.Elements.Add(new CrossHair(new CalibrationPoint(stepConfig.ImageMarkPoint, stepConfig.CurrentPlatPoint))); + } + } + + private void btnStartCalib_Click(object sender, EventArgs e) + { + if (chkOfflineCalib.Checked) + { + //ProcessControl.Calibration_Pick_9P_Dynamic_Offline(Config.Configs); + } + else + { + //ProcessControl.SendCalibStartSignal(Config.TriggerAddress); + } + } + + private void btnLoadOfflineImages_Click(object sender, EventArgs e) + { + Config.Configs.ForEach(c => + { + if (!string.IsNullOrWhiteSpace(c.OfflineImagePath)) + { + c.Image = (Bitmap)Image.FromFile(c.OfflineImagePath); + } + }); + + tsslInfo.Text = "绂荤嚎鍥剧墖杞藉叆瀹屾垚"; + } + + private void btnStepRun_Click(object sender, EventArgs e) + { + //CalibrationConfig config = propGridConfig.SelectedObject as CalibrationConfig; + //if (!chkOfflineRun.Checked) + //{ + // ProcessControl.CalibMarkPoint(Camera, config, _selectedStepIndex + 1); + //} + //else + //{ + // ProcessControl.CalibMarkPoint(_canvas.MAP, config, _selectedStepIndex + 1); + //} + + //tsslInfo.Text = $"鍗曟杩愮畻瀹屾垚銆傛爣璁扮偣鍧愭爣锛歿config.ImageMarkPoint.X},{config.ImageMarkPoint.Y}"; + } + + private void btnCalcuMatrix_Click(object sender, EventArgs e) + { + FinalCalculation.Invoke(Config.Configs); + } + + private void btnSnap_Click(object sender, EventArgs e) + { + CalibrationConfig config = propGridConfig.SelectedObject as CalibrationConfig; + Camera.UploadOperationConfig(config.CameraOpConfig); + Camera.Snapshot(config.CameraOpConfig, out HObject hImage); + hImage.Dispose(); + } + + private void chkContinueMode_CheckedChanged(object sender, EventArgs e) + { + if (chkContinueMode.Checked) + { + Task.Run(() => + { + HalconRelatedCameraOprerationConfigBase config = (propGridConfig.SelectedObject as CalibrationConfig).CameraOpConfig; + bool temp = config.IsSaveImage; + config.IsSaveImage = false; + + while (chkContinueMode.Checked) + { + try + { + Camera.UploadOperationConfig(config); + Camera.Snapshot(); + + _imageShowedHandle.WaitOne(3000); + } + catch (Exception) + { + } + } + + config.IsSaveImage = temp; + }); + } + } + + private void btnContinueCalib_Click(object sender, EventArgs e) + { + _confirmHandle.Set(); + btnContinueCalib.Visible = false; + } + } +} diff --git a/src/A032.Process/Calibration/CtrlCalib9PDynamic.resx b/src/A032.Process/Calibration/CtrlCalib9PDynamic.resx new file mode 100644 index 0000000..1b481a6 --- /dev/null +++ b/src/A032.Process/Calibration/CtrlCalib9PDynamic.resx @@ -0,0 +1,123 @@ +锘�<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="stspStatus.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/src/A032.Process/Calibration/FrmCalib9PDynamic.Designer.cs b/src/A032.Process/Calibration/FrmCalib9PDynamic.Designer.cs new file mode 100644 index 0000000..1c2fab9 --- /dev/null +++ b/src/A032.Process/Calibration/FrmCalib9PDynamic.Designer.cs @@ -0,0 +1,47 @@ +锘縩amespace A032.Process.Calibration +{ + partial class FrmCalib9PDynamic + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.SuspendLayout(); + // + // FrmCalib9PDynamic + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Name = "FrmCalib9PDynamic"; + this.Text = "鏍囧畾鐣岄潰"; + this.Load += new System.EventHandler(this.FrmCalib9PDynamic_Load); + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/src/A032.Process/Calibration/FrmCalib9PDynamic.cs b/src/A032.Process/Calibration/FrmCalib9PDynamic.cs new file mode 100644 index 0000000..e780681 --- /dev/null +++ b/src/A032.Process/Calibration/FrmCalib9PDynamic.cs @@ -0,0 +1,50 @@ +锘縰sing Bro.Common.Base; +using Bro.Common.Interface; +using Bro.Common.UI; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace A032.Process.Calibration +{ + public partial class FrmCalib9PDynamic : Form + { + public FrmCalib9PDynamic() + { + InitializeComponent(); + } + + public FrmCalib9PDynamic(ProcessControl process, IDevice device, IOperationConfig config, Action<List<CalibrationConfig>> finalCalculation) + { + InitializeComponent(); + + Device = device as CameraBase; + Config = config as CalibrationConfigCollection; + FinalCalculation = finalCalculation; + CtrlCalib9PDynamic = new CtrlCalib9PDynamic(process, device, config, finalCalculation); + } + + CameraBase Device { get; set; } + CalibrationConfigCollection Config { get; set; } + CtrlCalib9PDynamic CtrlCalib9PDynamic { get; set; } + Action<List<CalibrationConfig>> FinalCalculation { get; set; } + + private void FrmCalib9PDynamic_Load(object sender, EventArgs e) + { + CtrlCalib9PDynamic.Dock = DockStyle.Fill; + this.Controls.Add(CtrlCalib9PDynamic); + + this.FormClosing += (send, ee) => + { + CtrlCalib9PDynamic.RemoveHandles(); + }; + } + } +} diff --git a/src/A032.Process/Calibration/FrmCalib9PDynamic.resx b/src/A032.Process/Calibration/FrmCalib9PDynamic.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/src/A032.Process/Calibration/FrmCalib9PDynamic.resx @@ -0,0 +1,120 @@ +锘�<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/src/A032.Process/ProcessConfig.cs b/src/A032.Process/ProcessConfig.cs index 3640397..200811f 100644 --- a/src/A032.Process/ProcessConfig.cs +++ b/src/A032.Process/ProcessConfig.cs @@ -46,6 +46,12 @@ [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor<HikCameraInitialConfig>), typeof(UITypeEditor))] public List<HikCameraInitialConfig> CameraConfigCollection { get; set; } = new List<HikCameraInitialConfig>(); + + [Category("璁惧閰嶇疆")] + [Description("AGV灏忚溅璁惧缁戝畾閰嶇疆锛岄厤缃粦瀹氱殑AGV锛屾満鍣ㄤ汉鍜岀浉鏈轰俊鎭�")] + [TypeConverter(typeof(CollectionCountConvert))] + [Editor(typeof(ComplexCollectionEditor<AGVBindUnit>), typeof(UITypeEditor))] + public List<AGVBindUnit> AGVBindCollection { get; set; } = new List<AGVBindUnit>(); #endregion #region 鎿嶄綔閰嶇疆 @@ -55,15 +61,15 @@ //[Editor(typeof(MonitorSetBindEditor), typeof(UITypeEditor))] //public Dictionary<string, MonitorSet> PLCMonitorSet { get; set; } = new Dictionary<string, MonitorSet>(); - ///// <summary> - ///// 鎿嶄綔閰嶇疆鐨勫瓧鍏搁泦鍚� - ///// Key锛歁ethodCode锛孷alue锛氭搷浣滈厤缃� - ///// </summary> - //[Category("鎿嶄綔閰嶇疆")] - //[Description("鎿嶄綔閰嶇疆闆嗗悎")] - //[TypeConverter(typeof(CollectionCountConvert))] - //[Editor(typeof(OperationConfigBindEditor), typeof(UITypeEditor))] - //public Dictionary<string, IOperationConfig> ProcessOpConfigDict { get; set; } = new Dictionary<string, IOperationConfig>(); + /// <summary> + /// 鎿嶄綔閰嶇疆鐨勫瓧鍏搁泦鍚� + /// Key锛歁ethodCode锛孷alue锛氭搷浣滈厤缃� + /// </summary> + [Category("鎿嶄綔閰嶇疆")] + [Description("榛樿鎿嶄綔閰嶇疆闆嗗悎")] + [TypeConverter(typeof(CollectionCountConvert))] + [Editor(typeof(OperationConfigBindEditor), typeof(UITypeEditor))] + public Dictionary<string, IOperationConfig> ProcessOpConfigDict { get; set; } = new Dictionary<string, IOperationConfig>(); //[Category("鐩戝惉鍜屾搷浣滈厤缃�")] //[Description("鐩戝惉鎿嶄綔閰嶇疆闆嗗悎")] @@ -140,8 +146,44 @@ [Category("璺緞鐩稿叧")] [Description("鍚勪綅缃爣瀹氱煩闃�")] [TypeConverter(typeof(CollectionCountConvert))] - [Editor(typeof(ComplexCollectionEditor<PositionMatrix>), typeof(UITypeEditor))] - public List<PositionMatrix> MatrixCollection { get; set; } = new List<PositionMatrix>(); + [Editor(typeof(ComplexCollectionEditor<PositionVisionConfig>), typeof(UITypeEditor))] + public List<PositionVisionConfig> VisionConfigCollection { get; set; } = new List<PositionVisionConfig>(); + + /// <summary> + /// 绌篢ray涓婃枡闃堝�硷紝AGV涓婄殑绌簍ray鏁伴噺涓嶅ぇ浜庤鏁板�兼椂锛孉GV鍙互鎵ц绌篢ray涓婃枡浠诲姟 + /// </summary> + [Category("闃堝�艰缃�")] + [Description("绌篢ray涓婃枡闃堝�硷紝AGV涓婄殑绌簍ray鏁伴噺涓嶅ぇ浜庤鏁板�兼椂锛孉GV鍙互鎵ц绌篢ray涓婃枡浠诲姟")] + public int AGV_EmptyTrayThreshold { get; set; } = 0; + + /// <summary> + /// 婊ray涓嬫枡闃堝�硷紝AGV涓婄殑婊ray鏁伴噺涓嶅皬浜庤鏁板�兼椂锛孉GV鍙互鎵ц婊ray涓嬫枡浠诲姟 + /// </summary> + [Category("闃堝�艰缃�")] + [Description("婊ray涓嬫枡闃堝�硷紝AGV涓婄殑婊ray鏁伴噺涓嶅皬浜庤鏁板�兼椂锛孉GV鍙互鎵ц婊ray涓嬫枡浠诲姟")] + public int AGV_FullTrayThreshold { get; set; } = 10; + + /// <summary> + /// 浜х嚎蹇欐椂鎷嶇収纭绛夊緟闂撮殧锛屼互绉掍负鍗曚綅 + /// </summary> + [Category("闃堝�艰缃�")] + [Description("浜х嚎蹇欐椂鎷嶇収纭绛夊緟闂撮殧锛屼互绉掍负鍗曚綅")] + public int LineBusyWaitInterval { get; set; } = 60; + + /// <summary> + /// 浜х嚎蹇欐椂鎷嶇収閲嶈瘯娆℃暟 + /// </summary> + [Category("闃堝�艰缃�")] + [Description("浜х嚎蹇欐椂鎷嶇収閲嶈瘯娆℃暟")] + public int LineBusyRetryTimes { get; set; } = 10; + + [Category("闃堝�艰缃�")] + [Description("鏈哄彴鍘嬫満婊ray鏁伴噺")] + public int Machine_FullTrayNum { get; set; } + + [Category("闃堝�艰缃�")] + [Description("鏈哄彴鍘嬫満绌篢ray鏁伴噺")] + public int Machine_EmptyTrayNum { get; set; } #region Ignore [Browsable(false)] @@ -190,55 +232,5 @@ [JsonIgnore] public virtual bool IsDBSave { get; set; } = false; #endregion - } - - public class PathPosition : IComplexDisplay - { - [Category("瀵艰埅璺緞")] - [Description("璺緞鑺傜偣浠g爜")] - public string PositionCode { get; set; } - - [Category("瀵艰埅璺緞")] - [Description("璺緞鑺傜偣鎻忚堪")] - public string Description { get; set; } - - public string GetDisplayText() - { - return $"{PositionCode}-{Description}"; - } - } - - public class PositionMatrix : IComplexDisplay - { - [Category("浣嶇疆鐭╅樀")] - [Description("浣嶇疆浠g爜")] - [TypeConverter(typeof(PositionCodeConverter))] - public string PositionCode { get; set; } - - [Category("浣嶇疆鐭╅樀")] - [Description("璇ヤ綅缃爣瀹氱煩闃�")] - [TypeConverter(typeof(SimpleCollectionConvert<double>))] - public List<double> Matrix { get; set; } = new List<double>(); - - public string GetDisplayText() - { - return $"{PositionCode}:{string.Join(",", Matrix)}"; - } - } - - public class PositionCodeConverter : ComboBoxItemTypeConvert - { - public override void GetConvertHash() - { - using (var scope = GlobalVar.Container.BeginLifetimeScope()) - { - var config = scope.Resolve<ProcessConfig>(); - - config.PositionCollection.ForEach(p => - { - _hash[p.PositionCode] = $"{p.PositionCode}-{p.Description}"; - }); - } - } } } diff --git a/src/A032.Process/ProcessControl.cs b/src/A032.Process/ProcessControl.cs index 7d26329..04638ee 100644 --- a/src/A032.Process/ProcessControl.cs +++ b/src/A032.Process/ProcessControl.cs @@ -179,7 +179,7 @@ ProcessState = DeviceState.DSOpen; - QueryRobotIO(); + //QueryRobotIO(); //Task.Run(() => //{ @@ -298,9 +298,43 @@ InitialAGVs(); InitialCameras(); + InitialAGVBindUnit(); + + InitialMachineTrayNums(); + AutoFacRegister(); LogAsync(DateTime.Now, "Process Initialized", ""); + } + + private void InitialMachineTrayNums() + { + machineEmptyTrayDict = Config.PositionCollection.Where(u => u.Description == PathPositionDefinition.UnloadEmptyTray).ToDictionary(p => p.PositionNo, p => 0); + + machineFullTrayDict = Config.PositionCollection.Where(u => u.Description == PathPositionDefinition.LoadFullTray).ToDictionary(p => p.PositionNo, p => 0); + } + + private void InitialAGVBindUnit() + { + Config.AGVBindCollection.ForEach(u => + { + if (AGVDict.ContainsKey(u.AGVId)) + { + u.AGV = AGVDict[u.AGVId]; + } + + if (RobotDict.ContainsKey(u.RobotId)) + { + u.Robot = RobotDict[u.RobotId]; + } + + if (CameraDict.ContainsKey(u.CameraId)) + { + u.Camera = CameraDict[u.CameraId]; + } + + u.OnMethodInvoke = OnBindUnitTaskInvoke; + }); } private void InitialCameras() @@ -321,11 +355,11 @@ plc.InitialConfig = c; PLCDict[plc.InitialConfig.ID] = plc; - plc.OnMonitorAlarm -= Plc_OnMonitorAlarm; - plc.OnMonitorInvoke -= Plc_OnMonitorInvoke; + plc.OnMonitorAlarm -= OnMonitorAlarm; + plc.OnMonitorInvoke -= OnMonitorInvoke; - plc.OnMonitorAlarm += Plc_OnMonitorAlarm; - plc.OnMonitorInvoke += Plc_OnMonitorInvoke; + plc.OnMonitorAlarm += OnMonitorAlarm; + plc.OnMonitorInvoke += OnMonitorInvoke; }); } @@ -336,6 +370,14 @@ AuboRobotDriver robot = new AuboRobotDriver(); robot.InitialConfig = c; RobotDict[robot.InitialConfig.ID] = robot; + + robot.OnMsgReceived = OnRobotMsgReceived; + + robot.OnMonitorAlarm -= OnMonitorAlarm; + robot.OnMonitorInvoke -= OnMonitorInvoke; + + robot.OnMonitorAlarm += OnMonitorAlarm; + robot.OnMonitorInvoke += OnMonitorInvoke; }); } @@ -346,6 +388,9 @@ SeerAGVDriver agv = new SeerAGVDriver(); agv.InitialConfig = c; AGVDict[agv.InitialConfig.ID] = agv; + + agv.OnAGVPositoinChanged = OnAGVPositionChanged; + agv.OnAGVTaskStatusChanged = OnAGVTaskStatusChanged; }); } @@ -447,7 +492,7 @@ /// </summary> protected Dictionary<string, HDevEngineTool> _halconToolDict = new Dictionary<string, HDevEngineTool>(); - private void InitialProcessMethods() + public virtual void InitialProcessMethods() { _processMethodDict = new Dictionary<string, MethodInfo>(); var methods = this.GetType().GetMethods().ToList(); @@ -458,7 +503,7 @@ { _processMethodDict[attr.MethodCode] = m; - #region 鍒濆鍖朒alconTool + #region 鍒濆鍖朒alconTool 鏍规嵁processMethod鐨勭壒鎬ф潵閰嶇疆 //if (attr.DeviceType.EndsWith("Camera")) //{ // if (StationConfig.ProcessOpConfigDict.Keys.Contains(attr.MethodCode)) @@ -484,29 +529,39 @@ } }); - #region 鍒濆鍖朒alconTool + #region 鍒濆鍖朒alconTool 鏍规嵁閰嶇疆鐨勬帴鍙g被鍨嬫潵閰嶇疆 _halconToolDict = new Dictionary<string, HDevEngineTool>(); Config.PLCConfigCollection.SelectMany(plcConfig => plcConfig.MonitorSetCollection).Select(ms => ms.OpConfig).ToList().ForEach(c => + { + InitialHalconTool(c as IHalconToolPath); + }); + + Config.VisionConfigCollection.ForEach(c => + { + InitialHalconTool(c as IHalconToolPath); + }); + #endregion + } + + private void InitialHalconTool(IHalconToolPath toolPath) + { + //IHalconToolPath toolPath = c as IHalconToolPath; + if (toolPath != null) + { + toolPath.GetHalconToolPathList().ForEach(path => { - IHalconToolPath toolPath = c as IHalconToolPath; - if (toolPath != null) + if (!string.IsNullOrWhiteSpace(path) && !_halconToolDict.ContainsKey(path)) { - toolPath.GetHalconToolPathList().ForEach(path => - { - if (!string.IsNullOrWhiteSpace(path)) - { - string directoryPath = Path.GetDirectoryName(path); - string fileName = Path.GetFileNameWithoutExtension(path); + string directoryPath = Path.GetDirectoryName(path); + string fileName = Path.GetFileNameWithoutExtension(path); - HDevEngineTool tool = new HDevEngineTool(directoryPath); - tool.LoadProcedure(fileName); + HDevEngineTool tool = new HDevEngineTool(directoryPath); + tool.LoadProcedure(fileName); - _halconToolDict[path] = tool; - } - }); + _halconToolDict[path] = tool; } }); - #endregion + } } public List<IDevice> GetDeviceList() @@ -521,9 +576,8 @@ return list; } - #region PLC鐩戝惉 - - private void Plc_OnMonitorInvoke(DateTime dt, MonitorSet monitorSet) + #region IMonitor鐩戝惉 + private void OnMonitorInvoke(DateTime dt, IDevice device, MonitorSet monitorSet) { IOperationConfig config = monitorSet.OpConfig; string methodCode = monitorSet.MethodCode; @@ -535,7 +589,7 @@ try { //鏈塈OperationConfig鍙傛暟鐨勮皟鐢� - res = _processMethodDict[methodCode].Invoke(this, new object[] { config }); + res = _processMethodDict[methodCode].Invoke(this, new object[] { config, device }); reTryTimes = -1; } catch (Exception invokeEX) //娴佺▼鍔ㄤ綔寮傚父澶辫触 @@ -653,7 +707,7 @@ #endregion } - private void Plc_OnMonitorAlarm(DateTime dt, WarningSet warning, bool isAlarmRaised) + private void OnMonitorAlarm(DateTime dt, IDevice device, WarningSet warning, bool isAlarmRaised) { } @@ -1099,7 +1153,7 @@ protected Dictionary<string, Queue<string>> CameraBitmapDict = new Dictionary<string, Queue<string>>(); //protected Dictionary<string, Bitmap> CameraBitmapDict = new Dictionary<string, Bitmap>(); - protected HObject CollectHImage(CameraBase camera, IOperationConfig opConfig, string cameraId, string methodCode) + protected HObject CollectHImage(CameraBase camera, IOperationConfig opConfig, string methodCode) { HObject hImage = null; @@ -1131,9 +1185,6 @@ camera.UploadOperationConfig(opConfig); camera.Snapshot(opConfig, out hImage); - - //SaveTempImage(cameraName, camera.ImageFilePath); - //SaveTempImage(camera, cameraId); if (cameraConifg.DelayAfter > 0) { diff --git a/src/A032.Process/ProcessControl_Calibration.cs b/src/A032.Process/ProcessControl_Calibration.cs new file mode 100644 index 0000000..49fa9ee --- /dev/null +++ b/src/A032.Process/ProcessControl_Calibration.cs @@ -0,0 +1,101 @@ +锘縰sing A032.Process.Calibration; +using Bro.Common.Base; +using Bro.Common.Helper; +using Bro.Common.Interface; +using Bro.Common.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace A032.Process +{ + public partial class ProcessControl + { + [ProcessMethod("CalibrationCollection", "RobotCalibration", "鏈哄櫒浜�9鐐规爣瀹�", true)] + public ProcessResponse RobotCalibration(IOperationConfig config) + { + return new ProcessResponse(true); + } + + [ProcessMethod("CalibrationCollection", "StandardPointCalibration", "鏍囧噯鐐逛綅鏍囧畾", true)] + public ProcessResponse StandardPointCalibration(IOperationConfig config) + { + return new ProcessResponse(true); + } + + public void SendCalibrationStartSignal(int stepNum) + { + + } + + private int MultipleStepsCalibration(CalibrationConfigCollection configs, Action<List<CalibrationConfig>> FinalCalculation) + { + throw new NotImplementedException(); + + //configs.Configs.ForEach(c => + //{ + // c.Image = null; + //}); + + //if (string.IsNullOrWhiteSpace(configs.CameraId) || !CameraDict.ContainsKey(configs.CameraId)) + //{ + // throw new ProcessException("鏍囧畾閰嶇疆鏈厤缃纭殑鐩告満缂栧彿"); + //} + + //if (string.IsNullOrWhiteSpace(configs.PositionCode)) + //{ + // throw new ProcessException("鏍囧畾閰嶇疆鏈寚瀹氳矾寰勪綅缃�"); + //} + + //CameraBase camera = CameraDict[configs.CameraId]; + //FrmCalib9PDynamic frm9PDynamic = new FrmCalib9PDynamic(this, camera, configs, FinalCalculation); + //frm9PDynamic.ShowDialog(); + + //if (configs.InputPara == null || configs.InputPara.Count <= 0) + //{ + // return (int)PLCReplyValue.NG; + //} + + //if (configs.InputPara[0] <= 0 || configs.InputPara[0] > configs.Configs.Count) + //{ + // configs.InputPara = null; + // return (int)PLCReplyValue.IGNORE; + //} + + //int sequence = configs.InputPara[0]; + + ////绗竴娆� + //if (sequence == 1) + //{ + // configs.Configs.ForEach(c => + // { + // c.Image = null; + // c.OfflineImagePath = ""; + // c.CurrentPlatPoint = new CustomizedPoint(); + // c.ImageMarkPoint = new CustomizedPoint(); + // }); + //} + + //CalibrationConfig stepConfig = configs.Configs[sequence - 1]; + + //HDevEngineTool tool = _halconToolDict[] + + //CalibMarkPoint(camera, stepConfig, sequence); + + ////鑾峰彇褰撳墠骞冲彴鐐逛綅 + //stepConfig.CurrentPlatPoint = new CustomizedPoint(_monitorList.Skip(locationStartIndex).Take(4).ToList()); + ////stepConfig.CurrentPlatPoint = new CustomizedPoint(configs.InputPara.Skip(1).Take(4).ToList()); + + ////鏈�鍚庝竴娆� + //if (sequence == configs.Configs.Count) + //{ + // FinalCalculation?.Invoke(configs.Configs); + //} + + //configs.InputPara = null; + //return (int)PLCReplyValue.OK; + } + } +} diff --git a/src/A032.Process/ProcessControl_Method.cs b/src/A032.Process/ProcessControl_Method.cs index 1ff4d8d..61fb662 100644 --- a/src/A032.Process/ProcessControl_Method.cs +++ b/src/A032.Process/ProcessControl_Method.cs @@ -1,7 +1,10 @@ -锘縰sing Bro.Common.Helper; +锘縰sing Bro.Common.Base; +using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; +using Bro.Device.AuboRobot; using Bro.Device.HikCamera; +using Bro.Device.SeerAGV; using HalconDotNet; using System; using System.Collections.Generic; @@ -14,24 +17,1063 @@ namespace A032.Process { - public enum ResultState - { - OK = 1, - NG = -1, - Undetermined = -2, - } - public partial class ProcessControl { + Dictionary<int, int> machineFullTrayDict = new Dictionary<int, int>(); + Dictionary<int, int> machineEmptyTrayDict = new Dictionary<int, int>(); + List<TaskAssignInfo> taskAssignedList = new List<TaskAssignInfo>(); + + private void OnAGVTaskStatusChanged(SeerAGVDriver agv, AGVTaskStatus taskStatus) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.AGVId == agv.Id); + + if (bind == null) + { + throw new ProcessException("鏈兘鏍规嵁AGV淇℃伅鑾峰彇缁戝畾璁惧淇℃伅", null); + } + + if (bind.AGVDest == agv.CurrentPosition && taskStatus == AGVTaskStatus.Completed) + { + //PathPosition loadEmptyTrayPosition = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); + + //if (bind.AGVDest == loadEmptyTrayPosition.PositionCode) + //{ + // bind.RobotStatus = TaskStatus.Running; + //} + + bind.AGVStatus = TaskStatus.Available; + } + } + + private void OnAGVPositionChanged(SeerAGVDriver agv, string positionCode) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.AGVId == agv.Id); + + if (bind == null) + { + throw new ProcessException("鏈兘鏍规嵁AGV淇℃伅鑾峰彇缁戝畾璁惧淇℃伅", null); + } + + if (bind.AGVDest == positionCode && agv.TaskStatus == AGVTaskStatus.Completed) + { + //PathPosition loadEmptyTrayPosition = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); + + //if (bind.AGVDest == loadEmptyTrayPosition.PositionCode) + //{ + // bind.RobotStatus = TaskStatus.Running; + //} + + bind.AGVStatus = TaskStatus.Available; + } + } + + private void OnRobotMsgReceived(DateTime dt, AuboRobotDriver robot, RobotMsg msg) + { + LogAsync(dt, robot.Name + "鎺ユ敹淇℃伅", msg.GetDisplayText()); + + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robot.Id); + + if (bind == null) + { + throw new ProcessException("鏈兘鏍规嵁鏈哄櫒浜轰俊鎭幏鍙栫粦瀹氳澶囦俊鎭�", null); + } + + List<AGVTaskModel> models = new List<AGVTaskModel>(); + + switch (msg.Action) + { + case RobotMsgAction.Load: + { + switch (msg.Para1) + { + case RobotMsgParas.EmptyTray: + { + bind.RobotStatus = bind.AGVStatus = TaskStatus.Available; + } + break; + case RobotMsgParas.FullTray: + { + machineFullTrayDict[msg.Para2]--; + bind.CurrentFullTray = int.Parse(msg.Datas[1]); + + if (machineFullTrayDict[msg.Para2] > 0 && !bind.IsFullTrayFull) + { + RobotMsg_UnloadEmptyTray.Para2 = msg.Para2; + robot.SendMsg(RobotMsg_UnloadEmptyTray, true); + } + else + { + bind.RobotStatus = TaskStatus.Available; + } + } + break; + default: + break; + } + } + break; + case RobotMsgAction.Unload: + { + switch (msg.Para1) + { + case RobotMsgParas.EmptyTray: + { + machineEmptyTrayDict[msg.Para2]++; + bind.CurrentEmptyTray = int.Parse(msg.Datas[0]); + + if (machineEmptyTrayDict[msg.Para2] < Config.Machine_EmptyTrayNum) + { + bind.RobotIOHandle.Reset(); + bind.RobotIOHandle.WaitOne(); + + if (!bind.IsFullTrayFull) + { + RobotMsg_UnloadEmptyTray.Para2 = msg.Para2; + robot.SendMsg(RobotMsg_UnloadEmptyTray, true); + } + } + else + { + bind.RobotStatus = TaskStatus.Available; + } + } + break; + case RobotMsgParas.FullTray: + { + bind.CurrentFullTray = int.Parse(msg.Datas[1]); + + bind.RobotIOHandle.Reset(); + bind.RobotIOHandle.WaitOne(); + + if (!bind.IsFullTrayEmpty) + { + Camera_UnloadFullTray(robot.Id, msg.Para2); + } + } + break; + default: + break; + } + } + break; + case RobotMsgAction.Move: + { + switch (msg.Para1) + { + case RobotMsgParas.LineSnap: + { + Camera_UnloadFullTray(robot.Id, msg.Para2); + } + break; + case RobotMsgParas.LoadFullTraySnap: + { + Camera_LoadFullTray(robot.Id, msg.Para2); + } + break; + case RobotMsgParas.UnloadEmptyTraySnap: + { + Camera_UnloadEmptyTray(robot.Id, msg.Para2); + } + break; + case RobotMsgParas.Home: + { + bind.RobotStatus = TaskStatus.Available; + } + break; + default: + break; + } + } + break; + case RobotMsgAction.Calibration: + { + + } + break; + case RobotMsgAction.StandardPoint: + { + + } + break; + default: + break; + } + + if (models.Count > 0) + { + models.ForEach(model => + { + if (!bind.TaskList.Any(t => t.MethodFunc.Method.Name == model.MethodFunc.Method.Name)) + { + model.OpConfig = new AGVBindOpConfig(bind.Id); + bind.TaskList.Add(model); + } + }); + } + } + public void QueryRobotIO() { - + RobotDict.Values.ToList().ForEach(r => + { + r.SendMsg(RobotMsgAction.IO, RobotMsgParas.Query, 0); + }); } - [ProcessMethod("HikCamera", "RobotCorrection", "鎷嶆憚锛岀‘璁ゆ満鍣ㄤ汉璋冩暣浣嶇疆", true)] - public ProcessResponse RobotCorrection(IOperationConfig config) + private void OnBindUnitTaskInvoke(AGVBindUnit bind) { + var task = bind.TaskList[0]; + var response = task.MethodFunc.Invoke(task.OpConfig, task.Device); + } + + #region Robot鐩戝惉浜嬩欢 + private void AddNewTaskToBind(string robotId, List<AGVTaskModel> models) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId); + + if (bind == null) + { + throw new ProcessException("鏈兘鏍规嵁鏈哄櫒浜轰俊鎭幏鍙栫粦瀹氳澶囦俊鎭�", null); + } + + AddNewTaskToBind(bind, models); + } + + private void AddNewTaskToBind(AGVBindUnit bind, List<AGVTaskModel> models) + { + if (models.Count > 0) + { + models.ForEach(model => + { + if (!bind.TaskList.Any(t => t.MethodFunc.Method.Name == model.MethodFunc.Method.Name)) + { + model.OpConfig = new AGVBindOpConfig(bind.Id); + bind.TaskList.Add(model); + } + }); + } + } + + [ProcessMethod("", "Robot_Monitor_Alarm", "鏈哄櫒浜虹洃鍚簨浠�-鎶ヨ", true)] + public ProcessResponse Robot_Monitor_Alarm(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); + + if (bind == null) + { + throw new ProcessException("鏈兘鏍规嵁鏈哄櫒浜轰俊鎭幏鍙栫粦瀹氳澶囦俊鎭�", null); + } + + bind.AGV.PauseTask(); + bind.RobotStatus = TaskStatus.Warning; + return new ProcessResponse(true); } + + [ProcessMethod("", "Robot_Monitor_EmptyTrayEmpty", "鏈哄櫒浜虹洃鍚簨浠�-绌篢ray鍖哄煙娓呯┖", true)] + public ProcessResponse Robot_Monitor_EmptyTrayEmpty(IOperationConfig config, IDevice device) + { + bool isEmptyTrayEmpty = config.InputPara[0] == 1; + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); + if (isEmptyTrayEmpty) + { + bind.IsEmptyTrayEmpty = true; + + Task.Run(() => + { + Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadEmptyTray; + while (bind.IsEmptyTrayEmpty && bind.TaskList.Count == 0 && !bind.TaskList.Any(u => u.MethodFunc.Method.Name == action.Method.Name)) + { + if (bind.TaskList.Count == 0) + { + List<AGVTaskModel> models = new List<AGVTaskModel>(); + models.Add(new AGVTaskModel(TaskAvailableLevel.Both, AGV_LoadEmptyTray)); + models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, AfterEmptyTrayPositionArrived)); + + AddNewTaskToBind(device.Id, models); + } + else + { + Thread.Sleep(500); + } + } + }); + + } + else + { + bind.IsEmptyTrayEmpty = false; + } + + return new ProcessResponse(true); + } + + [ProcessMethod("", "Robot_Monitor_EmptyTrayEmpty", "鏈哄櫒浜虹洃鍚簨浠�-婊ray鍖哄煙鏀炬弧", true)] + public ProcessResponse Robot_Monitor_FullTrayFull(IOperationConfig config, IDevice device) + { + bool isFullTrayFull = config.InputPara[0] == 1; + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); + if (isFullTrayFull) + { + bind.IsFullTrayFull = true; + + Task.Run(() => + { + Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadFullTray; + while (bind.IsFullTrayFull && !bind.TaskList.Any(u => u.MethodFunc.Method.Name == action.Method.Name)) + { + if (bind.TaskList.Count == 0) + { + List<AGVTaskModel> models = new List<AGVTaskModel>(); + models.Add(new AGVTaskModel(TaskAvailableLevel.Both, AGV_UnloadFullTray)); + models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, Robot_UnloadFullTray)); + + AddNewTaskToBind(device.Id, models); + } + else + { + Thread.Sleep(500); + } + } + }); + } + else + { + bind.IsFullTrayFull = false; + } + + bind.RobotIOHandle.Set(); + + return new ProcessResponse(true); + } + + [ProcessMethod("", "Robot_Monitor_FullTrayEmpty", "鏈哄櫒浜虹洃鍚簨浠�-婊ray鍖哄煙娓呯┖", true)] + public ProcessResponse Robot_Monitor_FullTrayEmpty(IOperationConfig config, IDevice device) + { + bool isFullTrayEmpty = config.InputPara[0] == 1; + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); + bind.IsFullTrayEmpty = isFullTrayEmpty; + + bind.RobotIOHandle.Set(); + + return new ProcessResponse(true); + } + + //[ProcessMethod("", "Robot_Monitor_LoadEmptyTrayReady", "鏈哄櫒浜虹洃鍚簨浠�-杞藉叆绌篢ray灏辩华", true)] + //public ProcessResponse Robot_Monitor_LoadEmptyTrayReady(IOperationConfig config, IDevice device) + //{ + // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); + + // if (bind == null) + // { + // throw new ProcessException("鏈兘鏍规嵁鏈哄櫒浜轰俊鎭幏鍙栫粦瀹氳澶囦俊鎭�", null); + // } + + // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); + // if (bind.AGV.CurrentPosition != position.PositionCode) + // { + // new ProcessException("涓婄┖Tray瀹屾垚淇″彿浠呭湪涓婄┖Tray鍦扮偣鏈夋晥", null); + // return new ProcessResponse(true); + // } + + // List<AGVTaskModel> models = new List<AGVTaskModel>(); + // models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, EmptyTrayReady)); + // AddNewTaskToBind(bind, models); + + // return new ProcessResponse(true); + //} + + [ProcessMethod("", "Robot_Monitor_Reset", "鏈哄櫒浜虹洃鍚簨浠�-Reset澶嶄綅", true)] + public ProcessResponse Robot_Monitor_Reset(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); + + if (bind == null) + { + throw new ProcessException("鏈兘鏍规嵁鏈哄櫒浜轰俊鎭幏鍙栫粦瀹氳澶囦俊鎭�", null); + } + bind.AGV.CancelTask(); + + //isEmptyTrayTaskAssigned = false; + //isFullTrayTaskAssigned = false; + + taskAssignedList.RemoveAll(u => u.AgvId == device.Id); + + bind.TaskList.Clear(); + bind.RobotStatus = bind.AGVStatus = TaskStatus.Available; + + return new ProcessResponse(true); + } + #endregion + + #region 绌篢ray涓婃枡 + [ProcessMethod("", "AGV_LoadEmptyTray", "AGV鍘诲線绌篢ray涓婃枡", true)] + public ProcessResponse AGV_LoadEmptyTray(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃┖Tray涓婃枡鐐�"); + } + + bind.AGVDest = position.PositionCode; + bind.AGV.TaskOrder(position.PositionCode); + + bind.AGVStatus = TaskStatus.Running; + + return new ProcessResponse(true); + } + + [ProcessMethod("", "AfterEmptyTrayPositionArrived", "鍒拌揪绌篢ray涓婃枡鐐�", true)] + public ProcessResponse AfterEmptyTrayPositionArrived(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃┖Tray涓婃枡鐐�", null); + } + + if (bind.AGV.CurrentPosition != position.PositionCode) + { + throw new ProcessException("AGV灏氭湭鍒拌揪绌篢ray涓婃枡鐐�", null); + } + + bind.Robot.SendMsg(RobotMsgAction.Load, RobotMsgParas.EmptyTray, 0); + bind.RobotStatus = TaskStatus.Running; + + return new ProcessResponse(true); + } + + //[ProcessMethod("", "EmptyTrayReady", "绌篢ray涓婃枡瀹屾垚", true)] + //public ProcessResponse EmptyTrayReady(IOperationConfig config, IDevice device) + //{ + // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + // bind.RobotStatus = bind.AGVStatus = TaskStatus.Available; + + // return new ProcessResponse(true); + //} + #endregion + + #region 绌篢ray寰�鏈哄彴涓嬫枡 + //bool isEmptyTrayNeed = false; + //bool isEmptyTrayTaskAssigned = false; + RobotMsg RobotMsg_UnloadEmptyTray = new RobotMsg(); + + [ProcessMethod("", "PLC_NoticeEmptyTray", "PLC閫氱煡闇�瑕佷笂绌篢ray", true)] + public ProcessResponse PLC_NoticeEmptyTray(IOperationConfig config, IDevice device) + { + if (config.InputPara == null || config.InputPara.Count == 0) + { + throw new ProcessException("涓婄┖Tray鏂规硶鏈厤缃緭鍏ュ弬鏁�", null); + } + + bool isEmptyTrayNeed = config.InputPara[0] == 1; + + if (isEmptyTrayNeed) + { + var position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadEmptyTray && u.DeviceOwner == device.Id); + + machineEmptyTrayDict[position.PositionNo] = 0; + + if (!taskAssignedList.Any(u => u.PositionNo == position.PositionNo)) + { + taskAssignedList.Add(new TaskAssignInfo() + { + IsTaskNeed = true, + IsTaskAssgined = false, + PositionNo = position.PositionNo, + }); + } + + CheckEmptyTrayTask(position.PositionNo); + } + + return new ProcessResponse(true); + } + + private async void CheckEmptyTrayTask(int positionNo) + { + await Task.Run(() => + { + var taskStatus = taskAssignedList.FirstOrDefault(u => u.PositionNo == positionNo); + + if (taskStatus == null) + return; + + while (taskStatus.IsTaskNeed && !taskStatus.IsTaskAssgined) + { + Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadEmptyTray; + + //if (!Config.AGVBindCollection.Any(b => b.TaskList.Any(t => t.MethodFunc.Method.Name == action.Method.Name))) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.UnitStatus == TaskStatus.Available); + if (bind != null) + { + var position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNo); + AGVTaskModel model_AGV = new AGVTaskModel(TaskAvailableLevel.Both, action, new AGVBindOpConfig(bind.Id, position)); + AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, Robot_UnloadEmptyTray, new AGVBindOpConfig(bind.Id)); + + bind.TaskList.Add(model_AGV); + bind.TaskList.Add(model_Robot); + + taskStatus.IsTaskAssgined = true; + taskStatus.AgvId = bind.AGVId; + } + } + + Thread.Sleep(300); + } + }); + } + + //[ProcessMethod("", "AGV_UnloadEmptyTray", "AGV鍘诲線鍗歌浇绌篢ray鏂欎綅缃�", true)] + public ProcessResponse AGV_UnloadEmptyTray(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + + PathPosition position = (config as AGVBindOpConfig).Position; + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃┖Tray涓嬫枡鐐�"); + } + + bind.AGVDest = position.PositionCode; + bind.AGV.TaskOrder(position.PositionCode); + + bind.AGVStatus = TaskStatus.Running; + + return new ProcessResponse(true); + } + + //[ProcessMethod("", "Robot_UnloadEmptyTray", "鏈哄櫒浜鸿繍鍔ㄨ嚦绌篢ray鎷嶇収浣嶇疆", true)] + public ProcessResponse Robot_UnloadEmptyTray(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadEmptyTray && u.PositionCode == bind.AGV.CurrentPosition); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃┖Tray涓嬫枡鐐�"); + } + + taskAssignedList.RemoveAll(u => u.AgvId == bind.AGVId && u.PositionNo == position.PositionNo); + + bind.RobotStatus = TaskStatus.Running; + bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.UnloadEmptyTraySnap, position.PositionNo); + + return new ProcessResponse(true); + } + + //[ProcessMethod("", "Camera_UnloadEmptyTray", "鐩告満纭绌篢ray鍗歌浇鏈哄櫒浜轰綅缃皟鏁�", true)] + //public ProcessResponse Camera_UnloadEmptyTray(IOperationConfig config, IDevice device) + //{ + // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + + // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadEmptyTray); + + // if (position == null) + // { + // throw new ProcessException("璺緞閰嶇疆鏈缃┖Tray涓嬫枡鐐�"); + // } + + // if (bind.AGV.CurrentPosition != position.PositionCode) + // { + // throw new ProcessException("AGV褰撳墠鏈浜庣┖Tray涓嬫枡鐐�"); + // } + + // PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); + + // if (visionConfig == null) + // { + // throw new ProcessException("鏈厤缃鐩告満鐨勭┖Tray涓嬫枡鐐圭殑瑙嗚鎿嶄綔閰嶇疆"); + // } + + // float x = 0; + // float y = 0; + // float angle = 0; + + // using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_UnloadEmptyTray")) + // { + // string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; + // if (!_halconToolDict.ContainsKey(toolPath)) + // { + // throw new ProcessException($"鏈厤缃瓹amera_UnloadEmptyTray鐨勮瑙夌畻娉曡矾寰�"); + // } + + // var tool = _halconToolDict[toolPath]; + // tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); + // tool.RunProcedure(); + + // x = (float)tool.GetResultTuple("OUTPUT_X").D; + // y = (float)tool.GetResultTuple("OUTPUT_Y").D; + // angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; + // } + + // if (x <= 0 || y <= 0) + // { + // throw new ProcessException("Camera_UnloadEmptyTray瑙嗚璁$畻鑾峰彇鐐逛綅涓嶅彲灏忎簬0"); + // } + + // float dx = visionConfig.StandardPoint.X - x; + // float dy = visionConfig.StandardPoint.Y - y; + + // HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); + + // bind.Robot.SendMsg(RobotMsgAction.Unload, RobotMsgParas.EmptyTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); + + // return new ProcessResponse(true); + //} + + public ProcessResponse Camera_UnloadEmptyTray(string robotId, int positionNum) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId); + + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNum); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃┖Tray涓嬫枡鐐�"); + } + + if (bind.AGV.CurrentPosition != position.PositionCode) + { + throw new ProcessException("AGV褰撳墠鏈浜庣┖Tray涓嬫枡鐐�"); + } + + PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); + + if (visionConfig == null) + { + throw new ProcessException("鏈厤缃鐩告満鐨勭┖Tray涓嬫枡鐐圭殑瑙嗚鎿嶄綔閰嶇疆"); + } + + float x = 0; + float y = 0; + float angle = 0; + + using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_UnloadEmptyTray")) + { + string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; + if (!_halconToolDict.ContainsKey(toolPath)) + { + throw new ProcessException($"鏈厤缃瓹amera_UnloadEmptyTray鐨勮瑙夌畻娉曡矾寰�"); + } + + var tool = _halconToolDict[toolPath]; + tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); + tool.RunProcedure(); + + x = (float)tool.GetResultTuple("OUTPUT_X").D; + y = (float)tool.GetResultTuple("OUTPUT_Y").D; + angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; + } + + if (x <= 0 || y <= 0) + { + throw new ProcessException("Camera_UnloadEmptyTray瑙嗚璁$畻鑾峰彇鐐逛綅涓嶅彲灏忎簬0"); + } + + float dx = visionConfig.StandardPoint.X - x; + float dy = visionConfig.StandardPoint.Y - y; + + HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); + + //bind.Robot.SendMsg(RobotMsgAction.Unload, RobotMsgParas.EmptyTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); + RobotMsg_UnloadEmptyTray.Action = RobotMsgAction.Unload; + RobotMsg_UnloadEmptyTray.Para1 = RobotMsgParas.EmptyTray; + RobotMsg_UnloadEmptyTray.Para2 = position.PositionNo; + RobotMsg_UnloadEmptyTray.Datas = new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }.ConvertAll(s => s.ToString()).ToList(); + bind.Robot.SendMsg(RobotMsg_UnloadEmptyTray, true); + + return new ProcessResponse(true); + } + #endregion + + #region 浠庢満鍙颁笂婊ray + //bool isFullTrayNeed = false; + //bool isFullTrayTaskAssigned = false; + RobotMsg RobotMsg_LoadFullTray = new RobotMsg(); + + [ProcessMethod("", "PLC_NoticeFullTray", "PLC閫氱煡婊ray闇�瑕佸彇璧�", true)] + public ProcessResponse PLC_NoticeFullTray(IOperationConfig config, IDevice device) + { + if (config.InputPara == null || config.InputPara.Count == 0) + { + throw new ProcessException("涓婄┖Tray鏂规硶鏈厤缃緭鍏ュ弬鏁�", null); + } + + bool isFullTrayNeed = config.InputPara[0] == 1; + if (isFullTrayNeed) + { + var position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadFullTray && u.DeviceOwner == device.Id); + + machineFullTrayDict[position.PositionNo] = Config.Machine_FullTrayNum; + + if (!taskAssignedList.Any(u => u.PositionNo == position.PositionNo)) + { + taskAssignedList.Add(new TaskAssignInfo() + { + IsTaskNeed = true, + IsTaskAssgined = false, + PositionNo = position.PositionNo, + }); + } + + CheckFullTrayTask(position.PositionNo); + } + + return new ProcessResponse(true); + } + + private async void CheckFullTrayTask(int positionNo) + { + await Task.Run(() => + { + var taskStatus = taskAssignedList.FirstOrDefault(u => u.PositionNo == positionNo); + + if (taskStatus == null) + return; + + while (taskStatus.IsTaskNeed && !taskStatus.IsTaskAssgined) + { + Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadFullTray; + + //if (!Config.AGVBindCollection.Any(b => b.TaskList.Any(t => t.MethodFunc.Method.Name == action.Method.Name))) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.UnitStatus == TaskStatus.Available); + if (bind != null) + { + var position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNo); + AGVTaskModel model_AGV = new AGVTaskModel(TaskAvailableLevel.Both, action, new AGVBindOpConfig(bind.Id, position)); + AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, Robot_LoadFullTray, new AGVBindOpConfig(bind.Id)); + + bind.TaskList.Add(model_AGV); + bind.TaskList.Add(model_Robot); + + taskStatus.IsTaskAssgined = true; + taskStatus.AgvId = bind.AGVId; + } + } + + Thread.Sleep(300); + } + }); + } + + [ProcessMethod("", "AGV_LoadFullTray", "AGV鍘诲線婊ray涓婃枡浣嶇疆", true)] + public ProcessResponse AGV_LoadFullTray(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + + PathPosition position = (config as AGVBindOpConfig).Position; + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃弧Tray涓婃枡鐐�"); + } + + bind.AGVDest = position.PositionCode; + bind.AGV.TaskOrder(position.PositionCode); + + bind.AGVStatus = TaskStatus.Running; + + return new ProcessResponse(true); + } + + [ProcessMethod("", "Robot_LoadFullTray", "鏈哄櫒浜鸿繍鍔ㄨ嚦婊ray鎷嶇収浣嶇疆", true)] + public ProcessResponse Robot_LoadFullTray(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadFullTray && u.PositionCode == bind.AGV.CurrentPosition); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃弧Tray涓婃枡鐐�"); + } + + //if (bind.AGV.CurrentPosition != position.PositionCode) + //{ + // throw new ProcessException("AGV褰撳墠鏈浜庢弧Tray涓婃枡鐐�"); + //} + + bind.RobotStatus = TaskStatus.Running; + bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LoadFullTraySnap, position.PositionNo); + + return new ProcessResponse(true); + } + + //[ProcessMethod("", "Camera_LoadFullTray", "鐩告満纭婊ray涓婃枡鏈哄櫒浜轰綅缃皟鏁�", true)] + //public ProcessResponse Camera_LoadFullTray(IOperationConfig config, IDevice device) + //{ + // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + + // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadFullTray); + + // if (position == null) + // { + // throw new ProcessException("璺緞閰嶇疆鏈缃弧Tray涓婃枡鐐�"); + // } + + // if (bind.AGV.CurrentPosition != position.PositionCode) + // { + // throw new ProcessException("AGV褰撳墠鏈浜庢弧Tray涓婃枡鐐�"); + // } + + // PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); + + // if (visionConfig == null) + // { + // throw new ProcessException("鏈厤缃鐩告満鐨勬弧Tray涓婃枡鐐圭殑瑙嗚鎿嶄綔閰嶇疆"); + // } + + // float x = 0; + // float y = 0; + // float angle = 0; + + // using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_LoadFullTray")) + // { + // string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; + // if (!_halconToolDict.ContainsKey(toolPath)) + // { + // throw new ProcessException($"鏈厤缃瓹amera_LoadFullTray鐨勮瑙夌畻娉曡矾寰�"); + // } + + // var tool = _halconToolDict[toolPath]; + // tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); + // tool.RunProcedure(); + + // x = (float)tool.GetResultTuple("OUTPUT_X").D; + // y = (float)tool.GetResultTuple("OUTPUT_Y").D; + // angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; + // } + + // if (x <= 0 || y <= 0) + // { + // throw new ProcessException("Camera_LoadFullTray瑙嗚璁$畻鑾峰彇鐐逛綅涓嶅彲灏忎簬0"); + // } + + // float dx = visionConfig.StandardPoint.X - x; + // float dy = visionConfig.StandardPoint.Y - y; + + // HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); + + // bind.Robot.SendMsg(RobotMsgAction.Load, RobotMsgParas.FullTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); + + // return new ProcessResponse(true); + //} + + public ProcessResponse Camera_LoadFullTray(string robotId, int positionNum) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId); + + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNum); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃弧Tray涓婃枡鐐�"); + } + + if (bind.AGV.CurrentPosition != position.PositionCode) + { + throw new ProcessException("AGV褰撳墠鏈浜庢弧Tray涓婃枡鐐�"); + } + + PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); + + if (visionConfig == null) + { + throw new ProcessException("鏈厤缃鐩告満鐨勬弧Tray涓婃枡鐐圭殑瑙嗚鎿嶄綔閰嶇疆"); + } + + float x = 0; + float y = 0; + float angle = 0; + + using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_LoadFullTray")) + { + string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; + if (!_halconToolDict.ContainsKey(toolPath)) + { + throw new ProcessException($"鏈厤缃瓹amera_LoadFullTray鐨勮瑙夌畻娉曡矾寰�"); + } + + var tool = _halconToolDict[toolPath]; + tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); + tool.RunProcedure(); + + x = (float)tool.GetResultTuple("OUTPUT_X").D; + y = (float)tool.GetResultTuple("OUTPUT_Y").D; + angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; + } + + if (x <= 0 || y <= 0) + { + throw new ProcessException("Camera_LoadFullTray瑙嗚璁$畻鑾峰彇鐐逛綅涓嶅彲灏忎簬0"); + } + + float dx = visionConfig.StandardPoint.X - x; + float dy = visionConfig.StandardPoint.Y - y; + + HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); + + //bind.Robot.SendMsg(RobotMsgAction.Load, RobotMsgParas.FullTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); + RobotMsg_LoadFullTray.Action = RobotMsgAction.Load; + RobotMsg_LoadFullTray.Para1 = RobotMsgParas.FullTray; + RobotMsg_LoadFullTray.Para2 = position.PositionNo; + RobotMsg_LoadFullTray.Datas = new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }.ConvertAll(s => s.ToString()).ToList(); + bind.Robot.SendMsg(RobotMsg_LoadFullTray, true); + + return new ProcessResponse(true); + } + #endregion + + #region 婊ray浜х嚎涓嬫枡 + [ProcessMethod("", "AGV_UnloadFullTray", "AGV鍘诲線鍗歌浇婊ray鏂�", true)] + public ProcessResponse AGV_UnloadFullTray(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃弧Tray涓嬫枡鐐�"); + } + + bind.AGVDest = position.PositionCode; + bind.AGV.TaskOrder(position.PositionCode); + + bind.AGVStatus = TaskStatus.Running; + + return new ProcessResponse(true); + } + + [ProcessMethod("", "Robot_UnloadFullTray", "鏈哄櫒浜哄嵏杞芥弧Tray", true)] + public ProcessResponse Robot_UnloadFullTray(IOperationConfig config, IDevice device) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃弧Tray涓嬫枡鐐�"); + } + + if (bind.AGV.CurrentPosition != position.PositionCode) + { + throw new ProcessException("AGV褰撳墠鏈浜庢弧Tray涓嬫枡鐐�"); + } + + bind.RobotStatus = TaskStatus.Running; + bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LineSnap, position.PositionNo); + + return new ProcessResponse(true); + } + + //[ProcessMethod("", "Camera_UnloadFullTray", "鐩告満鎿嶄綔鍗歌浇婊ray", true)] + //public ProcessResponse Camera_UnloadFullTray(IOperationConfig config, IDevice device) + public ProcessResponse Camera_UnloadFullTray(string robotId, int positionNum) + { + var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId); + PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray && u.PositionNo == positionNum); + + if (position == null) + { + throw new ProcessException("璺緞閰嶇疆鏈缃弧Tray涓嬫枡鐐�"); + } + + if (bind.AGV.CurrentPosition != position.PositionCode) + { + throw new ProcessException("AGV褰撳墠鏈浜庢弧Tray涓嬫枡鐐�"); + } + + PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); + + if (visionConfig == null) + { + throw new ProcessException("鏈厤缃鐩告満鐨勬弧Tray涓嬫枡鐐圭殑瑙嗚鎿嶄綔閰嶇疆"); + } + + bool isLineReady = false; + int reTryTime = Config.LineBusyRetryTimes; + + do + { + using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_UnloadFullTray")) + { + string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; + if (!_halconToolDict.ContainsKey(toolPath)) + { + throw new ProcessException($"鏈厤缃瓹amera_UnloadFullTray鐨勮瑙夌畻娉曡矾寰�"); + } + + _halconToolDict[toolPath].SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_Result", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); + _halconToolDict[toolPath].RunProcedure(); + + isLineReady = _halconToolDict[toolPath].GetResultTuple("OUTPUT_Result").I == 1; + } + + if (!isLineReady) + { + Thread.Sleep(Config.LineBusyWaitInterval * 1000); + reTryTime--; + } + else + { + reTryTime = 0; + } + } while (reTryTime > 0); + + //if (!isLineReady) + //{ + // bind.Robot.SendMsg(RobotMsgType.Send, -1, true, RobotMsgAction.State, RobotMsgParas.LineSnap, new List<string>() { "-1" }); + // throw new ProcessException("浜х嚎蹇欙紝绛夊緟瓒呮椂"); + //} + //else + //{ + // bind.Robot.SendMsg(RobotMsgType.Send, -1, true, RobotMsgAction.State, RobotMsgParas.LineSnap, new List<string>() { "1" }); + //} + + if (isLineReady) + { + bind.Robot.SendMsg(RobotMsgAction.Unload, RobotMsgParas.FullTray, position.PositionNo); + } + else + { + bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.Home, position.PositionNo); + } + + return new ProcessResponse(true); + } + #endregion + } + + public class AGVBindOpConfig : OperationConfigBase + { + public string BindId { get; set; } + public PathPosition Position { get; set; } + + public AGVBindOpConfig() { } + + public AGVBindOpConfig(string bindId, PathPosition position = null) + { + BindId = bindId; + Position = position; + } + } + + public class TaskAssignInfo + { + public int PositionNo { get; set; } + + public bool IsTaskNeed { get; set; } = false; + + public bool IsTaskAssgined { get; set; } = false; + + public string AgvId { get; set; } } } diff --git a/src/Bro.Common.Model/Helper/ExceptionHelper.cs b/src/Bro.Common.Model/Helper/ExceptionHelper.cs index 446c170..db85703 100644 --- a/src/Bro.Common.Model/Helper/ExceptionHelper.cs +++ b/src/Bro.Common.Model/Helper/ExceptionHelper.cs @@ -50,7 +50,7 @@ // PositionIndex = positionIndex; //} - public ProcessException(string error, Exception ex) : base(error, ex) + public ProcessException(string error, Exception ex = null) : base(error, ex) { ErrorCode = error; OriginalException = ex; diff --git a/src/Bro.Common.Model/Interface/IMonitor.cs b/src/Bro.Common.Model/Interface/IMonitor.cs index 5747279..2d9e1b3 100644 --- a/src/Bro.Common.Model/Interface/IMonitor.cs +++ b/src/Bro.Common.Model/Interface/IMonitor.cs @@ -1,4 +1,5 @@ -锘縰sing System; +锘縰sing Bro.Common.Interface; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,8 +7,8 @@ namespace Bro.Common.Model.Interface { - public delegate void OnMonitorInvokeDelegate(DateTime dt, MonitorSet monitorSet); - public delegate void OnMonitorAlarmDelegate(DateTime dt, WarningSet warning, bool isAlarmRaised); + public delegate void OnMonitorInvokeDelegate(DateTime dt, IDevice device, MonitorSet monitorSet); + public delegate void OnMonitorAlarmDelegate(DateTime dt, IDevice device, WarningSet warning, bool isAlarmRaised); public interface IMonitor { List<int> GetMonitorValues(int startAddress, int length); diff --git a/src/Bro.Common.Model/Interface/IStationProcess.cs b/src/Bro.Common.Model/Interface/IStationProcess.cs index 8e526d6..64d39df 100644 --- a/src/Bro.Common.Model/Interface/IStationProcess.cs +++ b/src/Bro.Common.Model/Interface/IStationProcess.cs @@ -48,6 +48,8 @@ /// </summary> /// <returns></returns> List<ProcessMethodAttribute> CollectProcessMethods(); + + void InitialProcessMethods(); #endregion #region 浜嬩欢 diff --git a/src/Bro.Device.AuboRobot/AuboRobotConfig.cs b/src/Bro.Device.AuboRobot/AuboRobotConfig.cs index 190ee8b..50cfc4a 100644 --- a/src/Bro.Device.AuboRobot/AuboRobotConfig.cs +++ b/src/Bro.Device.AuboRobot/AuboRobotConfig.cs @@ -1,8 +1,11 @@ 锘縰sing Bro.Common.Base; using Bro.Common.Helper; +using Bro.Common.Model; using System; using System.Collections.Generic; using System.ComponentModel; +using System.Drawing.Design; +using System.Linq; namespace Bro.Device.AuboRobot { @@ -28,6 +31,16 @@ [Category("閫氫俊璁剧疆")] [Description("鍗忚鍐呭鍒嗛殧瀛楃")] public string Seperator { get; set; } = ","; + + [Category("IO鐩戝惉璁剧疆")] + [Description("IO鐩戝惉鎿嶄綔閰嶇疆闆嗗悎")] + [TypeConverter(typeof(CollectionCountConvert))] + [Editor(typeof(ComplexCollectionEditor<MonitorSet>), typeof(UITypeEditor))] + public List<MonitorSet> MonitorSetCollection { get; set; } = new List<MonitorSet>(); + + [Category("IO鐩戝惉璁剧疆")] + [Description("IO鐩戝惉闂撮殧锛屼互ms涓哄崟浣�")] + public int ScanInterval { get; set; } = 100; } [Device("AuboRobot", "濂ュ崥鏈哄櫒浜�", EnumHelper.DeviceAttributeType.OperationConfig)] @@ -45,22 +58,44 @@ public RobotMsgParas Para1 { get; set; } = RobotMsgParas.None; - public List<string> Paras { get; set; } = new List<string>(); + public int Para2 { get; set; } = 0; + + /// <summary> + /// Paras涓嶅寘鍚玃ara1,Para2鍐呭 + /// </summary> + public List<string> Datas { get; set; } = new List<string>(); public byte[] GetMsgBytes(string seperator, string endChar) { - List<string> list = new List<string>() { Type.ToString(), ID.ToString() }; + List<string> list = new List<string>() { ((int)Type).ToString("D2"), ID.ToString("D2") }; if (Type == RobotMsgType.Send) { - list.Add(Action.ToString()); + list.Add(((int)Action).ToString("D2")); - if (Para1 != RobotMsgParas.None) + list.Add(((int)Para1).ToString("D2")); + list.Add(Para2.ToString("D2")); + + if (Datas == null) { - list.Add(Para1.ToString()); + Datas = new List<string>(); } - list.AddRange(Paras); + while (Datas.Count < 5) + { + Datas.Add("0"); + } + + list.AddRange(Datas.ConvertAll(s => + { + string res = float.Parse(s).ToString("F7"); + + while (res.Length < 11) + { + res = "0" + s; + } + return res; + })); } string msg = string.Join(seperator, list); @@ -74,31 +109,17 @@ RobotMsg msg = new RobotMsg(); - msg.Type = (RobotMsgType)Enum.Parse(typeof(RobotMsgType), datas[0]); + msg.Type = (RobotMsgType)int.Parse(datas[0]); msg.ID = int.Parse(datas[1]); if (msg.Type == RobotMsgType.Send) { - msg.Action = (RobotMsgAction)Enum.Parse(typeof(RobotMsgAction), datas[2]); + msg.Action = (RobotMsgAction)int.Parse(datas[2]); - if (int.TryParse(datas[3], out int para1)) - { - msg.Para1 = RobotMsgParas.None; + msg.Para1 = (RobotMsgParas)int.Parse(datas[3]); + msg.Para2 = int.Parse(datas[4]); - for (int i = 3; i < datas.Length; i++) - { - msg.Paras.Add(datas[i]); - } - } - else - { - msg.Para1 = (RobotMsgParas)Enum.Parse(typeof(RobotMsgParas), datas[3]); - - for (int i = 4; i < datas.Length; i++) - { - msg.Paras.Add(datas[i]); - } - } + msg.Datas = datas.Skip(5).ToList(); } return msg; @@ -106,38 +127,36 @@ public string GetDisplayText() { - string msg = $"搴忓彿锛歿ID},{Action.ToString()}_{Para1.ToString()}{(Paras.Count > 0 ? ("_" + string.Join(",", Paras)) : "")}"; + string msg = $"搴忓彿锛歿ID},{Action.ToString()}_{Para1.ToString()}_{Para2.ToString()}_{(Datas.Count > 0 ? ("_" + string.Join(",", Datas)) : "")}"; return msg; } } public enum RobotMsgType { - Send, - Rec + Send = 1, + Rec = 2, } public enum RobotMsgAction { - Move, - State, - Adjust, - IO, + Move = 1, + Unload = 2, + Load = 3, + IO = 6, + Calibration = 9, + StandardPoint = 10, } public enum RobotMsgParas { - None, - LineSnap, - Line, - Robot, - LoadEmptyTraySnap, - LoadEmptyTrayDone, - LoadFullTraySnap, - LoadFullTrayDone, - EmptyTrayReady, - EmptyTrayEmpty, - FullTrayFull, - Query, + None = 0, + Home = 1, + LineSnap = 2, + EmptyTray = 3, + FullTray = 4, + UnloadEmptyTraySnap = 5, + LoadFullTraySnap = 6, + Query = 7, } } diff --git a/src/Bro.Device.AuboRobot/AuboRobotDriver.cs b/src/Bro.Device.AuboRobot/AuboRobotDriver.cs index 26e7324..7007dc8 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; @@ -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 { @@ -52,10 +54,20 @@ { } + 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() @@ -152,8 +164,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(resultStr[i]); + } + + monitorHandle.Set(); + } + else + { + OnMsgReceived?.BeginInvoke(DateTime.Now, this, msg, null, null); + } } }); }); @@ -164,7 +192,7 @@ { get { - if (sid > 999) + if (sid > 99) { sid = 1; } @@ -176,27 +204,33 @@ 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())); + + 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; + public void SendMsg(RobotMsg msg, bool isWaitReply = true, bool isMonitorMsg = false) { if (isWaitReply) { @@ -205,17 +239,99 @@ } byte[] bytes = msg.GetMsgBytes(IConfig.Seperator, IConfig.EndChar); - client.GetStream().Write(bytes, 0, bytes.Length); - if (isWaitReply) + if (!isMonitorMsg) { - replyHandleDict[msg.ID].WaitOne(IConfig.ReplyTimeout); + canMonitor = false; + } - if (replyHandleList.Contains(msg.ID)) + if (isMonitorMsg && !canMonitor) + return; + + lock (this) + { + client.GetStream().Write(bytes, 0, bytes.Length); + if (isWaitReply) { - throw new ProcessException("鍙嶉鏁版嵁瓒呮椂\r\n" + msg.GetDisplayText(), null); + replyHandleDict[msg.ID].WaitOne(IConfig.ReplyTimeout); + + if (replyHandleList.Contains(msg.ID)) + { + throw new ProcessException("鍙嶉鏁版嵁瓒呮椂\r\n" + msg.GetDisplayText(), null); + } } } } + + #region IMonitor + public event OnMonitorInvokeDelegate OnMonitorInvoke; + public event OnMonitorAlarmDelegate OnMonitorAlarm; + + protected List<int> oldValues = new List<int>(); + List<int> newValues = new List<int>(); + AutoResetEvent monitorHandle = new AutoResetEvent(false); + public List<int> GetMonitorValues(int startAddress, int length) + { + SendMsg(scanMsg, true, true); + monitorHandle.WaitOne(); + + 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 == 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 => + { + 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 } } diff --git a/src/Bro.Device.AuboRobot/Bro.Device.AuboRobot.csproj b/src/Bro.Device.AuboRobot/Bro.Device.AuboRobot.csproj index bea6b68..0af4af5 100644 --- a/src/Bro.Device.AuboRobot/Bro.Device.AuboRobot.csproj +++ b/src/Bro.Device.AuboRobot/Bro.Device.AuboRobot.csproj @@ -36,6 +36,7 @@ </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> diff --git a/src/Bro.Device.Common/DeviceBase/PLCBase.cs b/src/Bro.Device.Common/DeviceBase/PLCBase.cs index c1e99b9..10d42f1 100644 --- a/src/Bro.Device.Common/DeviceBase/PLCBase.cs +++ b/src/Bro.Device.Common/DeviceBase/PLCBase.cs @@ -79,7 +79,7 @@ } catch (Exception ex) { - OnLog?.Invoke(DateTime.Now, this, "PLC鐩戝惉寮傚父:" + ex.GetExceptionMessage()); + OnLog?.Invoke(DateTime.Now, this, $"{Name}鐩戝惉寮傚父:{ex.GetExceptionMessage()}"); } } } @@ -141,7 +141,7 @@ return tempNew[index]; }).ToList(); - OnMonitorInvoke?.BeginInvoke(DateTime.Now, m, OnMethodInvoked, m); + OnMonitorInvoke?.BeginInvoke(DateTime.Now, this, m, OnMethodInvoked, m); } } }); diff --git a/src/Bro.Device.OmronFins/OmronFinsConfig.cs b/src/Bro.Device.OmronFins/OmronFinsConfig.cs index a4d31ad..6d2c675 100644 --- a/src/Bro.Device.OmronFins/OmronFinsConfig.cs +++ b/src/Bro.Device.OmronFins/OmronFinsConfig.cs @@ -35,6 +35,7 @@ /// </summary> [Description("PLC缃戠粶鍙�")] [Category("閫氫俊璁剧疆-PLC")] + [Browsable(false)] public byte DNA { get; set; } = 0; /// <summary> @@ -42,6 +43,7 @@ /// </summary> [Description("PLC鑺傜偣鍙�")] [Category("閫氫俊璁剧疆-PLC")] + [Browsable(false)] public byte DA1 { get; set; } = 1; /// <summary> @@ -49,6 +51,7 @@ /// </summary> [Description("PLC鍗曞厓鍙�")] [Category("閫氫俊璁剧疆-PLC")] + [Browsable(false)] public byte DA2 { get; set; } = 0; /// <summary> @@ -70,6 +73,7 @@ /// </summary> [Description("PC缃戠粶鍙�")] [Category("閫氫俊璁剧疆-鏈満")] + [Browsable(false)] public byte SNA { get; set; } = 0; /// <summary> @@ -77,6 +81,7 @@ /// </summary> [Description("PC鑺傜偣鍙�")] [Category("閫氫俊璁剧疆-鏈満")] + [Browsable(false)] public byte SA1 { get; set; } = 10; /// <summary> @@ -84,9 +89,8 @@ /// </summary> [Description("PC鍗曞厓鍙�")] [Category("閫氫俊璁剧疆-鏈満")] + [Browsable(false)] public byte SA2 { get; set; } = 0; - - } public class OmronFinsInputConfig : PLCInputConfigBase diff --git a/src/Bro.Device.SeerAGV/SeerAGVConfig.cs b/src/Bro.Device.SeerAGV/SeerAGVConfig.cs index 88e3b3f..67482a1 100644 --- a/src/Bro.Device.SeerAGV/SeerAGVConfig.cs +++ b/src/Bro.Device.SeerAGV/SeerAGVConfig.cs @@ -136,6 +136,7 @@ QueryTaskStatus = 0x03FC, CancelTask = 0x0BBB, + PauseTask = 0x0BB9, TaskOrder = 0x0BEB, } diff --git a/src/Bro.Device.SeerAGV/SeerAGVDriver.cs b/src/Bro.Device.SeerAGV/SeerAGVDriver.cs index e64d17c..c5247c7 100644 --- a/src/Bro.Device.SeerAGV/SeerAGVDriver.cs +++ b/src/Bro.Device.SeerAGV/SeerAGVDriver.cs @@ -96,7 +96,7 @@ byte[] buffer = new byte[1024]; string currentPosition = ""; - string CurrentPosition + public string CurrentPosition { get => currentPosition; set @@ -105,13 +105,16 @@ { currentPosition = value; - OnAGVPositoinChanged?.Invoke(this, currentPosition); + if (!string.IsNullOrWhiteSpace(currentPosition)) + { + OnAGVPositoinChanged?.Invoke(this, currentPosition); + } } } } AGVTaskStatus taskStatus = AGVTaskStatus.None; - AGVTaskStatus TaskStatus + public AGVTaskStatus TaskStatus { get => taskStatus; set @@ -119,7 +122,11 @@ if (taskStatus != value) { taskStatus = value; - OnAGVTaskStatusChanged?.Invoke(this, taskStatus); + + if (taskStatus != AGVTaskStatus.None) + { + OnAGVTaskStatusChanged?.Invoke(this, taskStatus); + } } } } @@ -219,8 +226,15 @@ SendMsg(client_Guide, IConfig.GuidePort, msg); } + public void PauseTask() + { + SeerMessage msg = new SeerMessage((int)AGVCode.PauseTask, SID); + SendMsg(client_Guide, IConfig.GuidePort, msg); + } + public void TaskOrder(string dest) { + CurrentPosition = ""; SeerMessage msg = new SeerMessage((int)AGVCode.TaskOrder, SID, JsonConvert.SerializeObject(new { id = dest })); SendMsg(client_Guide, IConfig.GuidePort, msg); } -- Gitblit v1.8.0