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 lsResultdata; public LBAD_PILOT(string deviceid, bool isSimul) : base(deviceid, isSimul) { IsSimul = isSimul; lsResultdata = new List(); } public int Open(LBADConfig Config) { if (Config == null) { return -1; } if (Config.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 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 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; } } }