using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using Bro.Process; using HalconDotNet; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Bro.M071.Process { [Process("M071", EnumHelper.DeviceAttributeType.Device)] public partial class M071Process : ProcessControl { #region 构造函数 public M071Process() : base() { } public M071Process(string productionCode) : base(productionCode) { } #endregion #region 配置 M071Config Config { get => IConfig as M071Config; } #endregion #region 事件 public event Action OnMeasureStart; public event Action OnBarcodeChanged; public event Action OnElementUpdated; #endregion public override void Open() { InitialSetting(); base.Open(); } private void InitialSetting() { Config.SnapshotPointCollection.ForEach(u => { u.GetHalconToolPathList().ForEach(path => { LoadHalconTool(path, u.Id); }); }); Config.KeyUnitCollection.ForEach(u => { if (!u.IsEnabled) return; var snapshotPoint = Config.SnapshotPointCollection.FirstOrDefault(s => s.Id == u.SnapshotPointId && s.IsEnabled); if (snapshotPoint == null) throw new ProcessException($"{u.AlignName}未设置可用拍照点位"); if (u.ImageSeq < 1) throw new ProcessException($"{u.AlignName}图片序号小于1"); var algo = Config.KeyAlgorithemCollection.FirstOrDefault(a => a.Id == u.KeyAlgorithemId); if (algo == null) throw new ProcessException($"{u.AlignName}未设置检测算法"); u.KeyAlgorithemPath = algo.AlgorithemPath; LoadHalconTool(u.KeyAlgorithemPath, u.AlignName); var resultSet = Config.KeyResultCollection.FirstOrDefault(r => r.Id == u.KeyResultId); if (resultSet == null) throw new ProcessException($"{u.AlignName}未设置检测结果配置"); u.KeyResultList = new List(resultSet.Results); }); Config.MeasurementUnitCollection.ForEach(u => { if (!u.IsEnabled) return; var spec = Config.MeasureTypeCollection.FirstOrDefault(s => s.Code == u.MeasureType); if (spec == null) throw new ProcessException($"{u.GetDisplayText()}未设置检测类型"); u.Spec = new MeasureType(); u.Spec.DataFrom(spec); LoadHalconTool(u.Spec.AlgorithemPath, u.Id); u.KeyUnitCollection.ForEach(b => { var keyRespone = Config.KeyUnitCollection.Where(ku => ku.IsEnabled && ku.Key == b.Key).ToList(); if (keyRespone.Count == 0) throw new ProcessException($"{u.GetDisplayText()}对应的单键不存在或不可用"); if (b.KeyResult == "All") { keyRespone.SelectMany(kr => kr.KeyResultList).ToList().ForEach(r => { b.MeasureValueDict[r] = null; }); } else { b.MeasureValueDict[b.KeyResult] = null; } }); }); } #region InitialHalconTool //protected override void InitialHalconTool() //{ // base.InitialHalconTool(); // Config.SnapshotPointCollection.ForEach(u => // { // u.GetHalconToolPathList().ForEach(path => // { // if (!string.IsNullOrWhiteSpace(path)) // { // string directoryPath = Path.GetDirectoryName(path); // string fileName = Path.GetFileNameWithoutExtension(path); // HDevEngineTool tool = new HDevEngineTool(directoryPath); // tool.LoadProcedure(fileName); // //使用“|”作为间隔符 // _halconToolDict[u.Id + "|" + path] = tool; // } // }); // }); //} #endregion private string barCode = ""; public string BarCode { get => barCode; set { if (barCode != value) { barCode = value; OnBarcodeChanged?.Invoke(value); } } } [ProcessMethod("", "StartJob", "开始扫描", InvokeType.TestInvoke)] public ProcessResponse StartJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { if (string.IsNullOrWhiteSpace(BarCode)) { throw new ProcessException("未输入产品条码,请勿开始测量"); } OnMeasureStart?.BeginInvoke(null, null); var measurements = Config.MeasurementUnitCollection.Where(u => u.IsEnabled).ToList().DeepSerializeClone(); measurements.ForEach(m => { m.InitialKeyUnitMeasureChanged(); }); var pMeasure = new ProductionMeasurement() { Barcode = BarCode, Measurements = measurements, }; pMeasure.InitialMeasurementsPropertyChanged(); pMeasure.PropertyChanged += MeasureProduction_PropertyChanged; Config.SnapshotPointCollection.Where(u => u.IsEnabled).ToList().ForEach(s => { _pauseHandle.WaitHandle.WaitOne(); IDevice device = DeviceCollection.FirstOrDefault(u => u.Id == s.MotionDevice); if (device == null) throw new ProcessException($"{s.Name}拍照点位未设置运动设备"); IMotion motionDevice = device as IMotion; if (motionDevice == null) throw new ProcessException($"{s.Name}拍照点位设置{device.Name}不是运动设备"); if (!motionDevice.MoveToPoint(null)) { throw new ProcessException("运动中止", null, ExceptionLevel.Info); } CameraBase camera = DeviceCollection.FirstOrDefault(u => u.Id == s.CameraOp.Device) as CameraBase; if (camera == null) return; ImageSet imgSet = camera.Snapshot(s.CameraOp.OpConfig); if (imgSet == null) return; RunImageHandle(camera, s.CameraOp.OpConfig, imgSet, s.Id, s.Name, pMeasure.Measurements); }); BarCode = ""; return new ProcessResponse(true); } /// /// 暂停标志 /// WaitHandle 暂停句柄 默认为非阻塞 可执行 /// WaitResult 暂停标志 true 正常执行 false 暂停中 /// ManualWaitConfirm _pauseHandle = new ManualWaitConfirm() { WaitHandle = new ManualResetEvent(true), WaitResult = true, }; [ProcessMethod("", "PauseJob", "暂停流程", InvokeType.TestInvoke)] public ProcessResponse PauseJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { if (_pauseHandle.WaitResult) { #region 板卡暂停动作 #endregion _pauseHandle.WaitHandle.Reset(); } else { #region 板卡恢复动作 #endregion _pauseHandle.WaitHandle.Set(); } _pauseHandle.WaitResult = !_pauseHandle.WaitResult; return new ProcessResponse(_pauseHandle.WaitResult); } #region 私有方法 private void MeasureProduction_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (sender is ProductionMeasurement pMeasure) { //检查是否全部完成 pMeasure.Measurements.ForEach(m => { if (m.KeyUnitCollection.All(k => k.IsDone != null)) { if (!m.IsUpdated) { if (m.KeyUnitCollection.Any(k => k.IsDone == false)) { m.Spec.ActualValue = -999; } else { string toolKey = m.Id + "|" + m.Spec.AlgorithemPath; if (!_halconToolDict.ContainsKey(toolKey)) { LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}算法未初始化", ""); m.Spec.ActualValue = -999; } else { var array = m.KeyUnitCollection.SelectMany(u => u.MeasureValueDict.Values.ToList().ConvertAll(v => v ?? -999)).ToArray(); _halconToolDict[toolKey].InputTupleDic["INPUT_Params"] = new HTuple(array); if (!_halconToolDict[toolKey].RunProcedure(out string error)) { LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}算法异常,{error}", ""); m.Spec.ActualValue = -999; } else { m.Spec.ActualValue = _halconToolDict[toolKey].GetResultTuple("OUTPUT_Result").D; LogAsync(DateTime.Now, $"{m.GetDisplayText()}数据{m.Spec.ActualValue},结果{(m.Spec.MeasureResult == null ? "TBD" : (m.Spec.MeasureResult == true ? "OK" : "NG"))}", ""); } } } //输出图形基元到界面 todo OnElementUpdated?.BeginInvoke(null, null, null); m.IsUpdated = true; } } }); if (!pMeasure.Measurements.All(m => m.IsUpdated)) { return; } //MES输出 todo //Excel报表输出 todo //数据库保存 todo //MeasureDict.Remove(pMeasure.Barcode); pMeasure.Dispose(); } } private async void RunImageHandle(CameraBase camera, IOperationConfig opConfig, ImageSet imgSet, string snapshotId, string snapshotName, List measureList) { await Task.Run(() => { var keys = Config.KeyUnitCollection.Where(u => u.IsEnabled && u.SnapshotPointId == snapshotId); var keyBindCollection = measureList.SelectMany(u => u.KeyUnitCollection).Where(u => keys.Any(k => k.Key == u.Key)).ToList(); string toolKey = (opConfig as CameraOprerationConfigBase).AlgorithemPath; HObject images = imgSet.HImage; if (!string.IsNullOrWhiteSpace(toolKey)) { toolKey = snapshotId + "|" + toolKey; if (!_halconToolDict.ContainsKey(toolKey)) { LogAsync(DateTime.Now, $"{snapshotName}未初始化取图算法配置", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } _halconToolDict[toolKey].InputImageDic["INPUT_Image"] = imgSet.HImage; if (!_halconToolDict[toolKey].RunProcedure(out string error)) { LogAsync(DateTime.Now, $"{snapshotName}取图算法异常,{error}", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } images = _halconToolDict[toolKey].GetResultObject("OUTPUT_Images"); } HOperatorSet.CountObj(images, out HTuple count); if (count == 0) { LogAsync(DateTime.Now, $"{snapshotName}取图算法未输出图像", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } var excludeKeys = keys.Where(u => u.ImageSeq > count).ToList(); if (excludeKeys.Count > 0) { LogAsync(DateTime.Now, $"{string.Join(" ", excludeKeys.Select(u => u.AlignName))}未在图片获取序列中", ""); keyBindCollection.Where(k => excludeKeys.Any(u => u.Key == k.Key)).ToList().ForEach(k => { k.FillKeyValues(null); }); } Parallel.For(1, count.I, (i) => { HOperatorSet.SelectObj(images, out HObject image, i); keys.Where(u => u.ImageSeq == i).ToList().ForEach(k => { Dictionary resultDict = null; var keyBindList = keyBindCollection.Where(u => u.Key == k.Key).ToList(); string keyToolKey = k.AlignName + "|" + k.KeyAlgorithemPath; if (!_halconToolDict.ContainsKey(keyToolKey)) { LogAsync(DateTime.Now, $"{k.AlignName}检测算法未初始化", ""); } else { _halconToolDict[keyToolKey].InputImageDic["INPUT_Image"] = image; if (!_halconToolDict[keyToolKey].RunProcedure(out string error)) { LogAsync(DateTime.Now, $"{k.AlignName}检测算法异常,{error}", ""); } else { var results = _halconToolDict[keyToolKey].GetResultTuple("OUTPUT_Results").HTupleToDouble(); if (results.Count == 0 || results.Any(u => u < 0)) { LogAsync(DateTime.Now, $"{k.AlignName}检测结果异常", ""); } else { resultDict = k.KeyResultList.ToDictionary(u => u, u => { int index = k.KeyResultList.IndexOf(u); return results[index]; }); } } } keyBindList.ForEach(kb => kb.FillKeyValues(resultDict)); }); image.Dispose(); }); if (count.I != 1) imgSet.HImage.Dispose(); }); } #endregion } }