using Bro.Common.Base;
|
using Bro.Common.Helper;
|
using Bro.Common.Interface;
|
using Bro.Common.Model;
|
using Bro.Device.InsCamera;
|
using Bro.M135.Common;
|
using Bro.M135.DBManager;
|
using Bro.Process;
|
using Bro.Process.DataBase.Models;
|
using Bro.UI.Model.Winform;
|
using HalconDotNet;
|
using Newtonsoft.Json;
|
using Newtonsoft.Json.Linq;
|
using NPOI.SS.Formula.Functions;
|
using Org.BouncyCastle.Asn1.X509;
|
using Org.BouncyCastle.Ocsp;
|
using ScottPlot.Drawing.Colormaps;
|
using Sunny.UI;
|
using Sunny.UI.Win32;
|
using System.Collections.Concurrent;
|
using System.Collections.Generic;
|
using System.Drawing.Imaging;
|
using System.IO;
|
using System.Linq;
|
using Windows.ApplicationModel.Appointments;
|
using Windows.Networking;
|
using static Org.BouncyCastle.Math.EC.ECCurve;
|
|
namespace Bro.M141.Process
|
{
|
public partial class M141Process : ProcessControl
|
{
|
#region constructor
|
public M141Process() { }
|
|
public M141Process(string productCode) : base(productCode) { }
|
#endregion
|
|
public event Action<string, P_PRODUCT_DETAIL, string> OnSinglePostionDetectResultUpdate;
|
protected M141Config M141Config => Config as M141Config;
|
|
public static object _productListLock = new object();
|
public List<ProductModel> ProductList = new List<ProductModel>();
|
MachineLearningBase ML = null;
|
TcpListenerWrap TcpListener = null;
|
Spec _errorSpec = null;
|
public List<ProductModel> ProductSpecResultList { get; set; } = new List<ProductModel>();
|
TcpListenerWrap _realTimeServer = null;
|
|
volatile int _productIndex = 0;
|
|
int _backgroundImageWidth = 2448;
|
public event Action<string, string, List<IShapeElement>> OnPositionResultUpdated;
|
public event Action<ProductModel> OnNewProductEnqueued;
|
public event Action<ProductModel> OnProductDequeued;
|
public event Action<List<int>> RefreshUIplc;
|
public event Action<string> RefreshState;
|
|
List<ZipImage> ZipImages = new List<ZipImage>();
|
List<OKNGImage> OKNGImages = new List<OKNGImage>();
|
public override void InitialProcessMethods()
|
{
|
base.InitialProcessMethods();
|
OldDataClear.Instance.RunClearOldData(M141Config.DBDataTimeLimit);
|
InitialInspectionConfig();
|
InitialSummaryData();
|
}
|
|
public override void ProcessRunStateChanged()
|
{
|
base.ProcessRunStateChanged();
|
if (CurrentState == EnumHelper.RunState.Running)
|
{
|
OldDataClear.Instance.SetAllowFlag(false, M141Config.DBDataTimeLimit);
|
}
|
else
|
{
|
OldDataClear.Instance.SetAllowFlag(true, M141Config.DBDataTimeLimit);
|
}
|
}
|
|
public PLCBase Plc1;
|
Thread ThHeartPlc;
|
public override void Open()
|
{
|
base.Open();
|
|
ML = DeviceCollection.FirstOrDefault(u => u is MachineLearningBase) as MachineLearningBase;
|
if (ML == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"未设置ML实例");
|
}
|
Plc1 = DeviceCollection.FirstOrDefault(u => u is PLCBase) as PLCBase;
|
|
if (Plc1 == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未设置plc");
|
}
|
_errorSpec = M141Config.SpecCollection.FirstOrDefault(u => u.Code == M141Config.CheckErrorSpecCode) as Spec;
|
|
InitialProductList();
|
|
NetWarmUp();
|
|
_positionCheckTimeDict.Clear();
|
_positionSpecHeads.Clear();
|
|
|
if (ThHeartPlc == null)
|
{
|
ThHeartPlc = new Thread(Heartplc);
|
ThHeartPlc.IsBackground = true;
|
ThHeartPlc.Start();
|
}
|
|
InitialContinuousNGAlarm();
|
|
|
}
|
|
|
public void Heartplc()
|
{
|
int state = 0;
|
int state2 = 0;
|
while (true)
|
{
|
|
try
|
{
|
Plc1.WriteSingleAddress(3009, 2, out _);
|
}
|
catch
|
{
|
|
}
|
Thread.Sleep(1000);
|
try
|
{
|
var tem = Plc1.Read(3030, 17, out _);
|
if (tem != null && RefreshUIplc != null)
|
{
|
RefreshUIplc.Invoke(tem);
|
}
|
}
|
catch
|
{
|
|
}
|
try
|
{
|
var tem = Plc1.Read(3010, 8, out _);
|
if (tem != null && RefreshUIplc != null)
|
{
|
RefreshUIplc.Invoke(tem);
|
}
|
}
|
catch
|
{
|
|
}
|
|
try
|
{
|
var tem = Plc1.Read(3027, 1, out _)[0];
|
var tem2 = Plc1.Read(3028, 1, out _)[0];
|
|
|
if (state != tem || state2 != tem2)
|
{
|
state = tem;
|
state2 = tem2;
|
|
if (RefreshState != null)
|
{
|
if (state == 1)
|
{
|
RefreshState.Invoke("调试模式");
|
}
|
else if (state2 == 1)
|
{
|
RefreshState.Invoke("离线模式");
|
}
|
else
|
{
|
RefreshState.Invoke("正常模式");
|
}
|
}
|
}
|
}
|
catch
|
{
|
|
}
|
}
|
}
|
|
|
|
|
|
|
public void PlcWrite(int add, int va)
|
{
|
try
|
{
|
Plc1.WriteSingleAddress(add, va, out _);
|
var tem = Plc1.Read(3030, 16, out _);
|
if (tem != null && RefreshUIplc != null)
|
{
|
RefreshUIplc.Invoke(tem);
|
}
|
}
|
catch
|
{
|
|
}
|
}
|
|
|
/// <summary>
|
/// 网络预热
|
/// </summary>
|
/// <exception cref="NotImplementedException"></exception>
|
private void NetWarmUp()
|
{
|
|
string warmUpImageFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WarmUp");
|
if (!Directory.Exists(warmUpImageFolder))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"程序根目录下没有\"WarmUp\"预热图片文件夹");
|
return;
|
}
|
|
var ml = DeviceCollection.FirstOrDefault(u => u is MachineLearningBase && u.CurrentState == EnumHelper.DeviceState.DSOpen) as MachineLearningBase;
|
if (ml == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"预热时未能获取开启的深度学习驱动");
|
return;
|
}
|
var netNames = ml.IConfig.NetCollections.Where(u => u.IsEnabled).Select(u => u.Name).ToList();
|
var imageFiles = new DirectoryInfo(warmUpImageFolder).GetFiles().Select(u => u.FullName).ToList();
|
|
Parallel.ForEach(netNames, n =>
|
{
|
Parallel.ForEach(imageFiles, i =>
|
{
|
HImage hImage = new HImage();
|
hImage.ReadImage(i);
|
|
ml.RunNetEvaluate(n, hImage);
|
|
hImage.Dispose();
|
hImage = null;
|
});
|
});
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, "深度学习驱动预热完成");
|
|
|
if (M141Config.WarmUp && M141Config.WarmUpList.Count > 0)
|
{
|
M141Config.WarmUpList.AsParallel().ForAll(x =>
|
{
|
try
|
{
|
HImage im = new HImage(x.PicFilePath);
|
var tool = GetHalconTool(null, "", x.HalconFilePath);
|
if (tool != null)
|
{
|
//int num = 0;
|
//for (int i = 0; i < 10; i++)
|
//{
|
try
|
{
|
var res = tool.RunProcedure(null, new Dictionary<string, HalconDotNet.HObject>() { { "INPUT_Image", im } }, new List<string>() { "OUTPUT_Results_1", "OUTPUT_Results_2" }, null);
|
|
//if (res != null)
|
//{
|
// if (res.Item1&& res.Item2[$"OUTPUT_Results_{i}"].HTupleToDouble()[0]!=-1234)
|
// {
|
// num++;
|
// if (num >= 2)
|
// {
|
// LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"算法{x.HalconFilePath}预热完成{i}");
|
// break;
|
// }
|
// }
|
//}
|
}
|
catch
|
{
|
|
}
|
//if (i==9)
|
//{
|
// LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"算法{x.HalconFilePath}预热失败{num}");
|
//}
|
//}
|
}
|
im.Dispose();
|
|
}
|
catch
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"算法{x.HalconFilePath}预热失败");
|
}
|
});
|
}
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, "算法预热完成");
|
}
|
|
|
|
static object _positionCheckTimeLock = new object();
|
Dictionary<string, List<int>> _positionCheckTimeDict = new Dictionary<string, List<int>>();
|
Dictionary<string, List<string>> _positionSpecHeads = new Dictionary<string, List<string>>();
|
public ResponseMessage RunImageCheck(IOperationConfig config)
|
{
|
ResponseMessage msg = new ResponseMessage();
|
msg.Result = 1;
|
List<MeasureBind> measureBinds = new List<MeasureBind>();
|
string inputSequence = "";
|
var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
try
|
{
|
RunImageCheckPreTreat(config, out measureBinds, out inputSequence);
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测预处理异常,{ex.GetExceptionMessage()}");
|
msg.Result = -1;
|
msg.Message = ex.Message;
|
return msg;
|
}
|
|
List<string> cameraIds = measureBinds.Select(u => u.CameraId).ToList();
|
try
|
{
|
ConcurrentDictionary<MeasureBind, IImageSet> imgSetDicts = new ConcurrentDictionary<MeasureBind, IImageSet>();
|
|
measureBinds.AsParallel().ForAll(b =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == b.CameraId) as CameraBase;
|
if (camera == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测配置{b.GetDisplayText()}未能获取相机设备");
|
imgSetDicts[b] = null;
|
return;
|
}
|
imgSetDicts[b] = null;
|
//if (config.TriggerStr.Split(',')[0].Contains("2"))
|
//{
|
//camera.ClearImageBufferQueue();
|
try
|
{
|
imgSetDicts[b] = CollectHImage(camera, b.SnapshotOpConfig);
|
camera.ClearImageBufferQueue();
|
}
|
catch (Exception ea)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息异常 {ea.ToString()}");
|
}
|
finally
|
{
|
//try
|
//{
|
// if (imgSetDicts[b] == null || imgSetDicts[b].HImage == null)
|
// {
|
// LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息为null ");
|
// //if (camera is InsCameraDriver insCamera)
|
// //{
|
// // insCamera.Restart();
|
// //}
|
// }
|
//}
|
//catch (Exception ec)
|
//{
|
// LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, "ins相机重连异常" + ec.ToString());
|
//}
|
}
|
|
|
var pList = b.ProductIndices.Select(pi =>
|
{
|
string pid = $"{inputSequence}_{pi}";
|
return FindProductBySequence(pid, true);
|
}).ToList();
|
|
RunImageCheckAsync(pList, config.TriggerStr, config.TriggerSource, imgSetDicts[b], b);
|
|
});
|
|
|
//if (imgSetDicts.Values.Any(u => u == null || u.HImage == null))
|
//{
|
// //msg.Result = -1;
|
// //msg.Message = $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息失败";
|
// //return msg;
|
// throw new ProcessException($"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息失败");
|
//}
|
|
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测处理异常,{ex.GetExceptionMessage()}");
|
msg.Result = -1;
|
msg.Message = ex.Message;
|
|
return msg;
|
}
|
|
|
//if (triggerDatas[0].Contains("1"))
|
//{
|
// msg.Result = -1;
|
// return msg;
|
//}
|
|
CheckPositionDoneAsync(measureBinds[0].WorkPosition, inputSequence, config, cameraIds);
|
return msg;
|
}
|
|
public ResponseMessage RunImageCheck1(IOperationConfig config)
|
{
|
ResponseMessage msg = new ResponseMessage();
|
msg.Result = 1;
|
List<MeasureBind> measureBinds = new List<MeasureBind>();
|
string inputSequence = "";
|
|
try
|
{
|
RunImageCheckPreTreat1(config, out measureBinds, out inputSequence);
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测预处理异常,{ex.GetExceptionMessage()}");
|
msg.Result = -1;
|
msg.Message = ex.Message;
|
return msg;
|
}
|
|
List<string> cameraIds = measureBinds.Select(u => u.CameraId).ToList();
|
try
|
{
|
ConcurrentDictionary<MeasureBind, IImageSet> imgSetDicts = new ConcurrentDictionary<MeasureBind, IImageSet>();
|
|
measureBinds.AsParallel().ForAll(b =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == b.CameraId) as CameraBase;
|
if (camera == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测配置{b.GetDisplayText()}未能获取相机设备");
|
imgSetDicts[b] = null;
|
return;
|
}
|
imgSetDicts[b] = null;
|
|
try
|
{
|
imgSetDicts[b] = CollectHImage(camera, b.SnapshotOpConfig);
|
camera.ClearImageBufferQueue();
|
}
|
catch (Exception ea)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息失败 {ea.ToString()}");
|
}
|
|
|
var pList = b.ProductIndices.Select(pi =>
|
{
|
string pid = $"{inputSequence}_{pi}";
|
return FindProductBySequence(pid, true);
|
}).ToList();
|
|
RunImageCheckAsync(pList, config.TriggerStr, config.TriggerSource, imgSetDicts[b], b);
|
|
});
|
//DateTime.Now.DayOfWeek
|
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测处理异常,{ex.GetExceptionMessage()}");
|
msg.Result = -1;
|
msg.Message = ex.Message;
|
|
return msg;
|
}
|
|
|
CheckPositionDoneAsync1(measureBinds[0].WorkPosition, inputSequence, config, cameraIds);
|
return msg;
|
}
|
|
|
|
public void RunImageCheckPreTreat1(IOperationConfig config, out List<MeasureBind> measureBinds, out string inputSequence)
|
{
|
Task.Run(() =>
|
{
|
SetProcessRunState(EnumHelper.RunState.Running);
|
});
|
|
measureBinds = new List<MeasureBind>();
|
inputSequence = "";
|
|
var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
if (triggerDatas.Length < 2)
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}解析失败,数据长度小于2");
|
}
|
|
string positionValue = triggerDatas[0];
|
int checkIndex = -1;
|
if (!int.TryParse(triggerDatas[1], out checkIndex))
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}解析失败,未能获取检测序号");
|
}
|
|
|
var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == positionValue);
|
if (positionSet == null)
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}未能获取{positionValue}对应的可用工位信息");
|
}
|
|
measureBinds = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionSet.PositionName && u.CheckIndex == checkIndex).ToList();
|
if (measureBinds.Count == 0)
|
{
|
throw new ProcessException($"未能获取工位{positionSet.PositionName}的第{checkIndex}检测配置信息");
|
}
|
|
|
|
measureBinds.Select(u => u.CameraId).ToList().ForEach(c =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
if (camera != null)
|
{
|
camera.ClearImageBufferQueue();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"相机{camera.Name}检测前清理缓存完成");
|
}
|
});
|
|
if (positionSet.IsSendClearSingal)
|
{
|
var sourceData = config.TriggerSource.Split(':');
|
string ip = "";
|
int port = 0;
|
if (sourceData.Length >= 2)
|
{
|
ip = sourceData[0];
|
port = int.Parse(sourceData[1]);
|
}
|
|
TcpListener?.WriteAndRead(positionSet.ClearStr, out _, out _, false, ip, port);
|
}
|
|
inputSequence = triggerDatas[triggerDatas.Length - 1];
|
|
string tempPID = inputSequence;
|
string pidstr = DateTime.Now.ToString("yyyyMMddHHmmssfff");
|
measureBinds.Where(b => b.IsFirstPosition).ToList().ForEach(b =>
|
{
|
b.ProductIndices.ForEach(i =>
|
{
|
ProductModel p = new ProductModel();
|
p.SEQUENCE = $"{tempPID}_{i}";
|
p.PID = $"{pidstr}T_{i}";
|
p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Select(u => u.PositionName).ToList());
|
NewProductIntoList(p, true);
|
});
|
});
|
|
|
int de = 2;
|
//if (triggerDatas[0].Contains("11111"))
|
//{
|
// de = 2;
|
//}
|
//else
|
//{
|
|
// de = 2;
|
//}
|
|
|
measureBinds.Where(b => (b.CheckIndex == de || b.CheckIndex == 1) && b.ImageIndex == 0).AsParallel().ForAll(b =>
|
{
|
List<int> temint = new List<int>();
|
if (triggerDatas[0].Contains("11111"))
|
{
|
if (triggerDatas[1] == "1")
|
{
|
temint = new List<int>() { 1 };
|
}
|
else
|
{
|
temint = new List<int>() { 2 };
|
}
|
}
|
else
|
{
|
temint = new List<int>() { 1, 2 };
|
}
|
|
|
//new List<int>() { 1, 2 }.ForEach(i =>
|
temint.ForEach(i =>
|
{
|
string sequence = $"{tempPID}_{i}";
|
var p = FindProductBySequence(sequence, b.IsEnabelQueryFromQueue);
|
|
//初始化产品的检测次数
|
var checkIndexList = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition && u.ProductIndices.Contains(i)).Select(u => u.CheckIndex).OrderBy(u => u).ToList();
|
p.InitialPositionCheckList(b.WorkPosition, checkIndexList);
|
|
//p.ClearPositionResult(M141Config.StationCode, b.WorkPosition);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{p.PID}_{p.SEQUENCE}已清理{b.WorkPosition}检测数据。当前已完成工位{string.Join(",", p.Details.Select(u => u.PositionName))}");
|
});
|
|
//初始化工位的检测次数
|
var positionCheckTimes = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition).Select(u => u.CheckIndex).ToList();
|
lock (_positionCheckTimeLock)
|
{
|
_positionCheckTimeDict[b.WorkPosition] = positionCheckTimes;
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}初始化检测次数:{string.Join(",", positionCheckTimes)}");
|
}
|
});
|
|
measureBinds.AsParallel().ForAll(b =>
|
{
|
lock (_positionCheckTimeLock)
|
{
|
_positionCheckTimeDict[b.WorkPosition].RemoveAll(u => u == b.CheckIndex);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}开始第{b.CheckIndex}次检测,待检测序号:{string.Join(",", _positionCheckTimeDict[b.WorkPosition])}");
|
}
|
});
|
}
|
|
public void RunImageCheckPreTreat(IOperationConfig config, out List<MeasureBind> measureBinds, out string inputSequence)
|
{
|
Task.Run(() =>
|
{
|
SetProcessRunState(EnumHelper.RunState.Running);
|
});
|
|
measureBinds = new List<MeasureBind>();
|
inputSequence = "";
|
|
var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
if (triggerDatas.Length < 2)
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}解析失败,数据长度小于2");
|
}
|
|
string positionValue = triggerDatas[0];
|
int checkIndex = -1;
|
if (!int.TryParse(triggerDatas[1].Replace("Scan", ""), out checkIndex))
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}解析失败,未能获取检测序号");
|
}
|
|
|
var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == positionValue);
|
if (positionSet == null)
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}未能获取{positionValue}对应的可用工位信息");
|
}
|
|
measureBinds = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionSet.PositionName && u.CheckIndex == checkIndex).ToList();
|
if (measureBinds.Count == 0)
|
{
|
throw new ProcessException($"未能获取工位{positionSet.PositionName}的第{checkIndex}检测配置信息");
|
}
|
|
measureBinds.Select(u => u.CameraId).ToList().ForEach(c =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
if (camera != null)
|
{
|
camera.ClearImageBufferQueue();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"相机{camera.Name}检测前清理缓存完成");
|
}
|
});
|
|
if (positionSet.IsSendClearSingal)
|
{
|
var sourceData = config.TriggerSource.Split(':');
|
string ip = "";
|
int port = 0;
|
if (sourceData.Length >= 2)
|
{
|
ip = sourceData[0];
|
port = int.Parse(sourceData[1]);
|
}
|
|
TcpListener?.WriteAndRead(positionSet.ClearStr, out _, out _, false, ip, port);
|
}
|
|
inputSequence = triggerDatas[triggerDatas.Length - 1];
|
|
string tempPID = inputSequence;
|
|
string pidstr = DateTime.Now.ToString("yyyyMMddHHmmssfff");
|
measureBinds.Where(b => b.IsFirstPosition).ToList().ForEach(b =>
|
{
|
b.ProductIndices.ForEach(i =>
|
{
|
ProductModel p = new ProductModel();
|
p.SEQUENCE = $"{tempPID}_{i}";
|
p.PID = $"{pidstr}T_{i}";
|
p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Select(u => u.PositionName).ToList());
|
NewProductIntoList(p, true);
|
});
|
});
|
|
|
int de = 0;
|
if (triggerDatas[0].Contains("1") || triggerDatas[0].Contains("0"))
|
{
|
de = 2;
|
}
|
else
|
{
|
de = 1;
|
}
|
|
|
measureBinds.Where(b => (b.CheckIndex == de || b.CheckIndex == 1) && b.ImageIndex == 0).AsParallel().ForAll(b =>
|
{
|
List<int> temint = new List<int>();
|
if (triggerDatas[0].Contains("1") || triggerDatas[0].Contains("0"))
|
{
|
if (triggerDatas[1].Contains("1"))
|
{
|
temint = new List<int>() { 1 };
|
}
|
else
|
{
|
temint = new List<int>() { 2 };
|
}
|
}
|
else
|
{
|
temint = new List<int>() { 1, 2 };
|
}
|
|
|
//new List<int>() { 1, 2 }.ForEach(i =>
|
temint.ForEach(i =>
|
{
|
string sequence = $"{tempPID}_{i}";
|
var p = FindProductBySequence(sequence, b.IsEnabelQueryFromQueue);
|
|
//初始化产品的检测次数
|
var checkIndexList = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition && u.ProductIndices.Contains(i)).Select(u => u.CheckIndex).OrderBy(u => u).ToList();
|
p.InitialPositionCheckList(b.WorkPosition, checkIndexList);
|
|
//p.ClearPositionResult(M141Config.StationCode, b.WorkPosition);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{p.PID}_{p.SEQUENCE}已清理{b.WorkPosition}检测数据。当前已完成工位{string.Join(",", p.Details.Select(u => u.PositionName))}");
|
});
|
|
//初始化工位的检测次数
|
var positionCheckTimes = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition).Select(u => u.CheckIndex).ToList();
|
lock (_positionCheckTimeLock)
|
{
|
_positionCheckTimeDict[b.WorkPosition] = positionCheckTimes;
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}初始化检测次数:{string.Join(",", positionCheckTimes)}");
|
}
|
});
|
|
measureBinds.AsParallel().ForAll(b =>
|
{
|
lock (_positionCheckTimeLock)
|
{
|
_positionCheckTimeDict[b.WorkPosition].RemoveAll(u => u == b.CheckIndex);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}开始第{b.CheckIndex}次检测,待检测序号:{string.Join(",", _positionCheckTimeDict[b.WorkPosition])}");
|
}
|
});
|
}
|
|
public async Task<List<ProductModel>> CheckPositionDoneAsync(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds)
|
{
|
string triggerSource = config.TriggerSource;
|
return await _taskFactory.StartNew(() =>
|
{
|
try
|
{
|
|
if (positionName.Contains("1") || positionName.Contains("0"))
|
{
|
|
string index = config.TriggerStr.Split(',')[1];
|
var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName);
|
|
var checkRemains = _positionCheckTimeDict[positionName];
|
//if (checkRemains.Count != 0)
|
//{
|
// LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}");
|
// return null;
|
//}
|
|
string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue;
|
|
|
//if (checkRemains.Count != 0)
|
//{
|
replyData += "," + index;
|
//}
|
//else
|
//{
|
// replyData += ",2";
|
//}
|
|
var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList();
|
if (index.Contains("1"))
|
{
|
pIndices = new List<int> { 1 };
|
}
|
else
|
{
|
pIndices = new List<int> { 2 };
|
}
|
//var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0]));
|
//if (measureNum > 1)
|
//{
|
// replyData += ",C";
|
//}
|
|
var pList = pIndices.Select(u =>
|
{
|
string sequence = $"{inputSequence}_{u}";
|
return FindProductBySequence(sequence, true);
|
}).ToList();
|
|
if (pList.Any(u => u == null))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空");
|
pList.ForEach(u =>
|
{
|
replyData += ",NG";
|
});
|
}
|
else
|
{
|
int waitInterval = 300;
|
int repeatTime = M141Config.DetectTimeout / waitInterval;
|
do
|
{
|
if (!pList.All(p =>
|
{
|
p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
return detail?.IsDone ?? false;
|
}))
|
{
|
Thread.Sleep(waitInterval);
|
repeatTime--;
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"成功完成工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测");
|
break;
|
}
|
|
if (repeatTime < 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测获取结果超时");
|
break;
|
}
|
} while (true);
|
}
|
|
pList.ForEach(p =>
|
{
|
var isOK = p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
replyData += $",{(isOK ? "OK" : "NG")}";
|
List<string> specHeads = new List<string>();
|
string head = p.GetCSVHead(ref specHeads, positionName);
|
if (!_positionSpecHeads.ContainsKey(positionName))
|
{
|
_positionSpecHeads[positionName] = specHeads;
|
}
|
|
string data = p.GetCSVData(_positionSpecHeads[positionName], positionName);
|
CSVRecordAsync($"{positionName}_Record_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, head);
|
|
UpdatePositionResultToDB(detail);
|
var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]);
|
if (IsInspectionDoing)
|
{
|
OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]);
|
}
|
|
if (positionSet.IsLastPosition)
|
{
|
UpdateProductResultAsync(p);
|
UpdateOverAllProductResultToUI(p, isOK);
|
OnNewProductEnqueued?.Invoke(p);
|
OnProductDequeued?.Invoke(p);
|
}
|
|
SetSpecResult(p);
|
});
|
|
if (positionSet.IsLastPosition)
|
{
|
if (_ct != null)
|
{
|
UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0));
|
}
|
_ct = DateTime.Now;
|
}
|
//replyData += ",No Read,No Read";
|
if (positionName.Contains("0"))
|
{
|
var isOK = pList[0].GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
|
if (index.Contains("1"))
|
{
|
replyData = "0#,Scan1,Scan" + (isOK ? "OK" : "NG") + "1";
|
}
|
else
|
{
|
replyData = "0#,Scan2,Scan" + (isOK ? "OK" : "NG") + "2";
|
//replyData = "0#,Scan2,ScanOK2";
|
}
|
}
|
|
ReplyTcpData(positionName, triggerSource, replyData);
|
|
cameraIds.ForEach(c =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
if (camera != null)
|
{
|
camera.ClearImageBufferQueue();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"相机{camera.Name}清理缓存");
|
}
|
});
|
|
return pList;
|
}
|
else
|
{
|
var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName);
|
|
var checkRemains = _positionCheckTimeDict[positionName];
|
if (checkRemains.Count != 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}");
|
return null;
|
}
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测已完成,等待输出结果");
|
|
string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue;
|
|
var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList();
|
|
var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0]));
|
if (measureNum > 1)
|
{
|
replyData += ",C";
|
}
|
|
var pList = pIndices.Select(u =>
|
{
|
string sequence = $"{inputSequence}_{u}";
|
return FindProductBySequence(sequence, true);
|
}).ToList();
|
|
if (pList.Any(u => u == null))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空");
|
pList.ForEach(u =>
|
{
|
replyData += ",NG";
|
});
|
}
|
else
|
{
|
int waitInterval = 300;
|
int repeatTime = M141Config.DetectTimeout / waitInterval;
|
do
|
{
|
if (!pList.All(p =>
|
{
|
p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
return detail?.IsDone ?? false;
|
}))
|
{
|
Thread.Sleep(waitInterval);
|
repeatTime--;
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"成功完成工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测");
|
break;
|
}
|
|
if (repeatTime < 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测获取结果超时");
|
break;
|
}
|
} while (true);
|
}
|
|
pList.ForEach(p =>
|
{
|
var isOK = p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
replyData += $",{(isOK ? "OK" : "NG")}";
|
|
List<string> specHeads = new List<string>();
|
string head = p.GetCSVHead(ref specHeads, positionName);
|
if (!_positionSpecHeads.ContainsKey(positionName))
|
{
|
_positionSpecHeads[positionName] = specHeads;
|
}
|
|
string data = p.GetCSVData(_positionSpecHeads[positionName], positionName);
|
|
CSVRecordAsync($"{positionName}_Record_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, head);
|
|
UpdatePositionResultToDB(detail);
|
var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]);
|
if (IsInspectionDoing)
|
{
|
OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]);
|
}
|
|
if (positionSet.IsLastPosition)
|
{
|
UpdateProductResultAsync(p);
|
UpdateOverAllProductResultToUI(p, isOK);
|
OnNewProductEnqueued?.Invoke(p);
|
OnProductDequeued?.Invoke(p);
|
}
|
|
SetSpecResult(p);
|
});
|
|
if (positionSet.IsLastPosition)
|
{
|
if (_ct != null)
|
{
|
UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0));
|
}
|
_ct = DateTime.Now;
|
}
|
replyData += "," + pList[0]?.SN + "," + pList[1]?.SN;
|
|
|
ReplyTcpData(positionName, triggerSource, replyData);
|
|
cameraIds.ForEach(c =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
if (camera != null)
|
{
|
camera.ClearImageBufferQueue();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"相机{camera.Name}清理缓存");
|
}
|
});
|
|
return pList;
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, ex.ToString());
|
return null;
|
}
|
|
});
|
}
|
|
public async Task<List<ProductModel>> CheckPositionDoneAsync1(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds)
|
{
|
string triggerSource = config.TriggerSource;
|
return await _taskFactory.StartNew(() =>
|
{
|
|
var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName);
|
|
var checkRemains = _positionCheckTimeDict[positionName];
|
if (checkRemains.Count != 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}");
|
return null;
|
}
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测已完成,等待输出结果");
|
|
string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue;
|
|
var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList();
|
|
var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0]));
|
if (measureNum > 1)
|
{
|
replyData += ",C";
|
}
|
|
var pList = pIndices.Select(u =>
|
{
|
string sequence = $"{inputSequence}_{u}";
|
return FindProductBySequence(sequence, true);
|
}).ToList();
|
|
if (pList.Any(u => u == null))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空");
|
pList.ForEach(u =>
|
{
|
replyData += ",NG";
|
});
|
}
|
else
|
{
|
int waitInterval = 300;
|
int repeatTime = M141Config.DetectTimeout / waitInterval;
|
do
|
{
|
if (!pList.All(p =>
|
{
|
p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
return detail?.IsDone ?? false;
|
}))
|
{
|
Thread.Sleep(waitInterval);
|
repeatTime--;
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"成功完成工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测");
|
break;
|
}
|
|
if (repeatTime < 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测获取结果超时");
|
break;
|
}
|
} while (true);
|
}
|
|
pList.ForEach(p =>
|
{
|
var isOK = p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
replyData += $",{(isOK ? "OK" : "NG")}";
|
|
List<string> specHeads = new List<string>();
|
string head = p.GetCSVHead(ref specHeads, positionName);
|
if (!_positionSpecHeads.ContainsKey(positionName))
|
{
|
_positionSpecHeads[positionName] = specHeads;
|
}
|
|
string data = p.GetCSVData(_positionSpecHeads[positionName], positionName);
|
|
CSVRecordAsync($"{positionName}_Record_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, head);
|
|
UpdatePositionResultToDB(detail);
|
var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]);
|
|
|
if (IsInspectionDoing)
|
{
|
OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]);
|
}
|
|
|
if (positionSet.IsLastPosition)
|
{
|
UpdateProductResultAsync(p);
|
UpdateOverAllProductResultToUI(p, isOK);
|
OnNewProductEnqueued?.Invoke(p);
|
OnProductDequeued?.Invoke(p);
|
}
|
|
SetSpecResult(p);
|
});
|
|
if (positionSet.IsLastPosition)
|
{
|
if (_ct != null)
|
{
|
UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0));
|
}
|
_ct = DateTime.Now;
|
}
|
replyData += "," + pList[0].SN + "," + pList[1].SN;
|
if (!positionName.Contains("0"))
|
{
|
ReplyTcpData(positionName, triggerSource, replyData);
|
}
|
else
|
{
|
//replyData += "," + pList[0].SN=="NOREAD" + "," + pList[1]?.SN;
|
|
|
//replyData = "0#,2,"+ ((pList[0].SN == "NOREAD" || pList[1]?.SN=="NOREAD")? "NG":"OK") +","+ pList[0].SN+ ","+ pList[1].SN;
|
replyData = "0#,2,OK," + pList[0].SN + "," + pList[1].SN;
|
|
ReplyTcpData(positionName, triggerSource, replyData);
|
}
|
|
|
cameraIds.ForEach(c =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
if (camera != null)
|
{
|
camera.ClearImageBufferQueue();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"相机{camera.Name}清理缓存");
|
}
|
});
|
|
return pList;
|
|
});
|
}
|
|
|
public async Task<List<ProductModel>> CheckPositionDoneAsyncforsb(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds)
|
{
|
string triggerSource = config.TriggerSource;
|
return await _taskFactory.StartNew(() =>
|
{
|
|
var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName);
|
|
var checkRemains = _positionCheckTimeDict[positionName];
|
if (checkRemains.Count != 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测未完成,剩余:{string.Join(",", checkRemains)}");
|
return null;
|
}
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{positionName}检测已完成,等待输出结果");
|
|
string replyData = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName).TriggerValue;
|
|
var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList();
|
|
var measureNum = M141Config.MeasureBindCollection.Count(u => u.WorkPosition == positionName && u.ProductIndices.Contains(pIndices[0]));
|
if (measureNum > 1)
|
{
|
replyData += ",C";
|
}
|
|
var pList = pIndices.Select(u =>
|
{
|
string sequence = $"{inputSequence}_{u}";
|
return FindProductBySequence(sequence, true);
|
}).ToList();
|
|
if (pList.Any(u => u == null))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空");
|
pList.ForEach(u =>
|
{
|
replyData += ",NG";
|
});
|
}
|
else
|
{
|
int waitInterval = 300;
|
int repeatTime = M141Config.DetectTimeout / waitInterval;
|
do
|
{
|
if (!pList.All(p =>
|
{
|
p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
return detail?.IsDone ?? false;
|
}))
|
{
|
Thread.Sleep(waitInterval);
|
repeatTime--;
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"成功完成工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测");
|
break;
|
}
|
|
if (repeatTime < 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测获取结果超时");
|
break;
|
}
|
} while (true);
|
}
|
|
pList.ForEach(p =>
|
{
|
var isOK = p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
replyData += $",{(isOK ? "OK" : "NG")}";
|
|
List<string> specHeads = new List<string>();
|
string head = p.GetCSVHead(ref specHeads, positionName);
|
if (!_positionSpecHeads.ContainsKey(positionName))
|
{
|
_positionSpecHeads[positionName] = specHeads;
|
}
|
|
string data = p.GetCSVData(_positionSpecHeads[positionName], positionName);
|
|
CSVRecordAsync($"{positionName}_Record_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, head);
|
|
UpdatePositionResultToDB(detail);
|
var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]);
|
|
var temokimage = OKNGImages.Where(u => u.pid == p.PID).ToList();
|
|
if (isOK)
|
{
|
if (temokimage.Any(u => u.issave))
|
{
|
for (int i = 0; i < temokimage.Count; i++)
|
{
|
string realpath = Path.Combine(temokimage[i].path, $"{temokimage[i].name}.{temokimage[i].post}");
|
temokimage[i].bitmap.Save(realpath, temokimage[i].ImageFormat);
|
}
|
}
|
}
|
else
|
{
|
if (temokimage.Any(u => u.issave))
|
{
|
var temin = temokimage.FirstOrDefault(u => u.result == "NG");
|
if (temin != null)
|
{
|
for (int i = 0; i < temokimage.Count; i++)
|
{
|
string realpath = Path.Combine(temin.path, $"{temokimage[i].name}.{temokimage[i].post}");
|
temokimage[i].bitmap.Save(realpath, temokimage[i].ImageFormat);
|
}
|
}
|
else
|
{
|
for (int i = 0; i < temokimage.Count; i++)
|
{
|
string realpath = Path.Combine(temokimage[i].path, $"{temokimage[i].name}.{temokimage[i].post}");
|
temokimage[i].bitmap.Save(realpath, temokimage[i].ImageFormat);
|
}
|
}
|
}
|
}
|
|
|
|
//string ngImageFile = Path.Combine(folder, $"{id}.{post}");
|
//var bitmap = imgSet.HImage.ConvertHImageToBitmap();
|
//bitmap.Save(ngImageFile, M141Config.ImageFormatNG);
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}NG图片已保存");
|
|
|
|
|
|
if (IsInspectionDoing)
|
{
|
OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]);
|
}
|
|
|
if (positionSet.IsLastPosition)
|
{
|
UpdateProductResultAsync(p);
|
UpdateOverAllProductResultToUI(p, isOK);
|
OnNewProductEnqueued?.Invoke(p);
|
OnProductDequeued?.Invoke(p);
|
}
|
|
SetSpecResult(p);
|
});
|
|
|
OKNGImages.ForEach(x =>
|
{
|
x.bitmap.Dispose();
|
});
|
OKNGImages.Clear();
|
|
|
if (positionSet.IsLastPosition)
|
{
|
if (_ct != null)
|
{
|
UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds / 2.0));
|
}
|
_ct = DateTime.Now;
|
}
|
replyData += "," + pList[0].SN + "," + pList[1].SN;
|
if (!positionName.Contains("0"))
|
{
|
ReplyTcpData(positionName, triggerSource, replyData);
|
}
|
else
|
{
|
//replyData += "," + pList[0].SN=="NOREAD" + "," + pList[1]?.SN;
|
|
|
//replyData = "0#,2,"+ ((pList[0].SN == "NOREAD" || pList[1]?.SN=="NOREAD")? "NG":"OK") +","+ pList[0].SN+ ","+ pList[1].SN;
|
replyData = "0#,2,OK," + pList[0].SN + "," + pList[1].SN;
|
|
ReplyTcpData(positionName, triggerSource, replyData);
|
}
|
|
|
cameraIds.ForEach(c =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
if (camera != null)
|
{
|
camera.ClearImageBufferQueue();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"相机{camera.Name}清理缓存");
|
}
|
});
|
|
return pList;
|
|
});
|
}
|
|
private async void UpdatePositionResultDisplay(P_PRODUCT_DETAIL detail, bool isOK, string positionName, string productSequence)
|
{
|
await Task.Run(() =>
|
{
|
if (detail == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"无法显示检测明细信息");
|
return;
|
}
|
|
List<IShapeElement> eleList = new List<IShapeElement>();
|
|
TextDisplay txt = new TextDisplay();
|
txt.LineLimit = 30;
|
eleList.Add(txt);
|
|
txt.StartX = txt.StartY = 0;
|
|
txt.AddText($"{detail.SN} {(isOK ? "OK" : "NG")}", isOK ? Color.Lime : Color.White, isOK ? Color.Transparent : Color.Red);
|
|
txt.AddText(" ", Color.Transparent, Color.Transparent);
|
|
var ngSpecCode = new List<string>();
|
|
detail.SpecList.ToList().ForEach(s =>
|
{
|
GetIndicatorFromSpec(s, eleList, txt, ngSpecCode);
|
|
});
|
|
detail.ResultList.ToList().SelectMany(u => u.Specs).ToList().ForEach(s =>
|
{
|
GetIndicatorFromSpec(s, eleList, txt, ngSpecCode);
|
});
|
|
var defects = new List<string>(detail.DefectList);
|
defects.AddRange(detail.ResultList.GetDefectDescList());
|
|
defects = defects.Except(ngSpecCode).Distinct().ToList();
|
defects.ForEach(u =>
|
{
|
txt.AddText(u, Color.Red, Color.Transparent);
|
|
var indicator = M141Config.DefectIndicatorCollection.FirstOrDefault(d => d.DefectName == u);
|
if (indicator != null)
|
{
|
var cloneIndicator = indicator.Clone() as DefectRectangleIndicator;
|
eleList.Add(cloneIndicator);
|
}
|
});
|
|
OnPositionResultUpdated?.Invoke(positionName, productSequence, eleList);
|
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{detail.PID} 序号{productSequence} 工位{positionName}显示信息{JsonConvert.SerializeObject(detail)}");
|
});
|
}
|
|
private void GetIndicatorFromSpec(ISpec s, List<IShapeElement> eleList, TextDisplay txt, List<string> ngSpecCode)
|
{
|
txt.AddText($"{s.Code} {s.GetMeasureValueStr()}", s.MeasureResult == true ? Color.Lime : Color.Red, Color.Transparent);
|
|
var indicator = M141Config.DefectIndicatorCollection.FirstOrDefault(u => u.DefectName == s.Code);
|
if (indicator != null)
|
{
|
var cloneIndicator = indicator.Clone() as DefectRectangleIndicator;
|
cloneIndicator.DefectName += $"{s.Code} {s.GetMeasureValueStr()}";
|
cloneIndicator.IsOK = s.MeasureResult == true;
|
|
eleList.Add(cloneIndicator);
|
}
|
|
if (s.MeasureResult != true)
|
{
|
ngSpecCode.Add(s.Code);
|
}
|
}
|
|
private async void UpdateOverAllProductResultToUI(ProductModel product, bool isOK)
|
{
|
await Task.Run(() =>
|
{
|
List<IShapeElement> eleList = new List<IShapeElement>();
|
|
TextDisplay txt = new TextDisplay();
|
txt.LineLimit = 30;
|
eleList.Add(txt);
|
|
txt.StartX = txt.StartY = 0;
|
|
txt.AddText($"{product.SN} {product.Result}", isOK ? Color.Lime : Color.White, isOK ? Color.Transparent : Color.Red);
|
|
txt.AddText(" ", Color.Transparent, Color.Transparent);
|
|
var ngSpecCode = new List<string>();
|
|
product.Details.ForEach(d =>
|
{
|
d.SpecList.ForEach(s =>
|
{
|
GetIndicatorFromSpec(s, eleList, txt, ngSpecCode);
|
});
|
|
d.ResultList.SelectMany(u => u.Specs).ToList().ForEach(s =>
|
{
|
GetIndicatorFromSpec(s, eleList, txt, ngSpecCode);
|
});
|
|
var defects = new List<string>(d.DefectList);
|
defects.AddRange(d.ResultList.GetDefectDescList());
|
|
defects = defects.Except(ngSpecCode).Distinct().ToList();
|
defects.ForEach(u =>
|
{
|
txt.AddText(u, Color.Red, Color.Transparent);
|
|
var indicator = M141Config.DefectIndicatorCollection.FirstOrDefault(d => d.DefectName == u);
|
if (indicator != null)
|
{
|
var cloneIndicator = indicator.Clone() as DefectRectangleIndicator;
|
eleList.Add(cloneIndicator);
|
}
|
});
|
});
|
|
OnPositionResultUpdated?.Invoke("", product.SEQUENCE.Split("_")[product.SEQUENCE.Split("_").Count() - 1], eleList);
|
});
|
}
|
|
public virtual int UploadProductDataToMES(List<ProductModel> pList)
|
{
|
List<int> isUploadOK = new List<int>();
|
pList.ForEach(p =>
|
{
|
var pData = GetProductUploadMESData(p, p.Result);
|
|
ResponseMessage response = UploadDataToMES(new OperationConfigBase() { TriggerStr = pData }, null, null);
|
|
if (response.Result == -1)
|
{
|
//先上传一次,如果失败再试2次
|
for (int i = 0; i < 2; i++)
|
{
|
Thread.Sleep(500);
|
response = UploadDataToMES(new OperationConfigBase() { TriggerStr = pData }, null, null);
|
if (response.Result != -1)
|
{
|
break;
|
}
|
}
|
}
|
|
|
if (p.SN.Replace(" ", "").ToLower().Contains("noread") && response.Result == 1000)
|
{
|
isUploadOK.Add(3);
|
}
|
else
|
{
|
isUploadOK.Add(response.Result);
|
}
|
});
|
if (isUploadOK.All(u => u == 1000))
|
{
|
return 0;
|
}
|
else if (isUploadOK.Contains(1))
|
{
|
return 1;
|
}
|
else if (isUploadOK.Contains(4))
|
{
|
return 4;
|
}
|
else if (isUploadOK.Contains(-1))
|
{
|
return 2;
|
}
|
else if (isUploadOK.Contains(3))
|
{
|
return 3;
|
}
|
return 2;
|
}
|
|
volatile int uploadId = 0;
|
private string GetProductUploadMESData(ProductModel p, string pResult)
|
{
|
JObject jObj = new JObject();
|
Interlocked.Increment(ref uploadId);
|
//jObj.Add($"id", uploadId);
|
//jObj.Add($"Createor", Config.StationCode ?? "2966AOI3");
|
//jObj.Add($"CreateTime", p.CREATE_TIME.Value.ToString("yyyy-MM-dd HH:mm:ss"));
|
//jObj.Add($"Project", M141Config.MESProjectCode);
|
//jObj.Add($"MachineNumber", M141Config.MESMachineNum);
|
//jObj.Add($"DateTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
//jObj.Add($"Cycle", ((p.EndTime ?? DateTime.Now) - p.CREATE_TIME.Value).TotalSeconds.ToString("f2"));
|
//jObj.Add($"SN", p.SN);
|
//jObj.Add($"Result", pResult == "OK" ? "OK" : "NG");
|
|
|
//jObj.Add($"id", uploadId);
|
//jObj.Add($"Createor", Config.StationCode ?? "2966AOI3");
|
jObj.Add($"CreateTime", p.CREATE_TIME.Value.ToString("yyyy-MM-dd HH:mm:ss"));
|
jObj.Add($"SN", p.SN);
|
jObj.Add($"Project", M141Config.MESProjectCode);
|
jObj.Add($"MachineNumber", M141Config.MESMachineNum);
|
jObj.Add($"DateTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
|
List<string> ngitem = new List<string>();
|
foreach (var v in p.Details)
|
{
|
ngitem.AddRange(v.ResultList.GetDefectDescList());
|
ngitem.AddRange(v.DefectList);
|
}
|
ngitem = ngitem.Distinct().ToList();
|
|
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"MES 产品NG项汇总:{string.Join(",", ngitem)}");
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"MES :{JsonConvert.SerializeObject(p)}");
|
|
|
List<string> ngitemD = ngitem.Where(u => u.ToUpper().Contains("FAI")).ToList();
|
|
List<string> ngitemC = ngitem.Where(u => !u.ToUpper().Contains("FAI")).ToList();
|
|
jObj.Add($"Result_Dimension", ngitemD.Count == 0 ? "OK" : "NG");
|
jObj.Add($"Dimension_NGItems", string.Join(",", ngitemD));
|
//jObj.Add("NGItems", string.Join(",", defectList));
|
jObj.Add($"Result_Cosmetic", ngitemC.Count == 0 ? "OK" : "NG");
|
jObj.Add($"Cosmetic_NGItems", string.Join(",", ngitemC));
|
|
jObj.Add($"CycleTime", ((p.EndTime ?? DateTime.Now) - p.CREATE_TIME.Value).TotalSeconds.ToString("f2"));
|
|
var specList = p.Details.SelectMany(u => u.ResultList.SelectMany(r => r.Specs)).ToList();
|
p.Details.SelectMany(u => u.SpecList).ToList().ForEach(s =>
|
{
|
if (!specList.Any(u => u.Code == s.Code))
|
{
|
specList.Add(s);
|
}
|
});
|
|
List<string> temmescode = new List<string>();
|
specList.ForEach(s =>
|
{
|
var mapping = M141Config.MESCodeMappingCollection.FirstOrDefault(u => u.SpcCode == s.Code);
|
if (mapping != null)
|
{
|
if (!temmescode.Contains(mapping.MESCode))
|
{
|
temmescode.Add(mapping.MESCode);
|
jObj.Add(mapping.MESCode, s.GetMeasureValueStr(4));
|
}
|
}
|
else
|
{
|
if (!temmescode.Contains(s.Code))
|
{
|
temmescode.Add(s.Code);
|
jObj.Add(s.Code, s.GetMeasureValueStr(4));
|
}
|
}
|
});
|
|
var defectList = p.Details.SelectMany(u => u.ResultList).ToList().GetDefectDescList();
|
defectList.AddRange(p.Details.SelectMany(u => u.DefectList));
|
|
defectList = defectList.Except(specList.Select(u => u.Code)).Distinct().ToList();
|
//jObj.Add("NGItems", string.Join(",", defectList));
|
|
return JsonConvert.SerializeObject(jObj);
|
}
|
|
protected void ReplyTcpData(string positionName, string triggerSource, string replyData)
|
{
|
if (!string.IsNullOrWhiteSpace(triggerSource))
|
{
|
var sourceData = triggerSource.Split(':');
|
string ip = "";
|
int port = 0;
|
if (sourceData.Length >= 2)
|
{
|
ip = sourceData[0];
|
port = int.Parse(sourceData[1]);
|
}
|
|
string error = "";
|
if (!(TcpListener?.WriteAndRead(replyData, out error, out _, false, ip, port) ?? false))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}检测结果反馈异常,{error}");
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"工位{positionName}检测结果反馈完成,{replyData}");
|
}
|
}
|
}
|
|
public void NewProductIntoList(ProductModel p, bool isSaveDB)
|
{
|
lock (_productListLock)
|
{
|
ProductList.RemoveAll(u => u.PID == p.PID || u.SEQUENCE == p.SEQUENCE);
|
ProductList.Insert(0, p);
|
while (ProductList.Count > 200)
|
{
|
ProductList.RemoveAt(ProductList.Count - 1);
|
}
|
}
|
|
if (isSaveDB)
|
{
|
var isNewDone = _manager_P_Product.NewProduct(p, p.Details, out string msg);
|
if (!isNewDone)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{p.PID}数据库新增异常,{msg}");
|
}
|
}
|
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"{p.PID}_{p.SEQUENCE}产品入列完成");
|
}
|
|
public virtual ProductModel FindProductBySequence(string sequence, bool isEnabelQueue)
|
{
|
ProductModel p = null;
|
if (isEnabelQueue)
|
{
|
lock (_productListLock)
|
{
|
p = ProductList.FirstOrDefault(u => u.SEQUENCE == sequence);
|
}
|
}
|
|
if (p != null)
|
{
|
return p;
|
}
|
else
|
{
|
var pDB = _manager_P_Product.QueryProductBySequence(sequence);
|
if (pDB != null)
|
{
|
p = new ProductModel(pDB);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"从数据库获取产品对象{pDB.PID},序号{pDB.SEQUENCE},条码{pDB.SN}");
|
}
|
|
if (p == null)
|
{
|
p = new ProductModel();
|
p.SEQUENCE = sequence;
|
p.PID = p.PID + "_" + sequence.Split('_')[sequence.Split('_').Length - 1];
|
|
p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Where(u => u.IsEnabled).Select(u => u.PositionName).ToList());
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"未能从数据库获取产品对象,使用临时新建产品对象");
|
}
|
|
NewProductIntoList(p, false);
|
}
|
|
return p;
|
}
|
|
|
|
|
public async Task RunImageCheckAsync(List<ProductModel> products, string triggerText, string triggerSource, IImageSet imgSet, MeasureBind measureBind)
|
{
|
await Task.Run(() =>
|
{
|
List<DetectResult> resultList = new List<DetectResult>();
|
if (products == null || products.Count == 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"工位{measureBind.WorkPosition}检测时产品信息为空");
|
imgSet.HImage?.Dispose();
|
imgSet.HImage = null;
|
return;
|
}
|
|
try
|
{
|
List<string> pidList = products.Select(u => u.PID).OrderBy(u => u).ToList();
|
if (imgSet == null || imgSet.HImage == null)
|
{
|
throw new Exception($"产品{string.Join(",", pidList)}检测{measureBind.GetDisplayText()}未能获取图片对象");
|
}
|
|
//检测顺序 ML->自定义检测
|
if (!string.IsNullOrWhiteSpace(measureBind.DetectionId))
|
{
|
string detectionName = (ML.InitialConfig as MLInitialConfigBase).DetectionConfigs.FirstOrDefault(u => u.Id == measureBind.DetectionId)?.Name;
|
|
|
//List<string> pidList2 = new List<string>();//pidList.Select(u => u.Split('_')[u.Split('_').Length - 1]).ToList();
|
//Dictionary<string, string> dicpid = new Dictionary<string, string>();
|
|
//for (int i = 0; i < pidList.Count; i++)
|
//{
|
// var tem = pidList[i].Split('_')[pidList[i].Split('_').Length - 1];
|
// pidList2.Add(tem);
|
// dicpid[tem] = pidList[i];
|
//}
|
|
|
List<DetectResult> detectResults = ML?.RunMLDetectionSync(imgSet, pidList, measureBind.DetectionId);
|
List<DetectResult> ngResults = new List<DetectResult>();
|
|
|
//for (int i = 0; i < detectResults.Count; i++)
|
//{
|
// detectResults[i].PID = dicpid[detectResults[i].PID];
|
//}
|
|
|
detectResults.GroupBy(u => u.PID).ToList().ForEach(u =>
|
{
|
if (u.ToList().Count > 0 && u.ToList().Any(m => m.ResultState != EnumHelper.ResultState.OK))
|
{
|
if (u.ToList().GetDefectDescList().Count == 0)
|
{
|
var errorSpec = _errorSpec.Copy();
|
errorSpec.Code = "检测TBD";
|
errorSpec.ActualValue = -999;
|
DetectResult ngResult = new DetectResult() { Specs = new List<ISpec>() { errorSpec }, PID = u.Key };
|
ngResults.Add(ngResult);
|
}
|
}
|
});
|
|
detectResults.AddRange(ngResults);
|
resultList.AddRange(detectResults);
|
|
//detectResults[0].ActionForAllNetResults(n =>
|
//{
|
// if (n.DetectDetails.Count == 0)
|
// {
|
// string data = $"{n.DetectTime.ToString("HH:mm:ss.fff")},{pid},,,,{detectResult.DetectionName},{n.IsAbandoned},{n.NetName},{set.ImageIndex},OK,OK,,,,,,,,";
|
// CSVHelper.CSVOutputAsync(csvpartfilename, data, Part_CSV_Head);
|
// }
|
// else
|
// {
|
// n.DetectDetails.ForEach(d =>
|
// {
|
// string data = $"{n.DetectTime.ToString("HH:mm:ss.fff")},{pid},{d.Id},{string.Join("|", d.ParentIds)},{d.Remark},{detectResult.DetectionName},{d.IsAbandoned},{n.NetName},{set.ImageIndex},{d.FinalResult},{d.DetectResult},{d.ClassName},{(d.Rect.Width * d.PixelSize).ToString("f4")},{(d.Rect.Height * d.PixelSize).ToString("f4")},{d.Probability},{d.Uncertainty},{d.Area},{d.AreaInCrop},{d.AreaInActual.ToString("f4")},{d.Rect.X.ToString("f4")},{d.Rect.Y.ToString("f4")}";
|
// CSVHelper.CSVOutputAsync(csvpartfilename, data, Part_CSV_Head);
|
// });
|
// }
|
//});
|
}
|
|
|
RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedMonitorId, resultList);
|
RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedCombineMethodId, resultList);
|
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBind.WorkPosition}检测过程异常,{ex.ToString()}");
|
|
var errorSpec = _errorSpec.Copy();
|
errorSpec.ActualValue = -999;
|
products.ForEach(p =>
|
{
|
p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, new List<DetectResult>()
|
{
|
new DetectResult()
|
{
|
Specs = new List<ISpec>()
|
{
|
errorSpec
|
},
|
PID = p.PID,
|
}
|
});
|
});
|
}
|
finally
|
{
|
|
try
|
{
|
if (resultList.Count > 0)
|
{
|
products.ForEach(p =>
|
{
|
var pResults = resultList.Where(u => u.PID == p.PID).ToList();
|
p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, pResults);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}添加工位{measureBind.WorkPosition}检测结果,数量{pResults.Count}");
|
});
|
}
|
|
products.ForEach(p =>
|
{
|
if (p.PositoinCheckDone(measureBind.WorkPosition, measureBind.CheckIndex, out string msg))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,该工位检测全部结束");
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,{msg}");
|
}
|
});
|
|
|
if (resultList.Any(u => u.ResultState != EnumHelper.ResultState.OK))
|
{
|
if (!products[0].SEQUENCE.ToLower().Contains("test"))
|
{
|
SaveZipPreparation(string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}", imgSet, measureBind.WorkPosition);
|
}
|
if (measureBind.NGImageSwitch)
|
{
|
if (string.IsNullOrWhiteSpace(M141Config.NGImageFolder))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未配置NG图片保存目录");
|
}
|
else
|
{
|
string folder = Path.Combine(M141Config.NGImageFolder, DateTime.Now.ToString("yyyyMMdd"), measureBind.WorkPosition, "NG");
|
|
if (!Directory.Exists(folder))
|
{
|
Directory.CreateDirectory(folder);
|
}
|
|
string id = string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}";
|
|
string post = "";
|
if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatNG))
|
{
|
post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatNG];
|
}
|
else
|
{
|
post = M141Config.ImageFormatNG.ToString().ToLower();
|
}
|
|
string ngImageFile = Path.Combine(folder, $"{id}.{post}");
|
var bitmap = imgSet.HImage.ConvertHImageToBitmap();
|
bitmap.Save(ngImageFile, M141Config.ImageFormatNG);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}NG图片已保存");
|
bitmap.Dispose();
|
}
|
}
|
}
|
else
|
{
|
if (!products[0].SEQUENCE.ToLower().Contains("test"))
|
{
|
SaveZipPreparation(string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}", imgSet, measureBind.WorkPosition);
|
}
|
if (measureBind.OKImageSwitch)
|
{
|
if (string.IsNullOrWhiteSpace(M141Config.NGImageFolder))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未配置NG图片保存目录");
|
}
|
else
|
{
|
string folder = Path.Combine(M141Config.NGImageFolder, DateTime.Now.ToString("yyyyMMdd"), measureBind.WorkPosition, "OK");
|
|
if (!Directory.Exists(folder))
|
{
|
Directory.CreateDirectory(folder);
|
}
|
|
string id = string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}";
|
string post = "";
|
if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatOK))
|
{
|
post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatOK];
|
}
|
else
|
{
|
post = M141Config.ImageFormatOK.ToString().ToLower();
|
}
|
|
string ngImageFile = Path.Combine(folder, $"{id}.{post}");
|
var bitmap = imgSet.HImage.ConvertHImageToBitmap();
|
bitmap.Save(ngImageFile, M141Config.ImageFormatOK);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}OK图片已保存");
|
bitmap.Dispose();
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{measureBind.WorkPosition},产品{string.Join(",", products.Select(u => u.PID))}的NG图片保存异常,{ex.GetExceptionMessage()}");
|
}
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片{imgSet.PID}开始释放");
|
imgSet.HImage?.Dispose();
|
imgSet.HImage = null;
|
imgSet.Dispose();
|
imgSet = null;
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片已释放");
|
|
|
}
|
});
|
}
|
|
|
public async Task RunImageCheckAsyncForSB(List<ProductModel> products, string triggerText, string triggerSource, IImageSet imgSet, MeasureBind measureBind)
|
{
|
await Task.Run(() =>
|
{
|
List<DetectResult> resultList = new List<DetectResult>();
|
if (products == null || products.Count == 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"工位{measureBind.WorkPosition}检测时产品信息为空");
|
imgSet.HImage?.Dispose();
|
imgSet.HImage = null;
|
return;
|
}
|
|
try
|
{
|
List<string> pidList = products.Select(u => u.PID).OrderBy(u => u).ToList();
|
if (imgSet == null || imgSet.HImage == null)
|
{
|
throw new Exception($"产品{string.Join(",", pidList)}检测{measureBind.GetDisplayText()}未能获取图片对象");
|
}
|
|
//检测顺序 ML->自定义检测
|
if (!string.IsNullOrWhiteSpace(measureBind.DetectionId))
|
{
|
string detectionName = (ML.InitialConfig as MLInitialConfigBase).DetectionConfigs.FirstOrDefault(u => u.Id == measureBind.DetectionId)?.Name;
|
|
|
//List<string> pidList2 = new List<string>();//pidList.Select(u => u.Split('_')[u.Split('_').Length - 1]).ToList();
|
//Dictionary<string, string> dicpid = new Dictionary<string, string>();
|
|
//for (int i = 0; i < pidList.Count; i++)
|
//{
|
// var tem = pidList[i].Split('_')[pidList[i].Split('_').Length - 1];
|
// pidList2.Add(tem);
|
// dicpid[tem] = pidList[i];
|
//}
|
|
|
List<DetectResult> detectResults = ML?.RunMLDetectionSync(imgSet, pidList, measureBind.DetectionId);
|
List<DetectResult> ngResults = new List<DetectResult>();
|
|
|
//for (int i = 0; i < detectResults.Count; i++)
|
//{
|
// detectResults[i].PID = dicpid[detectResults[i].PID];
|
//}
|
|
|
detectResults.GroupBy(u => u.PID).ToList().ForEach(u =>
|
{
|
if (u.ToList().Count > 0 && u.ToList().Any(m => m.ResultState != EnumHelper.ResultState.OK))
|
{
|
if (u.ToList().GetDefectDescList().Count == 0)
|
{
|
var errorSpec = _errorSpec.Copy();
|
errorSpec.Code = "检测TBD";
|
errorSpec.ActualValue = -999;
|
DetectResult ngResult = new DetectResult() { Specs = new List<ISpec>() { errorSpec }, PID = u.Key };
|
ngResults.Add(ngResult);
|
}
|
}
|
});
|
|
detectResults.AddRange(ngResults);
|
resultList.AddRange(detectResults);
|
}
|
|
RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedMonitorId, resultList);
|
RunCustomizedMethod(products, triggerText, triggerSource, imgSet, measureBind.CustomizedCombineMethodId, resultList);
|
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBind.WorkPosition}检测过程异常,{ex.ToString()}");
|
|
var errorSpec = _errorSpec.Copy();
|
errorSpec.ActualValue = -999;
|
products.ForEach(p =>
|
{
|
p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, new List<DetectResult>()
|
{
|
new DetectResult()
|
{
|
Specs = new List<ISpec>()
|
{
|
errorSpec
|
},
|
PID = p.PID,
|
}
|
});
|
});
|
}
|
finally
|
{
|
|
try
|
{
|
if (resultList.Count > 0)
|
{
|
products.ForEach(p =>
|
{
|
var pResults = resultList.Where(u => u.PID == p.PID).ToList();
|
p.AddNewDetectResults(M141Config.StationCode, measureBind.WorkPosition, pResults);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}添加工位{measureBind.WorkPosition}检测结果,数量{pResults.Count}");
|
});
|
}
|
|
products.ForEach(p =>
|
{
|
if (p.PositoinCheckDone(measureBind.WorkPosition, measureBind.CheckIndex, out string msg))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,该工位检测全部结束");
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"产品{p.PID}_{p.SEQUENCE}工位{measureBind.WorkPosition}的第{measureBind.CheckIndex}检测完成,{msg}");
|
}
|
});
|
|
|
if (resultList.Any(u => u.ResultState != EnumHelper.ResultState.OK))
|
{
|
if (!products[0].SEQUENCE.ToLower().Contains("test"))
|
{
|
SaveZipPreparation(string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}", imgSet, measureBind.WorkPosition);
|
}
|
|
//if (measureBind.NGImageSwitch)
|
//{
|
if (string.IsNullOrWhiteSpace(M141Config.NGImageFolder))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未配置NG图片保存目录");
|
}
|
else
|
{
|
string folder = Path.Combine(M141Config.NGImageFolder, DateTime.Now.ToString("yyyyMMdd"), measureBind.WorkPosition, "NG");
|
|
if (!Directory.Exists(folder))
|
{
|
Directory.CreateDirectory(folder);
|
}
|
|
string id = string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}";
|
|
string post = "";
|
if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatNG))
|
{
|
post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatNG];
|
}
|
else
|
{
|
post = M141Config.ImageFormatNG.ToString().ToLower();
|
}
|
|
//string ngImageFile = Path.Combine(folder, $"{id}.{post}");
|
//var bitmap = imgSet.HImage.ConvertHImageToBitmap();
|
//bitmap.Save(ngImageFile, M141Config.ImageFormatNG);
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}NG图片已保存");
|
|
OKNGImages.Add(new OKNGImage()
|
{
|
pid = products[0].PID,
|
name = id,
|
path = folder,
|
post = post,
|
result = "NG",
|
bitmap = imgSet.HImage.ConvertHImageToBitmap(),
|
ImageFormat = M141Config.ImageFormatNG,
|
issave = measureBind.NGImageSwitch
|
});
|
|
|
|
}
|
//}
|
}
|
else
|
{
|
if (!products[0].SEQUENCE.ToLower().Contains("test"))
|
{
|
SaveZipPreparation(string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}", imgSet, measureBind.WorkPosition);
|
}
|
//if (measureBind.OKImageSwitch)
|
//{
|
if (string.IsNullOrWhiteSpace(M141Config.NGImageFolder))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"未配置NG图片保存目录");
|
}
|
else
|
{
|
string folder = Path.Combine(M141Config.NGImageFolder, DateTime.Now.ToString("yyyyMMdd"), measureBind.WorkPosition, "OK");
|
|
if (!Directory.Exists(folder))
|
{
|
Directory.CreateDirectory(folder);
|
}
|
|
string id = string.Join("_", products.Select(u => $"{u.PID}_{u.SN}")) + $"-{measureBind.ImageIndex}_{DateTime.Now.ToString("HHmmssfff")}";
|
string post = "";
|
if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatOK))
|
{
|
post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatOK];
|
}
|
else
|
{
|
post = M141Config.ImageFormatOK.ToString().ToLower();
|
}
|
|
//string ngImageFile = Path.Combine(folder, $"{id}.{post}");
|
//var bitmap = imgSet.HImage.ConvertHImageToBitmap();
|
//bitmap.Save(ngImageFile, M141Config.ImageFormatOK);
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}OK图片已保存");
|
OKNGImages.Add(new OKNGImage()
|
{
|
pid = products[0].PID,
|
name = id,
|
path = folder,
|
post = post,
|
result = "OK",
|
bitmap = imgSet.HImage.ConvertHImageToBitmap(),
|
ImageFormat = M141Config.ImageFormatOK,
|
issave = measureBind.OKImageSwitch
|
});
|
}
|
//}
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{measureBind.WorkPosition},产品{string.Join(",", products.Select(u => u.PID))}的NG图片保存异常,{ex.GetExceptionMessage()}");
|
}
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片{imgSet.PID}开始释放");
|
imgSet.HImage?.Dispose();
|
imgSet.HImage = null;
|
imgSet.Dispose();
|
imgSet = null;
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"图片已释放");
|
|
}
|
});
|
}
|
|
private void RunCustomizedMethod(List<ProductModel> products, string triggerText, string triggerSource, IImageSet imgSet, string methodId, List<DetectResult> resultList)
|
{
|
try
|
{
|
if (!string.IsNullOrWhiteSpace(methodId))
|
{
|
|
var monitorSet = Config.GetAllMonitorSet().FirstOrDefault(u => u.Id == methodId);
|
|
if (monitorSet.OpConfig is IImageCheckOperationConfig iConfig)
|
{
|
var opConfig = iConfig.Clone();
|
|
opConfig.Products = new List<ProductModel>(products);
|
opConfig.ImageSet = imgSet;
|
|
opConfig.TriggerStr = triggerText;
|
opConfig.TriggerSource = triggerSource;
|
opConfig.ExecuteDevice = iConfig.ExecuteDevice;
|
|
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"图片id,{imgSet.id}");
|
var res = RunSelectedMonitorSetByManual(methodId, opConfig);
|
|
if (res.DataObj is List<DetectResult> dr)
|
{
|
dr.ForEach(r =>
|
{
|
r.IsPreTreatDone = r.IsNetCheckDone = r.IsAfterTreatDone = true;
|
r.SetResult();
|
});
|
resultList.AddRange(dr);
|
}
|
|
if (res.Result != 1)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"自定义检测过程异常,{res.Message}");
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"自定义检测过程异常,{ex.GetExceptionMessage()}");
|
}
|
}
|
|
private void SetSpecResult(ProductModel productModel)
|
{
|
// 更新既有的检测记录内容
|
var existProduct = ProductSpecResultList.FirstOrDefault(x => x.PID == productModel.PID);
|
if (existProduct != null)
|
{
|
existProduct.Details = productModel.Details;
|
return;
|
}
|
|
// 新增检测产品记录
|
ProductSpecResultList.Insert(0, productModel);
|
while (ProductSpecResultList.Count > M141Config.MaxProductListAmount)
|
{
|
ProductSpecResultList.RemoveAt(ProductSpecResultList.Count - 1);
|
}
|
}
|
|
|
[ProcessMethod("", "HeartBeat", "心跳", InvokeType.TestInvoke)]
|
public ResponseMessage HeartBeat(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
|
{
|
ResponseMessage msg = new ResponseMessage();
|
msg.IsReply = true;
|
msg.DataStr = M141Config.Heartstr;
|
|
if (M141Config.PointState)
|
{
|
if (!CheckInspectionInPeriodic(3000))
|
{
|
msg.IsReply = false;
|
}
|
}
|
|
//DateTime now = DateTime.Now;
|
//DateTime today8am = new DateTime(now.Year, now.Month, now.Day, 8, 0, 0);
|
//DateTime today20am = new DateTime(now.Year, now.Month, now.Day, 20, 0, 0);
|
|
|
//InitialOEEStatistic()
|
|
return msg;
|
}
|
|
|
public void SaveZipPreparation(string id, IImageSet imgSet, string workstation)
|
{
|
try
|
{
|
if (M141Config.SaveStateZip)
|
{
|
if (M141Config.PositionZip.Any(u => u.WorkPosition == workstation))
|
{
|
if (M141Config.SaveTwoPathZip)
|
{
|
if (!string.IsNullOrEmpty(M141Config.SavePathZip) || !string.IsNullOrEmpty(M141Config.SavePathZip2))
|
{
|
if (string.IsNullOrEmpty(M141Config.CurrPathZip))
|
{
|
M141Config.CurrPathZip = M141Config.SavePathZip;
|
}
|
|
if (M141Config.CurrPathZip != M141Config.SavePathZip && M141Config.CurrPathZip != M141Config.SavePathZip2)
|
{
|
M141Config.CurrPathZip = M141Config.SavePathZip;
|
}
|
|
DriveInfo driveInfo3 = DriveInfo.GetDrives().First(d => M141Config.CurrPathZip.StartsWith(d.Name));
|
double freespace3 = (double)driveInfo3.AvailableFreeSpace / (double)driveInfo3.TotalSize * 100;
|
|
if (freespace3 < M141Config.SaveMinPercentZip)
|
{
|
DriveInfo driveInfo1 = DriveInfo.GetDrives().First(d => M141Config.SavePathZip.StartsWith(d.Name));
|
double freespace1 = (double)driveInfo1.AvailableFreeSpace / (double)driveInfo1.TotalSize * 100;
|
|
DriveInfo driveInfo2 = DriveInfo.GetDrives().First(d => M141Config.SavePathZip2.StartsWith(d.Name));
|
double freespace2 = (double)driveInfo2.AvailableFreeSpace / (double)driveInfo2.TotalSize * 100;
|
|
if (freespace1 > M141Config.SaveMinPercentZip)
|
{
|
M141Config.CurrPathZip = M141Config.SavePathZip;
|
SaveProcessConfig(M141Config);
|
}
|
else if (freespace2 > M141Config.SaveMinPercentZip)
|
{
|
M141Config.CurrPathZip = M141Config.SavePathZip2;
|
SaveProcessConfig(M141Config);
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"双磁盘都达到存储极限,不再保存压缩图片");
|
return;
|
}
|
}
|
|
string folder = Path.Combine(M141Config.CurrPathZip, DateTime.Now.ToString("yyyyMMdd"), workstation);
|
|
if (!Directory.Exists(folder))
|
{
|
Directory.CreateDirectory(folder);
|
}
|
|
string post = "";
|
if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatZip))
|
{
|
post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatZip];
|
}
|
else
|
{
|
post = M141Config.ImageFormatZip.ToString().ToLower();
|
}
|
|
|
HImage zoomimage;
|
if ((int)M141Config.SavezipZip != 10)
|
{
|
//// 调用zoom_image_factor算子
|
HOperatorSet.ZoomImageFactor(imgSet.HImage, out HObject zoomHob, ((double)M141Config.SavezipZip) / 10, ((double)M141Config.SavezipZip) / 10, "constant");
|
zoomimage = zoomHob.ConvertHObjectToHImage();
|
}
|
else
|
{
|
zoomimage = imgSet.HImage;
|
}
|
//string ngImageFile = Path.Combine(folder, $"{id}.{post}");
|
//var bitmap = zoomimage.ConvertHImageToBitmap();
|
//bitmap.Save(ngImageFile, M141Config.ImageFormatZip);
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}压缩图片已保存");
|
//zoomimage.Dispose();
|
//bitmap.Dispose();
|
|
lock (ZipImages)
|
{
|
ZipImages.Add(new ZipImage
|
{
|
path = folder,
|
name = id,
|
post = post,
|
image = zoomimage,
|
});
|
}
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"压缩图片保存双路径为空");
|
}
|
}
|
else
|
{
|
if (!string.IsNullOrEmpty(M141Config.SavePathZip))
|
{
|
|
string folder = Path.Combine(M141Config.SavePathZip, DateTime.Now.ToString("yyyyMMdd"), workstation);
|
if (!Directory.Exists(folder))
|
{
|
Directory.CreateDirectory(folder);
|
}
|
string post = "";
|
if (ImageSet.ImageFormatPostDict.ContainsKey(M141Config.ImageFormatZip))
|
{
|
post = ImageSet.ImageFormatPostDict[M141Config.ImageFormatZip];
|
}
|
else
|
{
|
post = M141Config.ImageFormatZip.ToString().ToLower();
|
}
|
|
//// 调用zoom_image_factor算子
|
HOperatorSet.ZoomImageFactor(imgSet.HImage, out HObject zoomHob, ((double)M141Config.SavezipZip) / 10, ((double)M141Config.SavezipZip) / 10, "constant");
|
|
HImage zoomimage = zoomHob.ConvertHObjectToHImage();
|
//string ngImageFile = Path.Combine(folder, $"{id}_{Result}.{post}");
|
//var bitmap = zoomimage.ConvertHImageToBitmap();
|
//bitmap.Save(ngImageFile, M141Config.ImageFormatZip);
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{id}压缩图片已保存");
|
//zoomimage.Dispose();
|
|
lock (ZipImages)
|
{
|
ZipImages.Add(new ZipImage
|
{
|
path = folder,
|
name = id,
|
post = post,
|
image = zoomimage,
|
});
|
}
|
|
}
|
else
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"压缩图片保存路径为空");
|
}
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"压缩图片整理异常{e.ToString()}");
|
}
|
}
|
|
|
public void SaveZip(string pid, string result)
|
{
|
try
|
{
|
if (M141Config.SaveStateZip)
|
{
|
lock (ZipImages)
|
{
|
var zipimagespid = ZipImages.Where(u => u.name.Contains(pid)).ToList();
|
if (zipimagespid != null)
|
{
|
for (int i = 0; i < zipimagespid.Count; i++)
|
{
|
string ngImageFile = Path.Combine(zipimagespid[i].path, $"{zipimagespid[i].name}_{result}.{zipimagespid[i].post}");
|
var bitmap = zipimagespid[i].image.ConvertHImageToBitmap();
|
bitmap.Save(ngImageFile, M141Config.ImageFormatZip);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{zipimagespid[i].name}压缩图片已保存");
|
zipimagespid[i].image.Dispose();
|
zipimagespid[i].image = null;
|
bitmap.Dispose();
|
}
|
ZipImages.RemoveAll(u => u.name.Contains(pid));
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"压缩图片保存异常{e.ToString()}");
|
}
|
}
|
|
|
#region plc
|
public ResponseMessage RunImageCheck_plc(IOperationConfig config, int plcnum)
|
{
|
ResponseMessage msg = new ResponseMessage();
|
msg.Result = 1;
|
List<MeasureBind> measureBinds = new List<MeasureBind>();
|
string inputSequence = "";
|
var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
try
|
{
|
RunImageCheckPreTreat_plc(config, out measureBinds, out inputSequence);
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测预处理异常,{ex.GetExceptionMessage()}");
|
msg.Result = -1;
|
msg.Message = ex.Message;
|
return msg;
|
}
|
|
List<string> cameraIds = measureBinds.Select(u => u.CameraId).ToList();
|
try
|
{
|
ConcurrentDictionary<MeasureBind, IImageSet> imgSetDicts = new ConcurrentDictionary<MeasureBind, IImageSet>();
|
|
measureBinds.AsParallel().ForAll(b =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == b.CameraId) as CameraBase;
|
if (camera == null)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测配置{b.GetDisplayText()}未能获取相机设备");
|
imgSetDicts[b] = null;
|
return;
|
}
|
imgSetDicts[b] = null;
|
|
try
|
{
|
imgSetDicts[b] = CollectHImage(camera, b.SnapshotOpConfig);
|
}
|
catch (Exception ea)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{measureBinds[0].WorkPosition}的第{measureBinds[0].CheckIndex}检测获取图像信息异常 {ea.ToString()}");
|
}
|
|
var pList = b.ProductIndices.Select(pi =>
|
{
|
string pid = $"{inputSequence}_{pi}";
|
return FindProductBySequence(pid, true);
|
}).ToList();
|
|
RunImageCheckAsync(pList, config.TriggerStr, config.TriggerSource, imgSetDicts[b], b);
|
});
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"检测处理异常,{ex.GetExceptionMessage()}");
|
msg.Result = -1;
|
msg.Message = ex.Message;
|
return msg;
|
}
|
|
CheckPositionDoneAsync_plc(measureBinds[0].WorkPosition, inputSequence, config, cameraIds, plcnum);
|
return msg;
|
}
|
|
|
public void RunImageCheckPreTreat_plc(IOperationConfig config, out List<MeasureBind> measureBinds, out string inputSequence)
|
{
|
Task.Run(() =>
|
{
|
SetProcessRunState(EnumHelper.RunState.Running);
|
});
|
|
measureBinds = new List<MeasureBind>();
|
inputSequence = "";
|
|
var triggerDatas = config.TriggerStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
if (triggerDatas.Length < 2)
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}解析失败,数据长度小于2");
|
}
|
|
string positionValue = triggerDatas[0];
|
int checkIndex = -1;
|
if (!int.TryParse(triggerDatas[1].Replace("Scan", ""), out checkIndex))
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}解析失败,未能获取检测序号");
|
}
|
|
|
var positionSet = M141Config.WorkPositionCollection.Where(u => u.IsEnabled).FirstOrDefault(u => u.TriggerValue == positionValue);
|
if (positionSet == null)
|
{
|
throw new ProcessException($"触发文本{config.TriggerStr}未能获取{positionValue}对应的可用工位信息");
|
}
|
|
measureBinds = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionSet.PositionName && u.CheckIndex == checkIndex).ToList();
|
if (measureBinds.Count == 0)
|
{
|
throw new ProcessException($"未能获取工位{positionSet.PositionName}的第{checkIndex}检测配置信息");
|
}
|
|
measureBinds.Select(u => u.CameraId).ToList().ForEach(c =>
|
{
|
var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
if (camera != null)
|
{
|
camera.ClearImageBufferQueue();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"相机{camera.Name}检测前清理缓存完成");
|
}
|
});
|
|
if (positionSet.IsSendClearSingal)
|
{
|
var sourceData = config.TriggerSource.Split(':');
|
string ip = "";
|
int port = 0;
|
if (sourceData.Length >= 2)
|
{
|
ip = sourceData[0];
|
port = int.Parse(sourceData[1]);
|
}
|
|
TcpListener?.WriteAndRead(positionSet.ClearStr, out _, out _, false, ip, port);
|
}
|
|
inputSequence = triggerDatas[triggerDatas.Length - 1];
|
|
string tempPID = inputSequence;
|
|
string pidstr = DateTime.Now.ToString("yyyyMMddHHmmssfff");
|
measureBinds.Where(b => b.IsFirstPosition).ToList().ForEach(b =>
|
{
|
b.ProductIndices.ForEach(i =>
|
{
|
ProductModel p = new ProductModel();
|
p.SEQUENCE = $"{tempPID}_{i}";
|
p.PID = $"{pidstr}T_{i}";
|
p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Select(u => u.PositionName).ToList());
|
NewProductIntoList(p, true);
|
});
|
});
|
|
|
int de = 0;
|
|
measureBinds.Where(b => (b.CheckIndex == de || b.CheckIndex == 1) && b.ImageIndex == 0).AsParallel().ForAll(b =>
|
{
|
List<int> temint = new List<int>();
|
|
temint = new List<int>() { 1, 2, 3 };
|
|
temint.ForEach(i =>
|
{
|
string sequence = $"{tempPID}_{i}";
|
var p = FindProductBySequence(sequence, b.IsEnabelQueryFromQueue);
|
|
//初始化产品的检测次数
|
var checkIndexList = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition && u.ProductIndices.Contains(i)).Select(u => u.CheckIndex).OrderBy(u => u).ToList();
|
p.InitialPositionCheckList(b.WorkPosition, checkIndexList);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{p.PID}_{p.SEQUENCE}已清理{b.WorkPosition}检测数据。当前已完成工位{string.Join(",", p.Details.Select(u => u.PositionName))}");
|
});
|
|
//初始化工位的检测次数
|
var positionCheckTimes = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == b.WorkPosition).Select(u => u.CheckIndex).ToList();
|
lock (_positionCheckTimeLock)
|
{
|
_positionCheckTimeDict[b.WorkPosition] = positionCheckTimes;
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}初始化检测次数:{string.Join(",", positionCheckTimes)}");
|
}
|
});
|
|
measureBinds.AsParallel().ForAll(b =>
|
{
|
lock (_positionCheckTimeLock)
|
{
|
_positionCheckTimeDict[b.WorkPosition].RemoveAll(u => u == b.CheckIndex);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"工位{b.WorkPosition}开始第{b.CheckIndex}次检测,待检测序号:{string.Join(",", _positionCheckTimeDict[b.WorkPosition])}");
|
}
|
});
|
}
|
|
public async Task<List<ProductModel>> CheckPositionDoneAsync_plc(string positionName, string inputSequence, IOperationConfig config, List<string> cameraIds, int plcnum)
|
{
|
string triggerSource = config.TriggerSource;
|
return await _taskFactory.StartNew(() =>
|
{
|
try
|
{
|
|
string index = config.TriggerStr.Split(',')[1];
|
var positionSet = M141Config.WorkPositionCollection.FirstOrDefault(u => u.PositionName == positionName);
|
|
var checkRemains = _positionCheckTimeDict[positionName];
|
|
var pIndices = M141Config.MeasureBindCollection.Where(u => u.WorkPosition == positionName).SelectMany(u => u.ProductIndices).Distinct().OrderBy(u => u).ToList();
|
pIndices = new List<int> { 1, 2, 3 };
|
|
|
var pList = pIndices.Select(u =>
|
{
|
string sequence = $"{inputSequence}_{u}";
|
return FindProductBySequence(sequence, true);
|
}).ToList();
|
List<bool> plcresult = new List<bool>();
|
if (pList.Any(u => u == null))
|
{
|
plcresult = new List<bool>() { false, false, false };
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"获取工位{positionName}汇总结果时产品信息为空");
|
}
|
else
|
{
|
int waitInterval = 20;
|
int repeatTime = M141Config.DetectTimeout / waitInterval;
|
do
|
{
|
if (!pList.All(p =>
|
{
|
p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
return detail?.IsDone ?? false;
|
}))
|
{
|
Thread.Sleep(waitInterval);
|
repeatTime--;
|
}
|
else
|
{
|
//Thread.Sleep(50);
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"成功完成工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测");
|
break;
|
}
|
|
if (repeatTime < 0)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"工位{positionName}产品{string.Join(",", pList.Select(u => $"{u.PID}_{u.SEQUENCE}"))}检测获取结果超时");
|
break;
|
}
|
} while (true);
|
}
|
|
|
pList.ForEach(p =>
|
{
|
var isOK = p.GetPositionResult(M141Config.StationCode, positionName, out P_PRODUCT_DETAIL detail);
|
plcresult.Add(isOK);
|
//List<string> specHeads = new List<string>();
|
//string head = p.GetCSVHead(ref specHeads, positionName);
|
//if (!_positionSpecHeads.ContainsKey(positionName))
|
//{
|
// _positionSpecHeads[positionName] = specHeads;
|
//}
|
|
//string data = p.GetCSVData(_positionSpecHeads[positionName], positionName);
|
//CSVRecordAsync($"{positionName}_Record_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, head);
|
|
////UpdatePositionResultToDB(detail);
|
//var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
//UpdatePositionResultDisplay(detail, isOK, positionName, seqData[seqData.Count - 1]);
|
//if (IsInspectionDoing)
|
//{
|
// OnSinglePostionDetectResultUpdate.Invoke(positionName, detail, seqData[seqData.Count - 1]);
|
//}
|
|
if (positionSet.IsLastPosition)
|
{
|
UpdateProductResultAsync(p);
|
//UpdateOverAllProductResultToUI(p, isOK);
|
//OnNewProductEnqueued?.Invoke(p);
|
//OnProductDequeued?.Invoke(p);
|
CheckContinuousNGAlarmAsync(p);
|
}
|
|
//SetSpecResult(p);
|
});
|
ReplyPlcData(plcresult, plcnum);
|
if (positionSet.IsLastPosition)
|
{
|
if (_ct != null)
|
{
|
UpdateCT(null, (float)((DateTime.Now - _ct.Value).TotalSeconds) / 3);
|
}
|
_ct = DateTime.Now;
|
}
|
|
//ReplyPlcData(positionName, config.TriggerValue);
|
|
//cameraIds.ForEach(c =>
|
//{
|
// var camera = DeviceCollection.FirstOrDefault(u => u.Id == c) as CameraBase;
|
// if (camera != null)
|
// {
|
// camera.ClearImageBufferQueue();
|
// LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"相机{camera.Name}清理缓存");
|
// }
|
//});
|
|
return pList;
|
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, ex.ToString());
|
return null;
|
}
|
|
});
|
}
|
|
|
public virtual void ReplyPlcData(List<bool> result, int plcnum)
|
{
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
public void wirtePLC(int add, int value)
|
{
|
Plc1?.WriteSingleAddress(add, value, out _);
|
}
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
public class ZipImage
|
{
|
public string path { set; get; }
|
|
public string name { set; get; }
|
|
public string post { set; get; }
|
|
public HImage image { set; get; }
|
|
}
|
public class OKNGImage
|
{
|
public string pid { set; get; }
|
public string path { set; get; }
|
|
public string name { set; get; }
|
|
public string post { set; get; }
|
public string result { set; get; }
|
|
public Bitmap bitmap { set; get; }
|
|
public ImageFormat ImageFormat { set; get; }
|
|
public bool issave { set; get; }
|
|
}
|
|
|
|
}
|