| | |
| | | using Bro.Common.Helper; |
| | | using Bro.Common.Interface; |
| | | using Bro.Common.Model; |
| | | //using Bro.M071.DBManager; |
| | | using Bro.M071.Model; |
| | | using Bro.M071.Model.Model; |
| | | using Bro.M071.Process.UI; |
| | | using Bro.Process; |
| | | using HalconDotNet; |
| | | using Newtonsoft.Json; |
| | | using OfficeOpenXml; |
| | | using OfficeOpenXml.Style; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.Configuration; |
| | | using System.Drawing; |
| | | using System.Drawing.Imaging; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | using static Bro.Common.Helper.EnumHelper; |
| | | |
| | | namespace Bro.M071.Process |
| | | { |
| | |
| | | |
| | | #region 事件 |
| | | public event Action OnMeasureStart; |
| | | public event Action<string> OnBarcodeChanged; |
| | | public event Action OnClearBarcode; |
| | | public event Action<IShapeElement> OnElementUpdated; |
| | | public event Action<MachineState> OnMachineStateChanged; |
| | | public event Action OnFullResetDone; |
| | | #endregion |
| | | |
| | | string _precision = "f3"; |
| | | double _allowedShift = 0; |
| | | |
| | | public override void Open() |
| | | { |
| | |
| | | |
| | | base.Open(); |
| | | |
| | | CheckMachineState(); |
| | | InitialMotionCardBaseAxisAlarm(); |
| | | |
| | | SwitchBeep(false); |
| | | SwitchLightGreen(false); |
| | | SwitchLightRed(false); |
| | | SwitchLightYellow(false); |
| | | |
| | | Reset(null, null, null); |
| | | FullReset(null); |
| | | |
| | | if (Config.Precision > 0) |
| | | { |
| | | _precision = "f" + Config.Precision; |
| | | } |
| | | |
| | | IncomingCheckMethod = InitialMESWebServiceMethod(IncomingCheckMethodName, out IncomingCheckObj); |
| | | DataUploadMethod = InitialMESWebServiceMethod(DataUploadMethodName, out DataUploadObj); |
| | | |
| | | var allowedShiftStr = ConfigurationManager.AppSettings["DataShift"]; |
| | | if (!double.TryParse(allowedShiftStr, out _allowedShift)) |
| | | { |
| | | _allowedShift = 0; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 检查设备状态 |
| | | /// </summary> |
| | | private void CheckMachineState() |
| | | private void InitialMotionCardBaseAxisAlarm() |
| | | { |
| | | throw new NotImplementedException(); |
| | | if (outputCtrlCard != null) |
| | | { |
| | | outputCtrlCard.OnAxisAlarmRaised -= MotionCard_OnAxisAlarmRaised; |
| | | outputCtrlCard.OnAxisAlarmRaised += MotionCard_OnAxisAlarmRaised; |
| | | } |
| | | } |
| | | |
| | | private void MotionCard_OnAxisAlarmRaised(int axisIndex, string alarmMsg) |
| | | { |
| | | RaisedAlarm(alarmMsg); |
| | | MachineState = MachineState.Alarm; |
| | | } |
| | | |
| | | private void InitialSetting() |
| | | { |
| | | //数据库迁移检查 |
| | | //DatabaseInitialize.Initialize(); |
| | | |
| | | MotionCardSettingCheck(); |
| | | |
| | | Config.SnapshotPointCollection.ForEach(u => |
| | | { |
| | | u.GetHalconToolPathList().ForEach(path => |
| | |
| | | |
| | | var snapshotPoint = Config.SnapshotPointCollection.FirstOrDefault(s => s.Id == u.SnapshotPointId && s.IsEnabled); |
| | | if (snapshotPoint == null) |
| | | throw new ProcessException($"{u.AlignName}未设置可用拍照点位"); |
| | | throw new ProcessException($"{u.AliasName}未设置可用拍照点位"); |
| | | |
| | | if (u.ImageSeq < 1) |
| | | throw new ProcessException($"{u.AlignName}图片序号小于1"); |
| | | throw new ProcessException($"{u.AliasName}图片序号小于1"); |
| | | |
| | | var algo = Config.KeyAlgorithemCollection.FirstOrDefault(a => a.Id == u.KeyAlgorithemId); |
| | | if (algo == null) |
| | | throw new ProcessException($"{u.AlignName}未设置检测算法"); |
| | | throw new ProcessException($"{u.AliasName}未设置检测算法"); |
| | | |
| | | u.KeyAlgorithemPath = algo.AlgorithemPath; |
| | | LoadHalconTool(u.KeyAlgorithemPath, u.AlignName); |
| | | LoadHalconTool(u.KeyAlgorithemPath, u.AliasName); |
| | | |
| | | var resultSet = Config.KeyResultCollection.FirstOrDefault(r => r.Id == u.KeyResultId); |
| | | if (resultSet == null) |
| | | throw new ProcessException($"{u.AlignName}未设置检测结果配置"); |
| | | throw new ProcessException($"{u.AliasName}未设置检测结果配置"); |
| | | |
| | | u.KeyResultList = new List<string>(resultSet.Results); |
| | | }); |
| | |
| | | if (keyRespone.Count == 0) |
| | | throw new ProcessException($"{u.GetDisplayText()}对应的单键不存在或不可用"); |
| | | |
| | | if (b.KeyResult == "All") |
| | | if (b.KeyResultId == "All") |
| | | { |
| | | keyRespone.SelectMany(kr => kr.KeyResultList).ToList().ForEach(r => |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | b.MeasureValueDict[b.KeyResult] = null; |
| | | b.MeasureValueDict[b.KeyResultId] = 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 |
| | | #region 流程中抛出异常 |
| | | public override void ExceptionRaisedInMonitor(Exception ex) |
| | | { |
| | | get => barCode; |
| | | set |
| | | if (ex is ProcessException pEx) |
| | | { |
| | | if (barCode != value) |
| | | if (pEx.Level >= ExceptionLevel.Fatal) |
| | | { |
| | | barCode = value; |
| | | OnBarcodeChanged?.Invoke(value); |
| | | RaisedAlarm(pEx.Message); |
| | | MachineState = MachineState.Alarm; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | RaisedAlarm(ex.Message); |
| | | MachineState = MachineState.Alarm; |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | List<ProductionMeasurement> productionList = new List<ProductionMeasurement>(); |
| | | |
| | | [ProcessMethod("", "StartJob", "开始扫描", InvokeType.TestInvoke)] |
| | | public ProcessResponse StartJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | if (string.IsNullOrWhiteSpace(BarCode)) |
| | | if (!IsAllowedWork) |
| | | { |
| | | throw new ProcessException("未输入产品条码,请勿开始测量"); |
| | | throw new ProcessException(SafetyMsg, null, ExceptionLevel.Fatal); |
| | | } |
| | | |
| | | OnMeasureStart?.BeginInvoke(null, null); |
| | | |
| | | var measurements = Config.MeasurementUnitCollection.Where(u => u.IsEnabled).ToList().DeepSerializeClone(); |
| | | measurements.ForEach(m => |
| | | string hint = ""; |
| | | if (MachineState != MachineState.Ready) |
| | | { |
| | | hint = "机台未就绪,请勿开始测量"; |
| | | OnCheckHintUpload?.Invoke(hint, true); |
| | | throw new ProcessException(hint, null, ExceptionLevel.Warning); |
| | | } |
| | | |
| | | if (string.IsNullOrWhiteSpace(BarCode)) |
| | | { |
| | | hint = "未输入产品条码,请勿开始测量"; |
| | | OnClearBarcode?.Invoke(); |
| | | OnCheckHintUpload?.Invoke(hint, true); |
| | | throw new ProcessException(hint); |
| | | } |
| | | |
| | | MachineState = MachineState.Running; |
| | | |
| | | OnCheckHintUpload?.Invoke(hint, true); |
| | | OnMeasureStart?.Invoke(); |
| | | |
| | | //var measurements = Config.MeasurementUnitCollection.Where(u => u.IsEnabled).ToList().DeepSerializeClone(); |
| | | //measurements.ForEach(m => |
| | | //{ |
| | | // m.InitialKeyUnitMeasureChanged(); |
| | | //}); |
| | | |
| | | List<MeasurementUnit> measurements = new List<MeasurementUnit>(); |
| | | Config.MeasurementUnitCollection.Where(u => u.IsEnabled).ToList().ForEach(u => |
| | | { |
| | | var m = u.Copy(); |
| | | m.InitialKeyUnitMeasureChanged(); |
| | | measurements.Add(m); |
| | | }); |
| | | |
| | | var pMeasure = new ProductionMeasurement() |
| | | { |
| | | Barcode = BarCode, |
| | | Measurements = measurements, |
| | | StartTime = DateTime.Now, |
| | | }; |
| | | |
| | | BarCode = ""; |
| | | |
| | | var existedProduction = productionList.FirstOrDefault(u => u.Barcode == pMeasure.Barcode); |
| | | if (existedProduction != null) |
| | |
| | | |
| | | Config.SnapshotPointCollection.Where(u => u.IsEnabled).ToList().ForEach(s => |
| | | { |
| | | _pauseHandle.WaitHandle.WaitOne(); |
| | | _pausedHandle.Wait(); |
| | | |
| | | if (MachineState == MachineState.Ready) |
| | | return; |
| | | |
| | | if (MachineState != MachineState.Running && MachineState != MachineState.Pause) |
| | | { |
| | | throw new ProcessException("机台状态不在运行中,退出检测"); |
| | | } |
| | | |
| | | IDevice device = DeviceCollection.FirstOrDefault(u => u.Id == s.MotionOp.Device); |
| | | if (device == null) |
| | |
| | | var response = motionDevice.Run(s.MotionOp.OpConfig); |
| | | if (!response.Result) |
| | | { |
| | | throw new ProcessException($"{device.Name}异常,{response.Message}", null, ExceptionLevel.Info); |
| | | throw new ProcessException($"{device.Name}异常,{response.Message}", null, ExceptionLevel.Fatal); |
| | | } |
| | | |
| | | CameraBase camera = DeviceCollection.FirstOrDefault(u => u.Id == s.CameraOp.Device) as CameraBase; |
| | | if (camera == null) |
| | | return; |
| | | |
| | | HImage hImage = CollectHImage(camera, s.CameraOp.OpConfig, out string imgSetId); |
| | | if (string.IsNullOrWhiteSpace(imgSetId)) |
| | | IImageSet set = null; |
| | | try |
| | | { |
| | | set = CollectHImage(camera, s.CameraOp.OpConfig); |
| | | } |
| | | catch (ProcessException pEx) |
| | | { |
| | | pEx.Level = ExceptionLevel.Fatal; |
| | | throw pEx; |
| | | } |
| | | |
| | | if (set == null) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | RunImageHandle(camera, s.CameraOp.OpConfig, hImage, s.Id, s.Name, pMeasure.Measurements); |
| | | RunImageHandle(s.CameraOp.OpConfig, set, s.Id, s.Name, pMeasure.Measurements); |
| | | }); |
| | | |
| | | BarCode = ""; |
| | | LogAsync(DateTime.Now, $"{pMeasure.Barcode}测量动作完成", ""); |
| | | |
| | | GC.Collect(0, GCCollectionMode.Optimized); |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 暂停标志 |
| | | /// WaitHandle 暂停句柄 默认为非阻塞 可执行 |
| | | /// WaitResult 暂停标志 true 正常执行 false 暂停中 |
| | | /// </summary> |
| | | ManualWaitConfirm _pauseHandle = new ManualWaitConfirm() |
| | | #region 双手启动 |
| | | bool isLeftStart = false; |
| | | bool IsLeftStart |
| | | { |
| | | WaitHandle = new ManualResetEvent(true), |
| | | WaitResult = true, |
| | | }; |
| | | |
| | | [ProcessMethod("", "PauseJob", "暂停流程", InvokeType.TestInvoke)] |
| | | public ProcessResponse PauseJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | if (_pauseHandle.WaitResult) |
| | | get => isLeftStart; |
| | | set |
| | | { |
| | | #region 板卡暂停动作 |
| | | #endregion |
| | | |
| | | _pauseHandle.WaitHandle.Reset(); |
| | | isLeftStart = value; |
| | | StartCheck(); |
| | | } |
| | | else |
| | | { |
| | | #region 板卡恢复动作 |
| | | #endregion |
| | | |
| | | _pauseHandle.WaitHandle.Set(); |
| | | } |
| | | |
| | | _pauseHandle.WaitResult = !_pauseHandle.WaitResult; |
| | | return new ProcessResponse(_pauseHandle.WaitResult); |
| | | } |
| | | |
| | | bool isRightStart = false; |
| | | bool IsRightStart |
| | | { |
| | | get => isRightStart; |
| | | set |
| | | { |
| | | isRightStart = value; |
| | | StartCheck(); |
| | | } |
| | | } |
| | | |
| | | private void StartCheck() |
| | | { |
| | | if (isRightStart && isLeftStart) |
| | | { |
| | | StartJob(null, null, null); |
| | | } |
| | | } |
| | | |
| | | [ProcessMethod("", "Start_Left", "左手启动", InvokeType.TestInvoke)] |
| | | public ProcessResponse Start_Left(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | if (opConfig.InputPara != null && opConfig.InputPara.Count > 0) |
| | | { |
| | | IsLeftStart = opConfig.InputPara[0] == 1; |
| | | } |
| | | |
| | | return new ProcessResponse(); |
| | | } |
| | | |
| | | [ProcessMethod("", "Start_Right", "右手启动", InvokeType.TestInvoke)] |
| | | public ProcessResponse Start_Right(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | if (opConfig.InputPara != null && opConfig.InputPara.Count > 0) |
| | | { |
| | | IsRightStart = opConfig.InputPara[0] == 1; |
| | | } |
| | | |
| | | return new ProcessResponse(); |
| | | } |
| | | |
| | | [ProcessMethod("Demostration", "CheckBasePlan", "基准平面检校", InvokeType.TestInvoke)] |
| | | public ProcessResponse CheckBasePlan(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | if (opConfig is DemostrationOperationConfig config) |
| | | { |
| | | config.DemoOperations.ForEach(d => |
| | | { |
| | | IDevice device = DeviceCollection.FirstOrDefault(u => u.Id == d.MotionOp.Device); |
| | | if (device != null) |
| | | { |
| | | IMotionCard motionDevice = device as IMotionCard; |
| | | |
| | | if (motionDevice != null) |
| | | { |
| | | var response = motionDevice.Run(d.MotionOp.OpConfig); |
| | | if (!response.Result) |
| | | { |
| | | throw new ProcessException($"{device.Name}异常,{response.Message}", null, ExceptionLevel.Fatal); |
| | | } |
| | | } |
| | | } |
| | | |
| | | CameraBase camera = DeviceCollection.FirstOrDefault(u => u.Id == d.CameraOp.Device) as CameraBase; |
| | | if (camera != null) |
| | | { |
| | | IImageSet set = null; |
| | | try |
| | | { |
| | | set = CollectHImage(camera, d.CameraOp.OpConfig); |
| | | } |
| | | catch (ProcessException pEx) |
| | | { |
| | | pEx.Level = ExceptionLevel.Fatal; |
| | | throw pEx; |
| | | } |
| | | |
| | | if (set != null) |
| | | { |
| | | LaserScanParam scanParam = JsonConvert.DeserializeObject<LaserScanParam>(set.ImageData); |
| | | LogAsync(DateTime.Now, $"扫描参数:{set.ImageData}", ""); |
| | | |
| | | var tool = GetHalconTool(d.CameraOp.OpConfig, config.MonitorSetId); |
| | | if (tool != null) |
| | | { |
| | | using (tool.InputImageDic["INPUT_Image"] = set.HImage) |
| | | { |
| | | tool.InputTupleDic["INPUT_Resolution_Z"] = scanParam.Resolution_Z / 1000000.0; |
| | | |
| | | if (!tool.RunProcedure(out string error)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{tool.ProcedureName}执行异常", error); |
| | | } |
| | | else |
| | | { |
| | | var diffX = tool.GetResultTuple("OUTPUT_Result_X").D; |
| | | var diffY = tool.GetResultTuple("OUTPUT_Result_Y").D; |
| | | LogAsync(DateTime.Now, $"检测平面,X方向极差:{diffX.ToString(_precision)},Y方向极差:{diffY.ToString(_precision)}", ""); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | return new ProcessResponse(); |
| | | } |
| | | #endregion |
| | | |
| | | #region 私有方法 |
| | | private void MeasureProduction_PropertyChanged(object sender, PropertyChangedEventArgs e) |
| | | { |
| | | if (sender is ProductionMeasurement pMeasure) |
| | | { |
| | | lock (pMeasure) |
| | | var production = productionList.FirstOrDefault(u => u.Barcode == pMeasure.Barcode); |
| | | if (production == null) |
| | | return; |
| | | |
| | | lock (production) |
| | | { |
| | | //检查是否全部完成 |
| | | pMeasure.Measurements.ForEach(m => |
| | | pMeasure.Measurements?.ForEach(m => |
| | | { |
| | | if (m.KeyUnitCollection.All(k => k.IsDone != null)) |
| | | { |
| | |
| | | { |
| | | if (m.KeyUnitCollection.Any(k => k.IsDone == false)) |
| | | { |
| | | m.Spec.ActualValue = -999; |
| | | //m.Spec.ActualValue = -999; |
| | | m.Spec.ActualValue = null; |
| | | } |
| | | else |
| | | { |
| | |
| | | if (!_halconToolDict.ContainsKey(toolKey)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}算法未初始化", ""); |
| | | m.Spec.ActualValue = -999; |
| | | //m.Spec.ActualValue = -999; |
| | | m.Spec.ActualValue = null; |
| | | } |
| | | 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)) |
| | | //var array = m.KeyUnitCollection.SelectMany(u => u.MeasureValueDict.Values.ToList().ConvertAll(v => v ?? -999)).ToArray(); |
| | | var array = m.KeyUnitCollection.SelectMany(u => u.MeasureValueDict.Values.Select(v => v ?? -999)).ToArray(); |
| | | |
| | | if (array == null || array.Length == 0) |
| | | { |
| | | LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}算法异常,{error}", ""); |
| | | m.Spec.ActualValue = -999; |
| | | LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}未能获取对应检测值", ""); |
| | | //m.Spec.ActualValue = -999; |
| | | m.Spec.ActualValue = null; |
| | | } |
| | | 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"))}", ""); |
| | | |
| | | _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; |
| | | m.Spec.ActualValue = null; |
| | | } |
| | | else |
| | | { |
| | | double actualValue = double.Parse(_halconToolDict[toolKey].GetResultTuple("OUTPUT_Result").D.ToString(_precision)); |
| | | m.Spec.ActualValue = actualValue; |
| | | |
| | | //M071要求超限数据在允许范围内压缩到合格范围内 |
| | | if (_allowedShift > 0 && m.Spec.MeasureResult != null && m.Spec.MeasureResult.Value == false) |
| | | { |
| | | m.Spec.ActualValue = m.Spec.StandardValue + (actualValue - m.Spec.StandardValue) * (m.Spec.Tolrenance_Positive - m.Spec.StandardValue) / (m.Spec.Tolrenance_Positive - m.Spec.StandardValue + _allowedShift); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | LogAsync(DateTime.Now, $"{m.GetDisplayText()}检测结果", $"{((m.Spec.MeasureResult ?? false) ? "OK" : "NG")}"); |
| | | |
| | | IShapeElement indicator = null; |
| | | KeyIndicator indicator = new KeyIndicator(m.Id, m.DisplayLocation); |
| | | indicator.Text = m.Spec.ActualValue == null ? "NA" : m.Spec.ActualValue.Value.ToString(_precision); |
| | | indicator.ResultState = m.Spec.MeasureResult; |
| | | pMeasure.ElementList.Add(indicator); |
| | | //输出图形基元到界面 todo |
| | | OnElementUpdated?.BeginInvoke(indicator, null, null); |
| | | //输出图形基元到界面 |
| | | OnElementUpdated?.Invoke(indicator); |
| | | |
| | | SaveKeyImages(pMeasure.Barcode, m); |
| | | |
| | |
| | | { |
| | | return; |
| | | } |
| | | |
| | | //MES输出 todo |
| | | |
| | | //Excel报表输出 todo |
| | | |
| | | //数据库保存 todo |
| | | |
| | | SaveWholeImage(pMeasure); |
| | | |
| | | productionList.RemoveAll(p => p.Barcode == pMeasure.Barcode); |
| | | pMeasure.Dispose(); |
| | | } |
| | | |
| | | pMeasure.EndTime = DateTime.Now; |
| | | //bool pResult = pMeasure.Measurements.All(u => u.Spec.MeasureResult == true); |
| | | //pMeasure.PResult = pResult ? "OK" : "NG"; |
| | | //OnUpdateResult?.Invoke(DateTime.Now, pResult ? 1 : 0); |
| | | //OnUpdateCT?.Invoke((float)(pMeasure.EndTime.Value - pMeasure.StartTime.Value).TotalSeconds); |
| | | |
| | | int result = -1; |
| | | if (pMeasure.Measurements.Any(u => u.Spec.MeasureResult == null)) |
| | | { |
| | | pMeasure.PResult = "NA"; |
| | | } |
| | | else if (pMeasure.Measurements.Any(u => u.Spec.MeasureResult == false)) |
| | | { |
| | | pMeasure.PResult = "NG"; |
| | | result = 0; |
| | | } |
| | | else |
| | | { |
| | | pMeasure.PResult = "OK"; |
| | | result = 1; |
| | | } |
| | | OnUpdateResult?.Invoke(DateTime.Now, result); |
| | | OnUpdateCT?.Invoke((float)(pMeasure.EndTime.Value - pMeasure.StartTime.Value).TotalSeconds); |
| | | |
| | | LogAsync(DateTime.Now, $"{pMeasure.Barcode} 检测完成,结果 {pMeasure.PResult}", ""); |
| | | |
| | | //if (MachineState == MachineState.Running) |
| | | // MachineState = MachineState.Ready; |
| | | |
| | | if (MachineState != MachineState.Alarm) |
| | | { |
| | | if (MachineState == MachineState.Pause) |
| | | { |
| | | _machineStateBeforePause = MachineState.Ready; |
| | | } |
| | | else |
| | | { |
| | | MachineState = MachineState.Ready; |
| | | } |
| | | } |
| | | |
| | | var measurementUnitResultAndKeyUnitDataSet = GetMeasurementUnitResultAndKeyUnitData(pMeasure); |
| | | |
| | | if (pMeasure.PResult != "NA") |
| | | { |
| | | //MES输出 |
| | | MESCheckDataUpload(pMeasure); |
| | | } |
| | | |
| | | //Excel报表输出 (单个产品的excel导出) |
| | | //ExportProductionExcel(measurementUnitResultAndKeyUnitDataSet); |
| | | |
| | | ExportProductionInColumns(measurementUnitResultAndKeyUnitDataSet); |
| | | ////数据库保存 |
| | | //SaveProductionData(measurementUnitResultAndKeyUnitDataSet); |
| | | |
| | | SaveWholeImage(pMeasure); |
| | | |
| | | productionList.RemoveAll(p => p.Barcode == pMeasure.Barcode); |
| | | pMeasure.Dispose(); |
| | | //LogAsync(DateTime.Now, $"{pMeasure.Barcode}产品信息释放完成", JsonConvert.SerializeObject(pMeasure)); |
| | | } |
| | | } |
| | | |
| | | //KeyUnitDataManager keyUnitDataManager = new KeyUnitDataManager(); |
| | | //MeasurementUnitResultManager measurementUnitResultManager = new MeasurementUnitResultManager(); |
| | | //MeasurementAndKeyDataRelationManager measurementAndKeyDataRelationManager = new MeasurementAndKeyDataRelationManager(); |
| | | //ProductionMeasurementRecordsManager productionMeasurementRecordsManager = new ProductionMeasurementRecordsManager(); |
| | | |
| | | static object dataSaveLock = new object(); |
| | | |
| | | //private async void SaveProductionData(ProductionMeasurementUnitResultAndKeyUnitDataSet measurementUnitResultAndKeyUnitDataSet) |
| | | //{ |
| | | // await Task.Run(() => |
| | | // { |
| | | // try |
| | | // { |
| | | // lock (dataSaveLock) |
| | | // { |
| | | // // 获取 产品数据 并保存 |
| | | // var productionMeasurementRecords = measurementUnitResultAndKeyUnitDataSet.ProductionMeasurementRecord; |
| | | // productionMeasurementRecordsManager.CreateModel(productionMeasurementRecords); |
| | | |
| | | // // 获取 原始数据 并保存 |
| | | // var keyUnitDatas = measurementUnitResultAndKeyUnitDataSet.KeyUnitDataList; |
| | | // keyUnitDataManager.BatchAddKeyUnitData(keyUnitDatas); |
| | | |
| | | // // 获取 检测结果数据 并保存 |
| | | // var measurementUnitResults = measurementUnitResultAndKeyUnitDataSet.MeasurementUnitResultList; |
| | | // measurementUnitResultManager.BatchAddMeasurementUnitResult(measurementUnitResults); |
| | | |
| | | // // 获取 关系数据并保存 |
| | | // var measurementAndKeyDataRelationList = measurementUnitResultAndKeyUnitDataSet.MeasurementAndKeyDataRelationList; |
| | | // measurementAndKeyDataRelationManager.BatchAddMeasurementAndKeyDataRelation(measurementAndKeyDataRelationList); |
| | | // } |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // LogAsync(DateTime.Now, "数据保存异常", ex.GetExceptionMessage()); |
| | | // } |
| | | // }); |
| | | //} |
| | | |
| | | private ProductionMeasurementUnitResultAndKeyUnitDataSet GetMeasurementUnitResultAndKeyUnitData(ProductionMeasurement pData) |
| | | { |
| | | ProductionMeasurementUnitResultAndKeyUnitDataSet measurementUnitResultAndKeyUnitDataSet = new ProductionMeasurementUnitResultAndKeyUnitDataSet(); |
| | | |
| | | try |
| | | { |
| | | |
| | | //产品数据 |
| | | ProductionMeasurementRecords productionMeasurementRecords = new ProductionMeasurementRecords(); |
| | | //关系数据 |
| | | List<MeasurementAndKeyDataRelation> measurementAndKeyDataRelationList = new List<MeasurementAndKeyDataRelation>(); |
| | | //原始数据 |
| | | List<KeyUnitData> keyUnitDatas = new List<KeyUnitData>(); |
| | | // 单个产品的测量汇总 |
| | | List<MeasurementUnitResult> measurementUnitResults = new List<MeasurementUnitResult>(); |
| | | |
| | | productionMeasurementRecords.ProductionBarcode = pData.Barcode; |
| | | productionMeasurementRecords.ProductionCode = ProductionCode; |
| | | productionMeasurementRecords.ProductionResult = pData.PResult; |
| | | productionMeasurementRecords.OperationStartTime = pData.StartTime.GetValueOrDefault(); |
| | | productionMeasurementRecords.OperationEndTime = pData.EndTime.GetValueOrDefault(); |
| | | |
| | | measurementUnitResultAndKeyUnitDataSet.ProductionMeasurementRecord = productionMeasurementRecords; |
| | | |
| | | foreach (var measurementUnit in pData.Measurements)//获取到单个测量项结果 |
| | | { |
| | | MeasurementUnitResult measurementUnitResult = new MeasurementUnitResult(); |
| | | measurementUnitResult.ProductionMeasurementRecordsId = productionMeasurementRecords.ID; |
| | | measurementUnitResult.ProductionBarcode = productionMeasurementRecords.ProductionBarcode; |
| | | measurementUnitResult.MeasurementName = measurementUnit.GetDisplayText(); |
| | | |
| | | if (measurementUnit.MeasureType.StartsWith("Alignment") || measurementUnit.MeasureType.StartsWith("Slant")) |
| | | { |
| | | measurementUnitResult.Keys = string.Join("-", measurementUnit.KeyUnitCollection.Select(u => u.Key)); |
| | | measurementUnitResult.Positions = string.Join("-", measurementUnit.KeyUnitCollection.Select(u => u.KeyResultId)); |
| | | } |
| | | else if (measurementUnit.MeasureType.StartsWith("RowAlignment")) |
| | | { |
| | | measurementUnitResult.Keys = measurementUnit.KeyUnitCollection[0].Key + "~" + measurementUnit.KeyUnitCollection[measurementUnit.KeyUnitCollection.Count() - 1].Key; |
| | | measurementUnitResult.Keys = measurementUnit.KeyUnitCollection[0].KeyResultId + "~" + measurementUnit.KeyUnitCollection[measurementUnit.KeyUnitCollection.Count() - 1].KeyResultId; |
| | | } |
| | | measurementUnitResult.MeasurementType = measurementUnit.MeasureType; |
| | | measurementUnitResult.MeasurementValue = measurementUnit.Spec.ActualValue == null ? "NA" : measurementUnit.Spec.ActualValue.Value.ToString(_precision); |
| | | measurementUnitResult.MeasurementResult = measurementUnit.Spec.MeasureResult == null ? "NA" : measurementUnit.Spec.MeasureResult.Value ? "OK" : "NG"; |
| | | |
| | | measurementUnitResults.Add(measurementUnitResult); |
| | | |
| | | foreach (var keyUnit in measurementUnit.KeyUnitCollection)//获取单个键的测量结果 |
| | | { |
| | | foreach (var keyValue in keyUnit.MeasureValueDict)//获取单个键的单个测量item 结果 |
| | | { |
| | | bool isExist = keyUnitDatas.Any(u => u.Key == keyUnit.Key && u.MeasurementItem == keyValue.Key); |
| | | if (!isExist)//已存在 不重复添加原始数据 |
| | | { |
| | | KeyUnitData keyUnitData = new KeyUnitData(); |
| | | keyUnitData.ProductionBarcode = productionMeasurementRecords.ProductionBarcode; |
| | | keyUnitData.Key = keyUnit.Key; |
| | | keyUnitData.MeasurementItem = keyValue.Key; |
| | | keyUnitData.ItemValue = keyValue.Value == null ? "NA" : keyValue.Value.Value.ToString(_precision); |
| | | keyUnitDatas.Add(keyUnitData); |
| | | |
| | | MeasurementAndKeyDataRelation measurementAndKeyDataRelation = new MeasurementAndKeyDataRelation(); |
| | | measurementAndKeyDataRelation.MeasurementUnitResultId = measurementUnitResult.ID; |
| | | measurementAndKeyDataRelation.KeyUnitDataId = keyUnitData.ID; |
| | | measurementAndKeyDataRelationList.Add(measurementAndKeyDataRelation); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | measurementUnitResultAndKeyUnitDataSet.ProductionMeasurementRecord = productionMeasurementRecords; |
| | | measurementUnitResultAndKeyUnitDataSet.MeasurementAndKeyDataRelationList = measurementAndKeyDataRelationList; |
| | | measurementUnitResultAndKeyUnitDataSet.KeyUnitDataList = keyUnitDatas; |
| | | measurementUnitResultAndKeyUnitDataSet.MeasurementUnitResultList = measurementUnitResults; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogAsync(DateTime.Now, "数据获取异常", ex.GetExceptionMessage()); |
| | | } |
| | | return measurementUnitResultAndKeyUnitDataSet; |
| | | } |
| | | |
| | | //private async void ExportProductionExcel(ProductionMeasurementUnitResultAndKeyUnitDataSet measurementUnitResultAndKeyUnitDataSet) |
| | | //{ |
| | | // if (!Config.IsCSVOutputEnabled) |
| | | // return; |
| | | |
| | | // await Task.Run(() => |
| | | // { |
| | | // ExcelExportSet excelExportDto = new ExcelExportSet(); |
| | | // excelExportDto.Worksheets = new List<string>() { "原始数据", "检测结果" }; |
| | | // var keyUnitColumns = new Dictionary<string, string>() |
| | | // { |
| | | // {"ProductionBarcode", "产品条码"}, |
| | | // {"Key", "键"}, |
| | | // {"MeasurementItem", "检测项"}, |
| | | // {"ItemValue", "检测值"} |
| | | // }; |
| | | // var measurementUnitResultColumns = new Dictionary<string, string>() |
| | | // { |
| | | // {"ProductionBarcode", "产品条码"}, |
| | | // {"MeasurementName", "检测名称"}, |
| | | // {"MeasurementType", "检测类型"}, |
| | | // {"MeasurementValue", "检测值"}, |
| | | // {"MeasurementResult", "检测结果"}, |
| | | // }; |
| | | // excelExportDto.WorksheetColumns[excelExportDto.Worksheets[0]] = keyUnitColumns; |
| | | // excelExportDto.WorksheetColumns[excelExportDto.Worksheets[1]] = measurementUnitResultColumns; |
| | | |
| | | // excelExportDto.WorksheetDataTable[excelExportDto.Worksheets[0]] = ExcelExportHelper.ListToDataTable(measurementUnitResultAndKeyUnitDataSet.KeyUnitDataList, keyUnitColumns); |
| | | // excelExportDto.WorksheetDataTable[excelExportDto.Worksheets[1]] = ExcelExportHelper.ListToDataTable(measurementUnitResultAndKeyUnitDataSet.MeasurementUnitResultList, measurementUnitResultColumns); ; |
| | | |
| | | // if (!Directory.Exists(Config.LogPath)) |
| | | // { |
| | | // Directory.CreateDirectory(Config.LogPath); |
| | | // } |
| | | // var fileName = Path.Combine(Config.LogPath, $"ProductionData_{DateTime.Now.ToString("yyyyMMdd")}.xlsx"); |
| | | |
| | | // byte[] filecontent = ExcelExportHelper.CreateOrAppendExcel(excelExportDto, fileName); |
| | | // FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write); |
| | | // fs.Write(filecontent, 0, filecontent.Length); |
| | | // fs.Flush(); |
| | | // fs.Close(); |
| | | // }); |
| | | //} |
| | | |
| | | static object excelExportLock = new object(); |
| | | private async void ExportProductionInColumns(ProductionMeasurementUnitResultAndKeyUnitDataSet exportData) |
| | | { |
| | | if (!Config.IsCSVOutputEnabled) |
| | | return; |
| | | |
| | | await Task.Run(() => |
| | | { |
| | | lock (excelExportLock) |
| | | { |
| | | if (!Directory.Exists(Config.LogPath)) |
| | | { |
| | | Directory.CreateDirectory(Config.LogPath); |
| | | } |
| | | var fileName = Path.Combine(Config.LogPath, $"LDSData_{DateTime.Now.ToString("yyyyMMdd")}.xlsx"); |
| | | //bool isExisted = File.Exists(fileName); |
| | | using (ExcelPackage package = new ExcelPackage(new FileInfo(fileName))) |
| | | { |
| | | ExcelWorksheet rawDataSheet = null; |
| | | ExcelWorksheet slantSheet = null; |
| | | ExcelWorksheet alignmentSheet = null; |
| | | ExcelWorksheet rowAlignmentSheet = null; |
| | | |
| | | if (!package.Workbook.Worksheets.Any(s => s.Name == "RawData")) |
| | | { |
| | | package.Workbook.Worksheets.Add("RawData"); |
| | | rawDataSheet = package.Workbook.Worksheets["RawData"]; |
| | | for (int i = 0; i < Config.KeyNameCollection.Count; i++) |
| | | { |
| | | var cell = rawDataSheet.Cells[i + 3, 1]; |
| | | cell.Value = Config.KeyNameCollection[i]; |
| | | SetTitleCell(cell, false); |
| | | } |
| | | } |
| | | rawDataSheet = package.Workbook.Worksheets["RawData"]; |
| | | |
| | | if (!package.Workbook.Worksheets.Any(s => s.Name == "Slant")) |
| | | { |
| | | package.Workbook.Worksheets.Add("Slant"); |
| | | slantSheet = package.Workbook.Worksheets["Slant"]; |
| | | |
| | | var keyCell = slantSheet.Cells[2, 1]; |
| | | keyCell.Value = "Key"; |
| | | SetTitleCell(keyCell); |
| | | |
| | | for (int i = 0; i < Config.KeyNameCollection.Count; i++) |
| | | { |
| | | var cell = slantSheet.Cells[i + 3, 1]; |
| | | cell.Value = Config.KeyNameCollection[i]; |
| | | SetTitleCell(cell, false); |
| | | } |
| | | } |
| | | slantSheet = package.Workbook.Worksheets["Slant"]; |
| | | |
| | | if (!package.Workbook.Worksheets.Any(s => s.Name == "Alignment")) |
| | | { |
| | | package.Workbook.Worksheets.Add("Alignment"); |
| | | alignmentSheet = package.Workbook.Worksheets["Alignment"]; |
| | | |
| | | var keysCell = alignmentSheet.Cells[2, 1]; |
| | | keysCell.Value = "Keys"; |
| | | SetTitleCell(keysCell); |
| | | |
| | | var positionCell = alignmentSheet.Cells[2, 2]; |
| | | positionCell.Value = "Positions"; |
| | | SetTitleCell(positionCell); |
| | | |
| | | var alignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType.StartsWith("Alignment")).ToList(); |
| | | for (int i = 0; i < alignmentMeasures.Count(); i++) |
| | | { |
| | | var cellKeys = alignmentSheet.Cells[i + 3, 1]; |
| | | cellKeys.Value = alignmentMeasures[i].Keys; |
| | | SetTitleCell(cellKeys, false); |
| | | |
| | | var cellPosition = alignmentSheet.Cells[i + 3, 2]; |
| | | cellPosition.Value = alignmentMeasures[i].Positions; |
| | | SetTitleCell(cellPosition, false); |
| | | } |
| | | } |
| | | alignmentSheet = package.Workbook.Worksheets["Alignment"]; |
| | | |
| | | if (!package.Workbook.Worksheets.Any(s => s.Name == "RowAlignment")) |
| | | { |
| | | package.Workbook.Worksheets.Add("RowAlignment"); |
| | | rowAlignmentSheet = package.Workbook.Worksheets["RowAlignment"]; |
| | | |
| | | var keysCell = rowAlignmentSheet.Cells[2, 1]; |
| | | keysCell.Value = "Keys"; |
| | | SetTitleCell(keysCell); |
| | | |
| | | var positionCell = rowAlignmentSheet.Cells[2, 2]; |
| | | positionCell.Value = "Positions"; |
| | | SetTitleCell(positionCell); |
| | | |
| | | var rowAlignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType.StartsWith("RowAlignment")).ToList(); |
| | | for (int i = 0; i < rowAlignmentMeasures.Count(); i++) |
| | | { |
| | | var cellKeys = rowAlignmentSheet.Cells[i + 3, 1]; |
| | | cellKeys.Value = rowAlignmentMeasures[i].Keys; |
| | | SetTitleCell(cellKeys, false); |
| | | |
| | | var cellPosition = rowAlignmentSheet.Cells[i + 3, 2]; |
| | | cellPosition.Value = rowAlignmentMeasures[i].Positions; |
| | | SetTitleCell(cellPosition, false); |
| | | } |
| | | } |
| | | rowAlignmentSheet = package.Workbook.Worksheets["RowAlignment"]; |
| | | |
| | | #region RawData |
| | | { |
| | | int rowDataStartCol = rawDataSheet.Dimension.Columns; |
| | | var barcodeCell = rawDataSheet.Cells[1, rowDataStartCol + 1, 1, rowDataStartCol + 4]; |
| | | barcodeCell.Merge = true; |
| | | barcodeCell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; |
| | | barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; |
| | | SetTitleCell(barcodeCell); |
| | | |
| | | var z1Cell = rawDataSheet.Cells[2, rowDataStartCol + 1]; |
| | | z1Cell.Value = "Z1"; |
| | | SetTitleCell(z1Cell); |
| | | |
| | | var z2Cell = rawDataSheet.Cells[2, rowDataStartCol + 2]; |
| | | z2Cell.Value = "Z2"; |
| | | SetTitleCell(z2Cell); |
| | | |
| | | var z3Cell = rawDataSheet.Cells[2, rowDataStartCol + 3]; |
| | | z3Cell.Value = "Z3"; |
| | | SetTitleCell(z3Cell); |
| | | |
| | | var z4Cell = rawDataSheet.Cells[2, rowDataStartCol + 4]; |
| | | z4Cell.Value = "Z4"; |
| | | SetTitleCell(z4Cell); |
| | | |
| | | exportData.KeyUnitDataList.ForEach(k => |
| | | { |
| | | int keyIndex = Config.KeyNameCollection.IndexOf(k.Key); |
| | | if (keyIndex < 0) |
| | | { |
| | | LogAsync(DateTime.Now, "Excel导出错误", $"{k.Key}的RawData未能获取行信息,未导出"); |
| | | return; |
| | | } |
| | | |
| | | int zIndex = int.Parse(k.MeasurementItem.Substring(1)); |
| | | |
| | | var cell = rawDataSheet.Cells[keyIndex + 1 + 2, rowDataStartCol + zIndex]; |
| | | cell.Value = string.IsNullOrWhiteSpace(k.ItemValue) ? "NA" : k.ItemValue; |
| | | }); |
| | | } |
| | | #endregion |
| | | |
| | | #region Slant |
| | | var slantMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType.StartsWith("Slant")).ToList(); |
| | | if (slantMeasures.Count > 0) |
| | | { |
| | | int slantStartCol = slantSheet.Dimension.Columns; |
| | | |
| | | var barcodeCell = slantSheet.Cells[1, slantStartCol + 1]; |
| | | barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; |
| | | SetTitleCell(barcodeCell); |
| | | |
| | | var valueCell = slantSheet.Cells[2, slantStartCol + 1]; |
| | | valueCell.Value = "Value"; |
| | | SetTitleCell(valueCell); |
| | | |
| | | slantMeasures.ForEach(m => |
| | | { |
| | | int rowIndex = Config.KeyNameCollection.IndexOf(m.Keys); |
| | | if (rowIndex < 0) |
| | | { |
| | | LogAsync(DateTime.Now, "Excel导出错误", $"{m.Keys}的Slant未能获取行信息,未导出"); |
| | | return; |
| | | } |
| | | |
| | | var cellValue = slantSheet.Cells[rowIndex + 1 + 2, slantStartCol + 1]; |
| | | //var cellResult = slantSheet.Cells[rowIndex + 1 + 2, slantStartCol + 2]; |
| | | |
| | | cellValue.Value = m.MeasurementValue; |
| | | //cellResult.Value = m.MeasurementResult; |
| | | |
| | | if (m.MeasurementResult != "OK") |
| | | { |
| | | SetNGCell(cellValue); |
| | | //SetNGCell(cellResult); |
| | | } |
| | | }); |
| | | } |
| | | #endregion |
| | | |
| | | #region Alignment |
| | | { |
| | | var alignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType.StartsWith("Alignment")).ToList(); |
| | | if (alignmentMeasures.Count > 0) |
| | | { |
| | | List<string> keysList = new List<string>(); |
| | | int allRowNums = alignmentSheet.Dimension.Rows; |
| | | int aligneStartCol = alignmentSheet.Dimension.Columns; |
| | | |
| | | for (int i = 3; i <= alignmentSheet.Dimension.End.Row; i++) |
| | | { |
| | | string keys = alignmentSheet.Cells[i, 1].Value.ToString(); |
| | | string position = alignmentSheet.Cells[i, 2].Value.ToString(); |
| | | |
| | | keysList.Add($"{keys}_{position}"); |
| | | } |
| | | |
| | | //var barcodeCell = alignmentSheet.Cells[1, aligneStartCol + 1, 1, aligneStartCol + 2]; |
| | | //barcodeCell.Merge = true; |
| | | //barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; |
| | | //SetTitleCell(barcodeCell); |
| | | |
| | | var barcodeCell = alignmentSheet.Cells[1, aligneStartCol + 1]; |
| | | barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; |
| | | SetTitleCell(barcodeCell); |
| | | |
| | | var valueCell = alignmentSheet.Cells[2, aligneStartCol + 1]; |
| | | valueCell.Value = "Value"; |
| | | SetTitleCell(valueCell); |
| | | |
| | | //var resultCell = alignmentSheet.Cells[2, aligneStartCol + 2]; |
| | | //resultCell.Value = "Result"; |
| | | //SetTitleCell(resultCell); |
| | | |
| | | alignmentMeasures.ForEach(a => |
| | | { |
| | | int rowIndex = keysList.IndexOf($"{a.Keys}_{a.Positions}"); |
| | | if (rowIndex < 0) |
| | | { |
| | | LogAsync(DateTime.Now, "Excel导出错误", $"{a.Keys}_{a.Positions}的Alignment未能获取行信息,未导出"); |
| | | return; |
| | | } |
| | | |
| | | var cellValue = alignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 1]; |
| | | //var cellResult = alignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 2]; |
| | | |
| | | cellValue.Value = a.MeasurementValue; |
| | | //cellResult.Value = a.MeasurementResult; |
| | | |
| | | if (a.MeasurementResult != "OK") |
| | | { |
| | | SetNGCell(cellValue); |
| | | //SetNGCell(cellResult); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | #region RowAlignment |
| | | { |
| | | var rowAlignmentMeasures = exportData.MeasurementUnitResultList.Where(u => u.MeasurementType.StartsWith("RowAlignment")).ToList(); |
| | | if (rowAlignmentMeasures.Count > 0) |
| | | { |
| | | List<string> keysList = new List<string>(); |
| | | int allRowNums = rowAlignmentSheet.Dimension.Rows; |
| | | int aligneStartCol = rowAlignmentSheet.Dimension.Columns; |
| | | |
| | | for (int i = 3; i <= allRowNums; i++) |
| | | { |
| | | string keys = alignmentSheet.Cells[i, 1].Value.ToString(); |
| | | string position = alignmentSheet.Cells[i, 2].Value.ToString(); |
| | | |
| | | keysList.Add($"{keys}_{position}"); |
| | | } |
| | | |
| | | //var barcodeCell = rowAlignmentSheet.Cells[1, aligneStartCol + 1, 1, aligneStartCol + 2]; |
| | | //barcodeCell.Merge = true; |
| | | //barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; |
| | | //SetTitleCell(barcodeCell); |
| | | |
| | | var barcodeCell = rowAlignmentSheet.Cells[1, aligneStartCol + 1]; |
| | | barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode; |
| | | SetTitleCell(barcodeCell); |
| | | |
| | | var valueCell = rowAlignmentSheet.Cells[2, aligneStartCol + 1]; |
| | | valueCell.Value = "Value"; |
| | | SetTitleCell(valueCell); |
| | | |
| | | //var resultCell = rowAlignmentSheet.Cells[2, aligneStartCol + 2]; |
| | | //resultCell.Value = "Result"; |
| | | //SetTitleCell(resultCell); |
| | | |
| | | rowAlignmentMeasures.ForEach(a => |
| | | { |
| | | int rowIndex = keysList.IndexOf($"{a.Keys}_{a.Positions}"); |
| | | if (rowIndex < 0) |
| | | { |
| | | LogAsync(DateTime.Now, "Excel导出错误", $"{a.Keys}_{a.Positions}的RowAlignment未能获取行信息,未导出"); |
| | | return; |
| | | } |
| | | |
| | | var cellValue = rowAlignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 1]; |
| | | //var cellResult = rowAlignmentSheet.Cells[rowIndex + 1 + 2, aligneStartCol + 2]; |
| | | |
| | | cellValue.Value = a.MeasurementValue; |
| | | //cellResult.Value = a.MeasurementResult; |
| | | |
| | | if (a.MeasurementResult != "OK") |
| | | { |
| | | SetNGCell(cellValue); |
| | | //SetNGCell(cellResult); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | package.Save(); |
| | | |
| | | rawDataSheet.Dispose(); |
| | | slantSheet.Dispose(); |
| | | alignmentSheet.Dispose(); |
| | | rowAlignmentSheet.Dispose(); |
| | | }; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private void SetNGCell(ExcelRange cell) |
| | | { |
| | | cell.Style.Font.Color.SetColor(Color.Red); |
| | | cell.Style.Font.Bold = true; |
| | | //cell.Style.Fill.PatternType = ExcelFillStyle.Solid; |
| | | //cell.Style.Fill.BackgroundColor.SetColor(Color.Red); |
| | | } |
| | | |
| | | private void SetTitleCell(ExcelRange cell, bool isCenterAlign = true) |
| | | { |
| | | cell.Style.Font.Color.SetColor(Color.White); |
| | | cell.Style.Font.Bold = true; |
| | | cell.Style.Fill.PatternType = ExcelFillStyle.Solid; |
| | | cell.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(31, 73, 125)); |
| | | cell.AutoFitColumns(); |
| | | if (isCenterAlign) |
| | | { |
| | | cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; |
| | | } |
| | | else |
| | | { |
| | | cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Left; |
| | | } |
| | | } |
| | | |
| | |
| | | Directory.CreateDirectory(dir); |
| | | } |
| | | |
| | | map.Save(Path.Combine(dir, $"{pMeasure.Barcode}_{DateTime.Now.ToString("HHmmss")}.bmp")); |
| | | map.Save(Path.Combine(dir, $"{pMeasure.Barcode}_{pMeasure.PResult}_{DateTime.Now.ToString("HHmmss")}.png"), ImageFormat.Png); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | private void SaveKeyImages(string barCode, MeasurementUint measureUnit) |
| | | private void SaveKeyImages(string barCode, MeasurementUnit measureUnit) |
| | | { |
| | | string measureName = measureUnit.GetDisplayText(); |
| | | if (Config.ImageSaveOption.IsSaveOriginImage) |
| | |
| | | } |
| | | } |
| | | |
| | | private async void SaveKeyImages(MeasurementUint measureUnit, string measureName, string dir) |
| | | private async void SaveKeyImages(MeasurementUnit measureUnit, string measureName, string dir) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | |
| | | int i = 0; |
| | | u.KeyImages?.ForEach(image => |
| | | { |
| | | string fileName = Path.Combine(dir, $"{measureName}_{u.Key}{(i == 0 ? "" : $"-{i}")}_{DateTime.Now.ToString("HHmmss")}.tiff"); |
| | | image.WriteImage("tiff", 0, fileName); |
| | | string fileName = ""; |
| | | try |
| | | { |
| | | fileName = Path.Combine(dir, $"{measureName}_{u.Key}{(i == 0 ? "" : $"-{i}")}_{DateTime.Now.ToString("HHmmss")}.tiff"); |
| | | image.WriteImage("tiff", 0, fileName); |
| | | } |
| | | catch (Exception) |
| | | { |
| | | LogAsync(DateTime.Now, "切图保存失败", fileName); |
| | | } |
| | | i++; |
| | | }); |
| | | |
| | |
| | | } |
| | | #endregion |
| | | |
| | | private async void RunImageHandle(CameraBase camera, IOperationConfig opConfig, HImage hImage, string snapshotId, string snapshotName, List<MeasurementUint> measureList) |
| | | private async void RunImageHandle(IOperationConfig opConfig, IImageSet imgSet, string snapshotId, string snapshotName, List<MeasurementUnit> 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(); |
| | | { |
| | | 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 = hImage; |
| | | string toolKey = (opConfig as CameraOprerationConfigBase).AlgorithemPath; |
| | | |
| | | if (!string.IsNullOrWhiteSpace(toolKey)) |
| | | { |
| | | toolKey = snapshotId + "|" + toolKey; |
| | | if (!_halconToolDict.ContainsKey(toolKey)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{snapshotName}未初始化取图算法配置", ""); |
| | | keyBindCollection.ForEach(k => k.FillKeyValues(null)); |
| | | return; |
| | | } |
| | | HObject images = new HObject(); |
| | | LaserScanParam scanParam = JsonConvert.DeserializeObject<LaserScanParam>(imgSet.ImageData); |
| | | LogAsync(DateTime.Now, $"扫描参数:{imgSet.ImageData}", ""); |
| | | |
| | | _halconToolDict[toolKey].InputImageDic["INPUT_Image"] = hImage; |
| | | if (!_halconToolDict[toolKey].RunProcedure(out string error)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{snapshotName}取图算法异常,{error}", ""); |
| | | keyBindCollection.ForEach(k => k.FillKeyValues(null)); |
| | | return; |
| | | } |
| | | if (!string.IsNullOrWhiteSpace(toolKey)) |
| | | { |
| | | toolKey = snapshotId + "|" + toolKey; |
| | | if (!_halconToolDict.ContainsKey(toolKey)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{snapshotName}未初始化取图算法配置", ""); |
| | | keyBindCollection.ForEach(k => k.FillKeyValues(null)); |
| | | return; |
| | | } |
| | | |
| | | images = _halconToolDict[toolKey].GetResultObject("OUTPUT_Images"); |
| | | } |
| | | //string fileName = Path.Combine(Config.ImageSaveFolder, "BeforeRun", $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.tif"); |
| | | //imgSet.HImage.WriteImage("tiff", 0, fileName); |
| | | |
| | | HOperatorSet.CountObj(images, out HTuple count); |
| | | if (imgSet.HImage == null) |
| | | { |
| | | LogAsync(DateTime.Now, $"{snapshotName}图片为空对象", ""); |
| | | keyBindCollection.ForEach(k => k.FillKeyValues(null)); |
| | | return; |
| | | } |
| | | |
| | | if (count == 0) |
| | | { |
| | | 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; |
| | | } |
| | | |
| | | 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); |
| | | }); |
| | | } |
| | | images = _halconToolDict[toolKey].GetResultObject("OUTPUT_Images"); |
| | | } |
| | | |
| | | Parallel.For(1, count.I, (i) => |
| | | { |
| | | HOperatorSet.SelectObj(images, out HObject image, i); |
| | | HOperatorSet.CountObj(images, out HTuple count); |
| | | LogAsync(DateTime.Now, $"{snapshotName}切图{count.I}张", ""); |
| | | |
| | | keys.Where(u => u.ImageSeq == i).ToList().ForEach(k => |
| | | { |
| | | Dictionary<string, double> resultDict = null; |
| | | if (count == 0) |
| | | { |
| | | LogAsync(DateTime.Now, $"{snapshotName}取图算法未输出图像", ""); |
| | | keyBindCollection.ForEach(k => k.FillKeyValues(null)); |
| | | return; |
| | | } |
| | | |
| | | var keyBindList = keyBindCollection.Where(u => u.Key == k.Key).ToList(); |
| | | var excludeKeys = keys.Where(u => u.ImageSeq > count.I).ToList(); |
| | | if (excludeKeys.Count > 0) |
| | | { |
| | | LogAsync(DateTime.Now, $"{string.Join(" ", excludeKeys.Select(u => u.AliasName))}未在图片获取序列中", ""); |
| | | keyBindCollection.Where(k => excludeKeys.Any(u => u.Key == k.Key)).ToList().ForEach(k => |
| | | { |
| | | k.FillKeyValues(null); |
| | | }); |
| | | } |
| | | |
| | | 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]; |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | //string dir = Path.Combine(Config.ImageSaveFolder, "Clips", $"{DateTime.Now.ToString("yyyyMMdd")}", $"{snapshotName}_{DateTime.Now.ToString("HHmmss")}"); |
| | | //if (!Directory.Exists(dir)) |
| | | //{ |
| | | // Directory.CreateDirectory(dir); |
| | | //} |
| | | |
| | | keyBindList.ForEach(kb => |
| | | { |
| | | kb.KeyImages.Add(image.Clone() as HImage); |
| | | kb.FillKeyValues(resultDict); |
| | | }); |
| | | }); |
| | | //Parallel.For(1, count.I + 1, (i) => |
| | | for (int i = 1; i <= count.I; i++) |
| | | { |
| | | HOperatorSet.SelectObj(images, out HObject image, i); |
| | | |
| | | image.Dispose(); |
| | | }); |
| | | //string fileName = Path.Combine(dir, $"{i}.tif"); |
| | | //using (HImage temp = image.ConvertHObjectToHImage()) |
| | | //{ |
| | | // temp.WriteImage("tiff", 0, fileName); |
| | | //} |
| | | |
| | | if (count.I != 1) |
| | | { |
| | | hImage?.Dispose(); |
| | | hImage = null; |
| | | } |
| | | }); |
| | | keys.Where(u => u.ImageSeq == i).ToList().ForEach(k => |
| | | { |
| | | Dictionary<string, double> resultDict = null; |
| | | |
| | | var keyBindList = keyBindCollection.Where(u => u.Key == k.Key).ToList(); |
| | | |
| | | string keyToolKey = k.AliasName + "|" + k.KeyAlgorithemPath; |
| | | if (!_halconToolDict.ContainsKey(keyToolKey)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{k.AliasName}检测算法未初始化", ""); |
| | | } |
| | | else |
| | | { |
| | | _halconToolDict[keyToolKey].InputImageDic["INPUT_Image"] = image; |
| | | _halconToolDict[keyToolKey].InputTupleDic["INPUT_Resolution_X"] = scanParam.Resolution_X / 1000000.0; |
| | | _halconToolDict[keyToolKey].InputTupleDic["INPUT_Resolution_Y"] = scanParam.Resolution_Y / 1000000.0; |
| | | _halconToolDict[keyToolKey].InputTupleDic["INPUT_Resolution_Z"] = scanParam.Resolution_Z / 1000000.0; |
| | | _halconToolDict[keyToolKey].InputTupleDic["INPUT_ImageId"] = $"{k.AliasName}_{DateTime.Now.ToString("HHmmssfff")}.tif"; |
| | | if (!_halconToolDict[keyToolKey].RunProcedure(out string error)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{k.AliasName}检测算法异常,{error}", ""); |
| | | } |
| | | else |
| | | { |
| | | var results = _halconToolDict[keyToolKey].GetResultTuple("OUTPUT_Results").DArr.ToList(); |
| | | if (results.Count == 0 || results.Any(u => u < 0)) |
| | | { |
| | | LogAsync(DateTime.Now, $"{k.AliasName}原始数据异常", ""); |
| | | } |
| | | else |
| | | { |
| | | //LogAsync(DateTime.Now, $"{k.AliasName}原始数据", $"{string.Join(" ", results)}"); |
| | | |
| | | results = results.Select(u => u - Config.PlanCompensation).ToList(); |
| | | resultDict = k.KeyResultList.ToDictionary(u => u, u => |
| | | { |
| | | int index = k.KeyResultList.IndexOf(u); |
| | | return results[index]; |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | |
| | | keyBindList.ForEach(kb => |
| | | { |
| | | kb.KeyImages.Add(image.ConvertHObjectToHImage()); |
| | | kb.FillKeyValues(resultDict); |
| | | }); |
| | | }); |
| | | |
| | | image.Dispose(); |
| | | image = null; |
| | | } |
| | | //); |
| | | |
| | | imgSet.HImage.Dispose(); |
| | | imgSet.HImage = null; |
| | | imgSet.Dispose(); |
| | | |
| | | images.Dispose(); |
| | | images = null; |
| | | |
| | | //if (count.I != 1) |
| | | //{ |
| | | // hImage?.Dispose(); |
| | | // hImage = null; |
| | | //} |
| | | }); |
| | | } |
| | | #endregion |
| | | } |