using Bro.Common.Base; 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.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using static Bro.Common.Helper.EnumHelper; 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 OnClearBarcode; public event Action OnElementUpdated; public event Action OnMachineStateChanged; public event Action OnFullResetDone; public event Action OnResetDone; #endregion string _precision = "f3"; double _allowedShift = 0; double _allowedShift2 = 0; public override void Open() { InitialSetting(); if (!Config.IsOfflineMode) { base.Open(); InitialMotionCardBaseAxisAlarm(); SwitchBeep(false); SwitchLightGreen(false); SwitchLightRed(false); SwitchLightYellow(false); Reset(null, null, null); FullReset(null); } if (Config.Precision > 0) { _precision = "f" + Config.Precision; } if (Config.IsEnableMESUpload) { IncomingCheckMethod = InitialMESWebServiceMethod(IncomingCheckMethodName, out IncomingCheckObj); DataUploadMethod = InitialMESWebServiceMethod(DataUploadMethodName, out DataUploadObj); } PrepareDataShift(); } private void PrepareDataShift() { var allowedShiftStr = ConfigurationManager.AppSettings["DataShift"]; if (!double.TryParse(allowedShiftStr, out _allowedShift)) { _allowedShift = 0; } string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dataShift"); if (!File.Exists(path)) { _allowedShift2 = 0; } else { using (StreamReader reader = new StreamReader(path, System.Text.Encoding.UTF8)) { string data = reader.ReadToEnd(); if (!string.IsNullOrWhiteSpace(data)) { if (double.TryParse(data, out double dataValue)) { _allowedShift2 = dataValue; } } } } _allowedShift += _allowedShift2; } private void InitialMotionCardBaseAxisAlarm() { 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 => { 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.AliasName}未设置可用拍照点位"); if (u.ImageSeq < 1) throw new ProcessException($"{u.AliasName}图片序号小于1"); var algo = Config.KeyAlgorithemCollection.FirstOrDefault(a => a.Id == u.KeyAlgorithemId); if (algo == null) throw new ProcessException($"{u.AliasName}未设置检测算法"); u.KeyAlgorithemPath = algo.AlgorithemPath; LoadHalconTool(u.KeyAlgorithemPath, u.AliasName); var resultSet = Config.KeyResultCollection.FirstOrDefault(r => r.Id == u.KeyResultId); if (resultSet == null) throw new ProcessException($"{u.AliasName}未设置检测结果配置"); 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.KeyResultId == "All") { keyRespone.SelectMany(kr => kr.KeyResultList).ToList().ForEach(r => { b.MeasureValueDict[r] = null; }); } else { b.MeasureValueDict[b.KeyResultId] = null; } }); }); } #region 流程中抛出异常 public override void ExceptionRaisedInMonitor(Exception ex) { if (ex is ProcessException pEx) { if (pEx.Level >= ExceptionLevel.Fatal) { RaisedAlarm(pEx.Message); MachineState = MachineState.Alarm; } } else { RaisedAlarm(ex.Message); MachineState = MachineState.Alarm; } } #endregion AutoResetEvent _jobDoneHandle = new AutoResetEvent(false); [ProcessMethod("ManualTest", "ManualTest", "手动测试", InvokeType.TestInvoke)] public ProcessResponse ManualTest(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice) { if (config is ManualTestOperationConfig opConfig) { Task.Run(async () => { for (int i = 0; i < opConfig.RepeatTimes; i++) { BarCode = $"Test_{i + 1}"; StartJob(null, null, null); if (_jobDoneHandle.WaitOne(20000)) { LogAsync(DateTime.Now, $"第{i + 1}次任务完成", ""); await Task.Delay(500); } else { LogAsync(DateTime.Now, $"第{i + 1}次任务超时", ""); break; } } }); } return new ProcessResponse(true); } object productionLock = new object(); List productionList = new List(); bool _isdoing = false; object _doingLock = new object(); [ProcessMethod("", "StartJob", "开始扫描", InvokeType.TestInvoke)] public ProcessResponse StartJob(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { if (!IsAllowedWork) { throw new ProcessException(SafetyMsg, null, ExceptionLevel.Fatal); } 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); } lock (_doingLock) { if (_isdoing) { LogAsync(DateTime.Now, "设备正在运行中", ""); return new ProcessResponse(true); } _isdoing = true; } MeasureState = 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 measurements = new List(); 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 = ""; lock (productionLock) { var existedProduction = productionList.FirstOrDefault(u => u.Barcode == pMeasure.Barcode); if (existedProduction != null) { productionList.Remove(existedProduction); existedProduction.Dispose(); existedProduction = null; } productionList.Add(pMeasure); } pMeasure.InitialMeasurementsPropertyChanged(); pMeasure.PropertyChanged += MeasureProduction_PropertyChanged; try { Config.SnapshotPointCollection.Where(u => u.IsEnabled).ToList().ForEach(s => { _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) throw new ProcessException($"{s.Name}拍照点位未设置运动设备"); IMotionCard motionDevice = device as IMotionCard; if (motionDevice == null) throw new ProcessException($"{s.Name}拍照点位设置{device.Name}不是运动设备"); var response = motionDevice.Run(s.MotionOp.OpConfig); if (!response.Result) { 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; IImageSet set = null; try { set = CollectHImage(camera, s.CameraOp.OpConfig); } catch (ProcessException pEx) { pEx.Level = ExceptionLevel.Fatal; throw pEx; } if (set == null) { return; } RunImageHandle(s.CameraOp.OpConfig, set, s.Id, s.Name, pMeasure.Measurements); }); } catch (Exception ex) { throw ex; } finally { LogAsync(DateTime.Now, $"{pMeasure.Barcode}测量动作完成", ""); _isdoing = false; GC.Collect(0, GCCollectionMode.Optimized); } return new ProcessResponse(true); } #region 双手启动 object _leftStartLock = new object(); object _rightStartLock = new object(); bool isLeftStart = false; bool IsLeftStart { get => isLeftStart; set { if (isLeftStart != value) { lock (_leftStartLock) { if (IsLeftStart != value) { isLeftStart = value; StartCheck(); } } } } } bool isRightStart = false; bool IsRightStart { get => isRightStart; set { if (isRightStart != value) { lock (_rightStartLock) { if (isRightStart != value) { isRightStart = value; StartCheck(); } } } } } private void StartCheck() { if (isRightStart && isLeftStart) { if (_isdoing) { OnCheckHintUpload?.Invoke("设备运行中", false); return; } 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(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(); } [ProcessMethod("KeyUnitGenerate", "GenerateKeyUnitByKeyNames", "生成单键配置", InvokeType.TestInvoke)] public ProcessResponse GenerateKeyUnitByKeyNames(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { if (opConfig is KeyUnitGenerateConfig config) { int i = 1; bool isStart = false; bool isEnd = false; foreach (string k in Config.KeyNameCollection) { if (k == config.StartKey) { isStart = true; } else if (k == config.EndKey) { isEnd = true; } if (isStart) { KeyUnit unit = new KeyUnit(); unit.Key = unit.AliasName = k; unit.SnapshotPointId = config.SnapshotPointId; unit.KeyAlgorithemId = config.KeyAlgorithemId; unit.KeyResultId = config.KeyResultId; unit.ImageSeq = i; Config.KeyUnitCollection.Add(unit); i++; } if (isEnd) { break; } } } return new ProcessResponse(true); } [ProcessMethod("", "SortKeyUnits", "单键配置排序", InvokeType.TestInvoke)] public ProcessResponse SortKeyUnits(IOperationConfig opConfig, IDevice invokeDevice, IDevice sourceDevice) { if (Config.KeyUnitCollection.Count > 0) { Config.KeyUnitCollection = Config.KeyUnitCollection.OrderBy(u => u.SnapshotPointId).ThenBy(u => u.ImageSeq).ToList(); } return new ProcessResponse(true); } #endregion #region 私有方法 private void MeasureProduction_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (sender is ProductionMeasurement pMeasure) { ProductionMeasurement production = null; lock (productionLock) { production = productionList.FirstOrDefault(u => u.Barcode == pMeasure.Barcode); if (production == null) return; } lock (production) { //检查是否全部完成 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; m.Spec.ActualValue = null; } else { string toolKey = m.Id + "|" + m.Spec.AlgorithemPath; if (!_halconToolDict.ContainsKey(toolKey)) { LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}算法未初始化", ""); //m.Spec.ActualValue = -999; m.Spec.ActualValue = null; } else { //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}未能获取对应检测值", ""); //m.Spec.ActualValue = -999; m.Spec.ActualValue = null; } else { _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; if (m.MeasureType.ToLower() == "alignment" || m.MeasureType.ToLower() == "slant") { //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); } } } } } } if (m.Spec?.ActualValue != null) { LogAsync(DateTime.Now, $"{m.Name}检测结果{m.Spec.ActualValue.Value.ToString(_precision)}", ""); } 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); //输出图形基元到界面 OnElementUpdated?.Invoke(indicator); SaveKeyImages(pMeasure.Barcode, m); m.IsUpdated = true; } } }); if (!pMeasure.Measurements.All(m => m.IsUpdated)) { return; } } 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; MeasureState = MachineState.Ready; if (MachineState != MachineState.Alarm) { if (MachineState == MachineState.Pause) { _machineStateBeforePause = MachineState.Ready; } else { MachineState = MachineState.Ready; } } _jobDoneHandle.Set(); var measurementUnitResultAndKeyUnitDataSet = GetMeasurementUnitResultAndKeyUnitData(pMeasure); if (pMeasure.PResult != "NA") { //MES输出 MESCheckDataUpload(pMeasure); } //Excel报表输出 (单个产品的excel导出) //ExportProductionExcel(measurementUnitResultAndKeyUnitDataSet); ExportProductionInColumns(measurementUnitResultAndKeyUnitDataSet); ////数据库保存 //SaveProductionData(measurementUnitResultAndKeyUnitDataSet); SaveWholeImage(pMeasure); lock (productionLock) { 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 measurementAndKeyDataRelationList = new List(); //原始数据 List keyUnitDatas = new List(); // 单个产品的测量汇总 List measurementUnitResults = new List(); 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() { "原始数据", "检测结果" }; // var keyUnitColumns = new Dictionary() // { // {"ProductionBarcode", "产品条码"}, // {"Key", "键"}, // {"MeasurementItem", "检测项"}, // {"ItemValue", "检测值"} // }; // var measurementUnitResultColumns = new Dictionary() // { // {"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(); string fileName = ""; private async void ExportProductionInColumns(ProductionMeasurementUnitResultAndKeyUnitDataSet exportData) { if (!Config.IsCSVOutputEnabled) return; await Task.Run(() => { lock (excelExportLock) { if (!Directory.Exists(Config.LogPath)) { Directory.CreateDirectory(Config.LogPath); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = Path.Combine(Config.LogPath, $"LDSData_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.xlsx"); } try { 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 keysList = new List(); 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 keysList = new List(); 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(); }; } catch (Exception ex) { LogAsync(DateTime.Now, "Excel日志异常", ex.GetExceptionMessage()); fileName = Path.Combine(Config.LogPath, $"LDSData_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.xlsx"); //string bkFileName = Path.Combine(Config.LogPath, $"{Path.GetFileNameWithoutExtension(fileName)}_bk_{DateTime.Now.ToString("HHmmss")}.xlsx"); //File.Copy(fileName, bkFileName); //File.Delete(fileName); } } }); } 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; } } #region 图像保存 private void SaveWholeImage(ProductionMeasurement pMeasure) { try { Bitmap backImage = (Bitmap)Bitmap.FromFile(Config.BackgroundImagePath); Bitmap map = new Bitmap(backImage.Width, backImage.Height); using (Graphics g = Graphics.FromImage(map)) { g.DrawImage(backImage, new PointF(0, 0)); pMeasure.ElementList.ForEach(e => { e.Draw(g); }); } string dir = Path.Combine(Config.ImageSaveFolder, "TopView", DateTime.Now.ToString("yyyyMMdd")); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } map.Save(Path.Combine(dir, $"{pMeasure.Barcode}_{pMeasure.PResult}_{DateTime.Now.ToString("HHmmss")}.png"), ImageFormat.Png); } catch (Exception ex) { LogAsync(DateTime.Now, "整体图片保存异常", ex.GetExceptionMessage()); } } private void SaveKeyImages(string barCode, MeasurementUnit measureUnit) { string measureName = measureUnit.GetDisplayText(); if (Config.ImageSaveOption.IsSaveOriginImage) { measureUnit.KeyUnitCollection.ForEach(u => u.ImageSaveStatus++); string dir = Path.Combine(Config.ImageSaveFolder, "Origin", DateTime.Now.ToString("yyyyMMdd"), barCode, measureUnit.MeasureType); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } SaveKeyImages(measureUnit, measureName, dir); } string result = (measureUnit.Spec.MeasureResult ?? false) ? "OK" : "NG"; if (Config.ImageSaveOption.AddtionalSaveType.ToUpper().Contains(result)) { measureUnit.KeyUnitCollection.ForEach(u => u.ImageSaveStatus++); string dir = Path.Combine(Config.ImageSaveFolder, result, DateTime.Now.ToString("yyyyMMdd"), barCode, measureUnit.MeasureType); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } SaveKeyImages(measureUnit, measureName, dir); } } private async void SaveKeyImages(MeasurementUnit measureUnit, string measureName, string dir) { await Task.Run(() => { measureUnit.KeyUnitCollection.ForEach(u => { int i = 0; u.KeyImages?.ForEach(image => { 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++; }); u.ImageSaveStatus--; }); }); } #endregion static object _resultCalcLock = new object(); private async void RunImageHandle(IOperationConfig opConfig, IImageSet 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(); if (imgSet.HImage == null) { LogAsync(DateTime.Now, $"{snapshotName}未获取扫描图像", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } string toolKey = (opConfig as CameraOprerationConfigBase).AlgorithemPath; HObject images = new HObject(); LaserScanParam scanParam = JsonConvert.DeserializeObject(imgSet.ImageData); LogAsync(DateTime.Now, $"扫描参数:{imgSet.ImageData}", ""); if (!string.IsNullOrWhiteSpace(toolKey)) { toolKey = snapshotId + "|" + toolKey; if (!_halconToolDict.ContainsKey(toolKey)) { LogAsync(DateTime.Now, $"{snapshotName}未初始化取图算法配置", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } //string fileName = Path.Combine(Config.ImageSaveFolder, "BeforeRun", $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.tif"); //imgSet.HImage.WriteImage("tiff", 0, fileName); if (imgSet.HImage == null) { 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); LogAsync(DateTime.Now, $"{snapshotName}切图{count.I}张", ""); if (count == 0) { LogAsync(DateTime.Now, $"{snapshotName}取图算法未输出图像", ""); keyBindCollection.ForEach(k => k.FillKeyValues(null)); return; } 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 dir = Path.Combine(Config.ImageSaveFolder, "Clips", $"{DateTime.Now.ToString("yyyyMMdd")}", $"{snapshotName}_{DateTime.Now.ToString("HHmmss")}"); //if (!Directory.Exists(dir)) //{ // Directory.CreateDirectory(dir); //} lock (_resultCalcLock) { //Parallel.For(1, count.I + 1, (i) => for (int i = 1; i <= count.I; i++) { HOperatorSet.SelectObj(images, out HObject image, i); //string fileName = Path.Combine(dir, $"{i}.tif"); //using (HImage temp = image.ConvertHObjectToHImage()) //{ // temp.WriteImage("tiff", 0, fileName); //} 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.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").HTupleToDouble(); if (results.Count == 0 || results.Any(u => u < 0)) { LogAsync(DateTime.Now, $"{k.AliasName}原始数据{string.Join(",", results)}异常", ""); } else { //LogAsync(DateTime.Now, $"{k.AliasName}原始数据", $"{string.Join(" ", results)}"); results = results.Select(u => u - Config.PlanCompensation).ToList(); string resultStr = ""; resultDict = k.KeyResultList.ToDictionary(u => u, u => { int index = k.KeyResultList.IndexOf(u); if (index < results.Count && index >= 0) { double origin = results[index]; var compensation = k.KeyCompensationCollection.FirstOrDefault(c => c.KeyResult == u); if (compensation != null) { origin = origin + compensation.Compensation; } resultStr += $"{u} {origin};"; return origin; } else { return -999.0; } }); LogAsync(DateTime.Now, $"{k.AliasName}结果:{resultStr}", ""); } } } keyBindList.ForEach(kb => { if (kb.KeyImages != null) { kb.KeyImages.Add(image.ConvertHObjectToHImage()); kb.FillKeyValues(resultDict); } else { } }); }); 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 } }