using Bro.Common.Base;
|
using Bro.Common.Helper;
|
using Bro.Common.Interface;
|
using Bro.Common.Model;
|
using Bro.M135.Common;
|
using Bro.M141.Process;
|
using Bro.UI.Model.Winform;
|
using HalconDotNet;
|
using NPOI.POIFS.Crypt.Dsig;
|
using NPOI.SS.Formula.Functions;
|
using NPOI.XSSF.Streaming.Values;
|
using System.Collections.Concurrent;
|
using System.Net.Sockets;
|
using System.Text.RegularExpressions;
|
using static NPOI.HSSF.Util.HSSFColor;
|
using static Org.BouncyCastle.Crypto.Engines.SM2Engine;
|
using static Org.BouncyCastle.Math.EC.ECCurve;
|
using static ScottPlot.Plottable.PopulationPlot;
|
|
namespace Bro.M141_AOI1.Process
|
{
|
[Process("AOI1", EnumHelper.DeviceAttributeType.Device)]
|
public class AOI1Process : M141Process
|
{
|
#region constructor
|
public AOI1Process() : base() { }
|
public AOI1Process(string productCode) : base(productCode) { }
|
#endregion
|
|
AOI1Config ConfigAOI1 => Config as AOI1Config;
|
TcpClientWrapBase BarcodeScanner = null;
|
|
|
public override void Open()
|
{
|
base.Open();
|
BarcodeScanner = DeviceCollection.FirstOrDefault(u => u is TcpClientWrapBase) as TcpClientWrapBase;
|
}
|
|
[ProcessMethod("", "PositionCheck_P1", "工位1检测", InvokeType.TestInvoke)]
|
public ResponseMessage PositionCheck_P1(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
|
{
|
|
var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == "1#");
|
if (positionSet == null)
|
{
|
throw new ProcessException($"P1检测未能获取对应的可用工位信息");
|
}
|
var plcnum = Plc1.Read(positionSet.plcnum, 1, out _);
|
|
config.TriggerStr = "1#,1,Str," + plcnum[0];
|
ResponseMessage msg = RunImageCheck_plc(config);
|
msg.IsReply = false;
|
|
return msg;
|
}
|
|
[ProcessMethod("", "PositionCheck_P2", "工位2检测", InvokeType.TestInvoke)]
|
public ResponseMessage PositionCheck_P2(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
|
{
|
var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == "2#");
|
if (positionSet == null)
|
{
|
throw new ProcessException($"P2检测未能获取对应的可用工位信息");
|
}
|
var plcnum = Plc1.Read(positionSet.plcnum, 1, out _);
|
|
config.TriggerStr = "2#,1,Str," + plcnum[0];
|
ResponseMessage msg = RunImageCheck_plc(config);
|
msg.IsReply = false;
|
|
return msg;
|
}
|
|
[ProcessMethod("", "PositionCheck_P3", "工位3检测", InvokeType.TestInvoke)]
|
public ResponseMessage PositionCheck_P3(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
|
{
|
var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == "3#");
|
if (positionSet == null)
|
{
|
throw new ProcessException($"P3检测未能获取对应的可用工位信息");
|
}
|
var plcnum = Plc1.Read(positionSet.plcnum, 1, out _);
|
|
config.TriggerStr = "3#,1,Str," + plcnum[0];
|
ResponseMessage msg = RunImageCheck_plc(config);
|
msg.IsReply = false;
|
|
return msg;
|
}
|
|
|
|
[ProcessMethod("ImageCheck", "ReadBarcode", "读码", InvokeType.TestInvoke)]
|
public ResponseMessage ReadBarcode(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
|
{
|
ResponseMessage msg = new ResponseMessage();
|
if (config is IImageCheckOperationConfig opConfig)
|
{
|
var results = opConfig.Products.Select(u =>
|
{
|
DetectResult result = new DetectResult();
|
result.PID = u.PID;
|
result.Specs = GetSpecListFromConfigSelection(opConfig.SpecCollection);
|
return result;
|
}).ToList();
|
|
msg.DataObj = results;
|
|
string barcode = BarcodeScannerCommunicate();
|
|
List<double> ret = new List<double>();
|
if ("NOREAD".Equals(barcode.ToUpper()))
|
{
|
ret.Add(999);
|
}
|
else
|
{
|
ret.Add(1);
|
}
|
|
FillSpecResults(results[0].PID, results[0].Specs, ret, opConfig.Products[0].SEQUENCE);
|
|
|
opConfig.Products[0].SN = barcode;
|
opConfig.Products[0].Details.ForEach(u => u.SN = barcode);
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{opConfig.Products[0].PID}条码获取为{barcode}");
|
|
}
|
return msg;
|
}
|
|
|
|
private string BarcodeScannerCommunicate()
|
{
|
string barcode = "";
|
|
for (int i = 0; i < 3; i++)
|
{
|
if (BarcodeScanner.WriteAndRead("start", out string error, out barcode, true))
|
{
|
barcode = barcode.Trim(' ', '\r', '\n');
|
if (CheckBarcodeValid(barcode))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{BarcodeScanner.Name}扫码完成,反馈{barcode}");
|
return barcode;
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{BarcodeScanner.Name}第{i + 1}扫码完成,反馈{barcode},不是合法条码");
|
Thread.Sleep(200);
|
}
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{BarcodeScanner.Name}扫码失败,{error}");
|
break;
|
}
|
}
|
|
return "NOREAD";
|
}
|
|
private bool CheckBarcodeValid(string barcode)
|
{
|
bool isBarcodeValid = true;
|
if (string.IsNullOrWhiteSpace(barcode) || barcode == "NA" || barcode == "NoRead")
|
{
|
isBarcodeValid = false;
|
}
|
return isBarcodeValid;
|
}
|
|
|
|
|
|
|
[ProcessMethod("ImageCheck", "CheckLineProfile", "检测产品线轮廓度", InvokeType.TestInvoke)]
|
public ResponseMessage CheckLineProfile(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
|
{
|
ResponseMessage msg = new ResponseMessage();
|
try
|
{
|
if (config is IImageCheckOperationConfig opConfig)
|
{
|
var results = opConfig.Products.Select(u =>
|
{
|
DetectResult result = new DetectResult();
|
result.PID = u.PID;
|
result.Specs = GetSpecListFromConfigSelection(opConfig.SpecCollection);
|
return result;
|
}).ToList();
|
|
List<ContourPoint> CheckPointList = GetPointListFromConfigSelection(opConfig.CheckPointList);
|
msg.DataObj = results;
|
CheckPointList = CheckPointList.OrderBy(u => u.index).ToList();
|
|
List<double> pointdataF = new List<double>();
|
foreach (var item in CheckPointList)
|
{
|
pointdataF.Add(item.X);
|
pointdataF.Add(item.Y);
|
}
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"检测产品线轮廓度输入点数据 {string.Join(',', pointdataF)}");
|
|
var tool = GetHalconTool(null, "", opConfig.AlgorithemPath);
|
var ret = tool.RunProcedure(new Dictionary<string, HalconDotNet.HTuple>() { { "INPUT_Points", pointdataF.ToArray() } }, new Dictionary<string, HalconDotNet.HObject>() { { "INPUT_Image", opConfig.ImageSet.HImage } }, new List<string>() { "OUTPUT_Results", "OUTPUT_PointZ" }, null);
|
|
if (ret == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"脚本{opConfig.AlgorithemPath}运行异常,返回值为null");
|
}
|
else if (!ret.Item1)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"脚本{opConfig.AlgorithemPath}运行异常,{ret.Item4}");
|
}
|
else
|
{
|
//List<double> datasX = ret.Item2["OUTPUT_PointX"].HTupleToDouble();
|
//List<double> datasY = ret.Item2["OUTPUT_PointY"].HTupleToDouble();
|
List<double> datasZ = ret.Item2["OUTPUT_PointZ"].HTupleToDouble();
|
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{results[0].PID}获取数据OUTPUT_PointX {string.Join(",", datasX.Select(u => u.ToString("f4")))}");
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{results[0].PID}获取数据OUTPUT_PointY {string.Join(",", datasY.Select(u => u.ToString("f4")))}");
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{results[0].PID}获取数据OUTPUT_PointZ {string.Join(",", datasZ.Select(u => u.ToString("f4")))}");
|
|
|
if (datasZ.Count == CheckPointList.Count)
|
{
|
string Postion = "P" + opConfig.TriggerStr.Split('#')[0];
|
string csvhead = "Time,Pid,Postion";
|
string csvdata = $"{DateTime.Now.ToString("yyyyMMddHHmmss")}T,{results[0].PID},{Postion}";
|
|
for (int i = 0; i < CheckPointList.Count; i++)
|
{
|
CheckPointList[i].ActualZ = datasZ[i] + CheckPointList[i].compensateZ;
|
|
csvhead += $",{CheckPointList[i].Name}_X";
|
csvhead += $",{CheckPointList[i].Name}_Y";
|
csvhead += $",{CheckPointList[i].Name}_Z";
|
|
csvdata += $",{CheckPointList[i].X.ToString("F4")}";
|
csvdata += $",{CheckPointList[i].Y.ToString("F4")}";
|
csvdata += $",{CheckPointList[i].ActualZ.ToString("F4")}";
|
}
|
|
foreach (var item in results[0].Specs.AsParallel())
|
{
|
var temcal = ConfigAOI1.MeasureItemBinds.FirstOrDefault(u => u.SpecCode == item.Code);
|
|
if (temcal == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测项 {item.Code}未能获取计算公式");
|
}
|
else
|
{
|
List<double> pointdata = new List<double>();
|
foreach (var item1 in temcal.MeasurePointNameCollection)
|
{
|
var point = CheckPointList.FirstOrDefault(u => u.Name == item1.MeasurePointName);
|
if (point == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"未能找到检测项{item.Code}的点数据{item1.MeasurePointName}");
|
}
|
else
|
{
|
if (item1.ContourEdge == ContourEdge.X)
|
{
|
pointdata.Add(point.X);
|
}
|
else if (item1.ContourEdge == ContourEdge.Y)
|
{
|
pointdata.Add(point.Y);
|
}
|
else if (item1.ContourEdge == ContourEdge.Z)
|
{
|
pointdata.Add(point.ActualZ);
|
}
|
}
|
|
}
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{results[0].PID} {item.Code}输入计算公式数据 {string.Join(",", pointdata.Select(u => u.ToString("f4")))}");
|
var toolcal = GetHalconTool(null, "", temcal.AlgorithemPath);
|
var retcal = toolcal.RunProcedure(new Dictionary<string, HalconDotNet.HTuple>() { { "INPUT_Points", pointdata.ToArray() } }, null, new List<string>() { "OUTPUT_Results" }, null);
|
|
if (retcal != null && !ret.Item1)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"未能找到检测项{item.Code}的计算公式算法运行异常{retcal?.Item4}");
|
}
|
else
|
{
|
item.ActualValue = retcal.Item2["OUTPUT_Results"].HTupleToDouble()[0];
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{results[0].PID}获取计算公式数据{item.Code} {item.GetMeasureValueStr()}");
|
}
|
}
|
}
|
|
|
CSVRecordAsync($"ContourPointRecord_{Postion}.csv", csvdata, csvhead);
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"脚本{opConfig.AlgorithemPath}输出数据长度异常");
|
throw new Exception();
|
}
|
}
|
|
}
|
}
|
catch (Exception re)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"{re.ToString()}");
|
}
|
|
return msg;
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
}
|