274 lines
11 KiB
C#
274 lines
11 KiB
C#
using Aurora.Api;
|
|
using Aurora.Api.Devices;
|
|
using Aurora.Util.HislogPlus;
|
|
using Hermes;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace AuroraLBAD.Service
|
|
{
|
|
public class StreamLightLBAD
|
|
{
|
|
static readonly Logger Log = new Logger("StreamLightLBAD");
|
|
|
|
public StreamLightClient _Client { get; set; }
|
|
public StreamLightSub _Sub { get; set; }
|
|
private List<LBAD_Feature_Data> LBADFeatureDataList = new List<LBAD_Feature_Data>();
|
|
private List<LBAD_Raw_Data> LBADRawDataList = new List<LBAD_Raw_Data>();
|
|
|
|
public Int16 LBADAlive { get; set; }
|
|
public class LBAD_Raw_Data
|
|
{
|
|
public Int32 ChannelSize { get; set; }
|
|
public Int32 BeadSize { get; set; }
|
|
}
|
|
public class LBAD_Feature_Data
|
|
{
|
|
public string LotID { get; set; }
|
|
public string CellID { get; set; }
|
|
public Int16 RecipeID { get; set; }
|
|
public Int16 ResultFlag { get; set; }
|
|
public double Avg { get; set; }
|
|
public double Min { get; set; }
|
|
public double Max { get; set; }
|
|
public double Stddev { get; set; }
|
|
public double RateDifference { get; set; }
|
|
public double CenterX { get; set; }
|
|
public double CenterY { get; set; }
|
|
public double Circularity { get; set; }
|
|
public double OuterDiameter { get; set; }
|
|
}
|
|
public enum eRequestData
|
|
{
|
|
Ready_Off = 1000,
|
|
Ready_On = 1001,
|
|
Welding_Trigger = 4000,
|
|
Welding_Stop = 5000,
|
|
Judge_Complete = 6000
|
|
}
|
|
public enum eJudgeFlag
|
|
{
|
|
NO_RESPONSE = -1,
|
|
OK = 6000,
|
|
WARNING,
|
|
NA,
|
|
NG,
|
|
ERROR
|
|
}
|
|
public unsafe struct stCellInfoData
|
|
{
|
|
public fixed byte chLotID[40]; // 40byte
|
|
public fixed byte chCellID[40]; // 40byte
|
|
public Int16 nRecipeID;
|
|
public Int16 nModelID;
|
|
}
|
|
|
|
//StreamLight Client LBAD
|
|
public const string MESSAGE_PC_LBAD_READY_STATUS = "PcLBADReadyStatus";
|
|
public const string MESSAGE_PC_LBAD_WELDING_TRIGGER = "PcLBADWeldingTrigger";
|
|
public const string MESSAGE_PC_LBAD_WELDING_STOP = "PcLBADWeldingStop";
|
|
public const string MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE = "PcLBADJudgementComplete";
|
|
public const string MESSAGE_PC_LBAD_CELL_INFO = "PcLBADCellinfo";
|
|
|
|
//StreamLight Sub LBAD
|
|
public const string MESSAGE_LBAD_FEATURE_DATA = "LBADFeatureData";
|
|
public const string MESSAGE_LBAD_RAW_DATA = "LBADRawData";
|
|
public const string MESSAGE_LBAD_ALIVE = "LBADAlive";
|
|
|
|
public void Initialize()
|
|
{
|
|
_Client.AddParser(MESSAGE_PC_LBAD_READY_STATUS, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
_Client.AddParser(MESSAGE_PC_LBAD_WELDING_TRIGGER, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
_Client.AddParser(MESSAGE_PC_LBAD_WELDING_STOP, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
//용접 완료 후 LBAD측에 JudgeComplete를 요청한뒤 JudgeFlag를 회신 받는다
|
|
_Client.AddParser(MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE, new StreamNumberParser<int>(), new StreamNumberParser<int>());
|
|
_Client.AddParser(MESSAGE_PC_LBAD_CELL_INFO, new StreamStringParser(), new StreamNumberParser<int>());
|
|
|
|
_Sub.AddParser(MESSAGE_LBAD_ALIVE, new StreamJsonParser<int>());
|
|
_Sub.AddParser(MESSAGE_LBAD_FEATURE_DATA, new StreamJsonParser<LBAD_Feature_Data>());
|
|
_Sub.AddParser(MESSAGE_LBAD_RAW_DATA, new StreamJsonParser<LBAD_Raw_Data>());
|
|
}
|
|
|
|
public bool SendReadyStatus(eRequestData data)
|
|
{
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
//int requestData = 1001;
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_READY_STATUS} Request");
|
|
var reply = _Client.RequestNReply(data, MESSAGE_PC_LBAD_READY_STATUS);
|
|
if (reply != null) {
|
|
var replyParsed = (int)reply;
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_READY_STATUS} Reply Result : {replyParsed}");
|
|
sw.Stop();
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_READY_STATUS} Complete time : {sw.ElapsedMilliseconds}");
|
|
} else {
|
|
Log.E($"StreamLight {MESSAGE_PC_LBAD_READY_STATUS} reply is null!");
|
|
sw.Stop();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool SendCellInfo(string lotID, string cellID, int recipeNo, int modelID)
|
|
{
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
byte[] arrCellinfo = null;
|
|
int sendresult = MakeInfoData(lotID, cellID, recipeNo, modelID, out arrCellinfo);
|
|
|
|
var replyData = _Client.RequestNReply(arrCellinfo, MESSAGE_PC_LBAD_CELL_INFO);
|
|
|
|
if (replyData != null) {
|
|
if (replyData is byte[] bytes && bytes.Length > 0) {
|
|
int replyParsed = bytes[0]; // 첫 바이트만 가져와서 int로 사용
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_CELL_INFO} Reply Result : {replyParsed}");
|
|
sw.Stop();
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_CELL_INFO} Complete time : {sw.ElapsedMilliseconds}");
|
|
return true;
|
|
}
|
|
} else {
|
|
Log.E($"StreamLight {MESSAGE_PC_LBAD_CELL_INFO} reply is null!");
|
|
sw.Stop();
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool SetWeldTriggerOn()
|
|
{
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
//int requestData = 4000;
|
|
var replyData = _Client.RequestNReply(eRequestData.Welding_Trigger, MESSAGE_PC_LBAD_WELDING_TRIGGER);
|
|
|
|
if (replyData != null) {
|
|
var replyParsed = (int)replyData;
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_WELDING_TRIGGER} Reply Result : {replyParsed}");
|
|
sw.Stop();
|
|
Log.I($"Stream {MESSAGE_PC_LBAD_WELDING_TRIGGER} Complete time : {sw.ElapsedMilliseconds}");
|
|
return true;
|
|
} else {
|
|
Log.E($"StreamLight {MESSAGE_PC_LBAD_WELDING_TRIGGER} reply is null!");
|
|
sw.Stop();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public bool SendWeldingStop()
|
|
{
|
|
//Welding Stop On
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
//int requestData = 5000;
|
|
var reply = _Client.RequestNReply(eRequestData.Welding_Stop, MESSAGE_PC_LBAD_WELDING_STOP);
|
|
|
|
if (reply != null) {
|
|
var replyParsed = (int)reply;
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_WELDING_STOP} Reply Result : {replyParsed}");
|
|
sw.Stop();
|
|
Log.I($"Stream {MESSAGE_PC_LBAD_WELDING_STOP} Complete time : {sw.ElapsedMilliseconds}");
|
|
return true;
|
|
} else {
|
|
Log.E($"StreamLight {MESSAGE_PC_LBAD_WELDING_STOP} reply is null!");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public eJudgeFlag CheckJudgeComplete()
|
|
{
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
//int requestData = 6000;
|
|
var reply = _Client.RequestNReply(eRequestData.Judge_Complete, MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE);
|
|
if (reply != null) {
|
|
var replyParsed = (int)reply;
|
|
Log.I($"StreamLight {MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE} Reply Result : {replyParsed}");
|
|
//JudgeFlag에 따라서 시퀀스 결정
|
|
//(OK = 6000, WARNING = 6001, NA = 6002, NG = 6003, ERROR = 6004)
|
|
if (Enum.IsDefined(typeof(eJudgeFlag), replyParsed)) {
|
|
sw.Stop();
|
|
Log.I($"Stream {MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE} Complete time : {sw.ElapsedMilliseconds}");
|
|
return (eJudgeFlag)replyParsed;
|
|
}
|
|
|
|
Log.E($"StreamLight {MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE} reply is abnormal value : {replyParsed}!");
|
|
sw.Stop();
|
|
} else {
|
|
Log.E($"StreamLight {MESSAGE_PC_LBAD_JUDGEMENT_COMPLETE} reply is null!");
|
|
sw.Stop();
|
|
}
|
|
return eJudgeFlag.NO_RESPONSE;
|
|
}
|
|
|
|
private static unsafe int MakeInfoData(string strLotID, string strCellID, int nRecipeID, int nModelID, out byte[] arrSendData)
|
|
{
|
|
stCellInfoData SendData = new stCellInfoData();
|
|
SendData.nRecipeID = Convert.ToInt16(nRecipeID);
|
|
SendData.nModelID = Convert.ToInt16(nModelID);
|
|
// data
|
|
// LotID, CellID 는 39자를 넘지 말것. 마지막에 /0 을 같이 보내자
|
|
// string byte 를 memory copy 하면 제대로 복사가 되지 않는다. 일일히 넣어줘야한다.
|
|
if (strLotID.Length > 39 || strCellID.Length > 39) {
|
|
arrSendData = null;
|
|
return E2.INVALID_ARGUMENT;
|
|
}
|
|
|
|
|
|
byte* PtrLotID = SendData.chLotID;
|
|
{
|
|
for (int i = 0; i < strLotID.Length; i++) {
|
|
SendData.chLotID[i] = Convert.ToByte(strLotID[i]);
|
|
}
|
|
SendData.chLotID[strLotID.Length] = Convert.ToByte('\0');
|
|
}
|
|
|
|
byte* PtrCellID = SendData.chCellID;
|
|
{
|
|
for (int i = 0; i < strCellID.Length; i++) {
|
|
SendData.chCellID[i] = Convert.ToByte(strCellID[i]);
|
|
}
|
|
SendData.chCellID[strCellID.Length] = Convert.ToByte('\0');
|
|
}
|
|
arrSendData = StructToBytes(SendData);
|
|
return E1.OK;
|
|
}
|
|
|
|
public static byte[] StructToBytes<T>(T structure) where T : struct
|
|
{
|
|
int size = Marshal.SizeOf(typeof(T));
|
|
byte[] bytes = new byte[size];
|
|
IntPtr ptr = Marshal.AllocHGlobal(size);
|
|
|
|
try {
|
|
Marshal.StructureToPtr(structure, ptr, true);
|
|
Marshal.Copy(ptr, bytes, 0, size);
|
|
} finally {
|
|
Marshal.FreeHGlobal(ptr);
|
|
}
|
|
return bytes;
|
|
}
|
|
|
|
private static void OnSubscribe(string from, string topic, object data)
|
|
{
|
|
switch (topic) {
|
|
case MESSAGE_LBAD_FEATURE_DATA:
|
|
var replyParsed = data as LBAD_Feature_Data;
|
|
|
|
Log.I($"StreamLight LBAD Feature Data : " +
|
|
$"LotID {replyParsed.LotID}, CellID {replyParsed.CellID}, RecipeID {replyParsed.RecipeID}, ResultFlag {replyParsed.ResultFlag}, " +
|
|
$"Avg {replyParsed.Avg}, Min {replyParsed.Min}, Max {replyParsed.Max}, Stddev {replyParsed.Stddev}" +
|
|
$"RateDifference {replyParsed.RateDifference}, CenterX {replyParsed.CenterX}, CenterY {replyParsed.CenterY}, " +
|
|
$"Circularity {replyParsed.Circularity}, OuterDiameter {replyParsed.OuterDiameter}");
|
|
break;
|
|
case MESSAGE_LBAD_ALIVE:
|
|
//var replyParsed = data as LBADAlive;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|