2026-01-26 14:51:28 +09:00

243 lines
7.7 KiB
C#

using Aurora.Api.Devices;
using Hermes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace AuroraLBAD.Device
{
public class LBAD_PILOT : SocketConn, ILBAD
{
SocketConnConfig config;
bool IsSimul;
bool IsReadyStatusbyAuto = false;
public List<stReceiveData> lsResultdata;
public LBAD_PILOT(string deviceid, bool isSimul) : base(deviceid, isSimul)
{
IsSimul = isSimul;
lsResultdata = new List<stReceiveData>();
}
public int Open(LBADConfig Config)
{
if (Config == null) {
return -1;
}
if (IsSimul) {
return E1.OK;
}
config = Config.ConnConfig as SocketConnConfig;
return Connect(config);
}
public void DisConnect()
{
if (config == null)
return;
Close();
}
public bool GetConnected()
{
if (IsSimul) {
return true;
}
return IsConnected();
}
public Int16 GetResult()
{
// 마지막 List 정보 가져오기
stReceiveData LastReceiveData;
GetResultData(out LastReceiveData);
return LastReceiveData.nResultFlag;
}
public int GetAlarm()
{
return E1.OK;
}
public int GetEnable()
{
return E1.OK;
}
public int SendCellData()
{
return SendInfoData("TEST_LOT_01", "TEST_CELL_01", 1, 4680);
}
public int SendCellData(string strLotID, string strCellID, int nRecipeID, int nModelID)
{
return SendInfoData(strLotID, strCellID, nRecipeID, nModelID);
}
public unsafe int SendInfoData(string strLotID, string strCellID, int nRecipeID, int nModelID)
{
stSendData SendData = new stSendData();
SendData.nBodySize = 84; // sizeof 를 대체할 방법을 찾아보자
SendData.nCmd = cmdSendInfo;
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)
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');
}
byte[] arrSendData = StructureAToByte(SendData);
return Send(arrSendData);
}
protected override void OnReceive(object sender, AsyncSocketReceiveEventArgs e)
{
stReceiveData ReceiveData;
byte[] arrReceiveData;
arrReceiveData = e.ReceiveData;
// 258 바이트만 복사
byte[] trimmedData = new byte[258];
Array.Copy(arrReceiveData, trimmedData, 258);
ReceiveData = BytesToObject(trimmedData);
lsResultdata.Add(ReceiveData);
}
public int GetResultData(out stReceiveData ReceiveData)
{
//byte[] arrReceiveData;
//Recieve(out arrReceiveData, 1000);
//ReceiveData = BytesToObject(arrReceiveData);
if(lsResultdata.Count > 0)
{
ReceiveData = lsResultdata.Last();
return E1.OK;
}
else
{
ReceiveData = new stReceiveData();
return E1.GENERIC;
}
}
public int GetResultDataList(out List<stReceiveData> ResultList)
{
ResultList = lsResultdata;
return E1.OK;
}
public void ClearResultDataList()
{
if (lsResultdata != null)
lsResultdata.Clear();
}
const Int16 cmdSendInfo = 10;
const Int16 cmdJobResultReport = 20;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct stSendData
{
public Int32 nBodySize; // sizeof(body) = 84byte
public Int16 nCmd; // cmdSendInfo = 10;
public fixed byte chLotID[40]; // 40byte
public fixed byte chCellID[40]; // 40byte
public Int16 nRecipeID;
public Int16 nModelID;
}
[StructLayout(LayoutKind.Sequential, Pack =1)]
public unsafe struct stReceiveData
{
public Int32 nBodySize; // sizeof(body) = 252byte
public Int16 nCmd; // cmdJobResultReport = 20;
public fixed byte chLotID[40]; // 40byte
public fixed byte chCellID[40]; // 40byte
public Int16 nRecipeID;
public Int16 nResultFlag; // (OK = 0, NG = 1, NA = 2, FAILED = 3, ERROR = 4)
public fixed double arrAverage[4]; // 8byte * 4ch = 32byte /Power -> arrAverage[0] //Br ->arrAverage[1]
public fixed double arrMin[4]; // 8byte * 4ch = 32byte
public fixed double arrMax[4]; // 8byte * 4ch = 32byte
public fixed double arrStdev[4]; // 8byte * 4ch = 32byte
public double dRateDifference;
public double dCenterX;
public double dCenterY;
public double dCircularity;
public double dOuterDiameter;
}
private byte[] StructureAToByte(stSendData stA)
{
int size = Marshal.SizeOf(typeof(stSendData));
byte[] bytes = new byte[size]; // StructureA 는 4Byte
IntPtr buff = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(stA, buff, true);
Marshal.Copy(buff, bytes, 0, size);
Marshal.FreeHGlobal(buff);
return bytes;
}
private stReceiveData BytesToObject(byte[] data)
{
IntPtr ptr = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, ptr, data.Length);
var obj = (stReceiveData)Marshal.PtrToStructure(ptr, typeof(stReceiveData));
Marshal.FreeHGlobal(ptr);
if (Marshal.SizeOf(obj) != data.Length)
{
return default(stReceiveData);
}
return obj;
}
// TODO: AlarmMonitor 들어 오면서 추가된 부분으로, Sequence 가 돌고 있을 때, Device 상태 체크를 하는 Alarm 을 안띄우도록 하는 로직 임.
// TODO: 수정 필요함.
public void SetReadybyAuto(bool isSeqInitialize)
{
if (isSeqInitialize) {
IsReadyStatusbyAuto = true;
Log.I($"LBAD IsReadyStatusbyAuto : {IsReadyStatusbyAuto}");
} else {
IsReadyStatusbyAuto = false;
Log.I($"LBAD IsReadyStatusbyAuto : {IsReadyStatusbyAuto}");
}
}
public bool GetReadybyAuto()
{
return IsReadyStatusbyAuto;
}
}
}