using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using SA_LTT.Base; using System.Collections; using System.Threading; namespace SA_LTT.Module { public enum VisionToControlCommand : short { VisionReadyAck = 150, InspReadyEnd = 151, WaferDetectionReadyAck = 250, WaferDetectionReadyEnd = 251, WaferDetectionStartAck= 252, WaferDetectionResult = 253, RecipeChangeSwitchAck = 750, RecipeChangeUpdate = 751, Alarm = 950, AliveAck = 1050, } public enum ControlToVisionCommand : short { VisionReady = 100, InspReadyEndAck = 101, WaferDetectionReady = 200, WaferDetectionReadyEndAck = 201, WaferDetectionStart = 202, WaferDetectionResultAck = 203, RecipeSwitch = 700, RecipeUpdateAck = 701, AlarmAck = 900, RequestAlive = 1000, } public class VisionControl : SocketClient { Equipment _equipment; public Queue commandlist; private bool IsDisposed = false; private string _ip = "127.000.000.1"; private int _port = 9119; private Thread communicationThread; private int retry_connect_cnt; private DateTime alive_check; private DateTime connect_time_check; private Dictionary _commnadAcks = new Dictionary(); private InspReadyEnd _inspectionReadyEndValue = new InspReadyEnd(); private WaferDetectionResult _waferDetectionResultValue = new WaferDetectionResult(); private RecipeSwitchAck _recipeSwitchAckValue = new RecipeSwitchAck(); private RecipeUpdate _recipeUpdateValue = new RecipeUpdate(); private AlarmOccured _alarmOccuredValue = new AlarmOccured(); private int _aliveAck; public int AliveAck { get { return _aliveAck; } set { _aliveAck = value; } } public Dictionary CommnadAcks { get => _commnadAcks; private set =>_commnadAcks = value; } public InspReadyEnd InspectionReadyEndValue { get => _inspectionReadyEndValue; set => _inspectionReadyEndValue = value; } public WaferDetectionResult WaferDetectionResultValue { get => _waferDetectionResultValue; set => _waferDetectionResultValue = value; } public RecipeSwitchAck RecipeSwitchAckValue { get => _recipeSwitchAckValue; set => _recipeSwitchAckValue = value; } public RecipeUpdate RecipeUpdateValue { get => _recipeUpdateValue; set => _recipeUpdateValue = value; } public AlarmOccured AlarmOccuredValue { get => _alarmOccuredValue; set => _alarmOccuredValue = value; } public VisionControl(Equipment equipment) { _equipment = equipment; ChangeAddress(IPAddress.Parse("127.000.000.1"), 9119); alive_check = DateTime.Now; connect_time_check = DateTime.Now; foreach(VisionToControlCommand value in Enum.GetValues(typeof(VisionToControlCommand))) { CommnadAcks.Add(value, false); } Add_received_event(Received); commandlist = new Queue(); communicationThread = new Thread(CommandTrigger); communicationThread.Start(); } public new bool Connect() { try { if (base.Connect()) { Thread.Sleep(50); if (isConnected) { alive_check = DateTime.Now; return true; } else { return false; } } else { return false; } } catch (Exception ex) { return false; } } public void CommandTrigger() { DateTime heartBeatTime = DateTime.Now; while (!_equipment.IsDisposed) { try { Thread.Sleep(10); if (commandlist.Count > 0) { byte[] recvData = (byte[])commandlist.Dequeue(); byte[] size = new byte[4]; byte[] bcode = new byte[2]; Array.Copy(recvData, size, size.Length); Array.Copy(recvData, 4, bcode, 0, bcode.Length); short code = BitConverter.ToInt16(bcode, 0); switch (code) { case (short)VisionToControlCommand.VisionReadyAck: { SendInspReadyEndAck(); break; } case (short)VisionToControlCommand.InspReadyEnd: { RecvInspReadyEnd(recvData, out _inspectionReadyEndValue); break; } case (short)VisionToControlCommand.WaferDetectionReadyAck: { break; } case (short)VisionToControlCommand.WaferDetectionReadyEnd: { SendInspReadyEndAck(); break; } case (short)VisionToControlCommand.WaferDetectionStartAck: { break; } case (short)VisionToControlCommand.WaferDetectionResult: { RecvWaferDetectionResult(recvData, out _waferDetectionResultValue); SendWaferDetectionResultAck(); break; } case (short)VisionToControlCommand.RecipeChangeSwitchAck: { RecvRecipeSwitchAck(recvData, out _recipeSwitchAckValue); break; } case (short)VisionToControlCommand.RecipeChangeUpdate: { RecvRecipeUpdate(recvData, out _recipeUpdateValue); break; } case (short)VisionToControlCommand.Alarm: { RecvAlarm(recvData, out _alarmOccuredValue); break; } case (short)VisionToControlCommand.AliveAck: { AliveAck aliveAck; RecvAliveAck(recvData, out aliveAck); AliveAck = aliveAck.Run; break; } default: break; } alive_check = DateTime.Now; if (CommnadAcks.ContainsKey((VisionToControlCommand)code)) { CommnadAcks[(VisionToControlCommand)code] = true; } } else { if((DateTime.Now - heartBeatTime).TotalSeconds > _equipment.settingParameterManager.SettingParameter.VisionHeartBeatTimeOut - 0.5) { SendRequestAlive(); heartBeatTime = DateTime.Now; } } if ((DateTime.Now - alive_check).TotalSeconds > _equipment.settingParameterManager.SettingParameter.VisionHeartBeatTimeOut) { if (isConnected) { Disconnect(); continue; } } if (isConnected == false) { if ((DateTime.Now - connect_time_check).TotalSeconds > 3) { if (Connect()) { retry_connect_cnt = 0; } else { if (retry_connect_cnt > 3) { //Alarm. } retry_connect_cnt++; } connect_time_check = DateTime.Now; } } } catch (Exception ex) { } } } public void Received(object sender, ReceiveEventArgs events) { byte[] data = new byte[events.stateobject.Received_data.Length]; Array.Copy(events.stateobject.buffer, data, data.Length); //=============================================== ArrayList recvList = new ArrayList(); byte[] data1; byte[] data2; while (true) { bool check = RecvData(data, out data1, out data2); if (check) { if (data1 != null) recvList.Add(data1); break; } else { recvList.Add(data1); data = data2; } } //=============================================== foreach (byte[] commands in recvList) { commandlist.Enqueue(commands); } } private bool RecvData(byte[] recvData, out byte[] Data1, out byte[] Data2) { try { ArrayList list = new ArrayList(); byte[] data = new byte[recvData.Length]; Array.Copy(recvData, data, data.Length); byte[] bsize = new byte[4]; Array.Copy(data, bsize, bsize.Length); int size = BitConverter.ToInt32(bsize, 0) + 6; if (recvData.Length > size) { Data1 = new byte[size]; Array.Copy(recvData, Data1, Data1.Length); Data2 = new byte[recvData.Length - size]; Array.Copy(recvData, Data1.Length, Data2, 0, Data2.Length); return false; } else if (recvData.Length == size) { Data1 = new byte[size]; Array.Copy(recvData, Data1, Data1.Length); Data2 = null; return true; } else { Data1 = recvData; Data2 = null; return true; } } catch (Exception ex) { Data1 = null; Data2 = null; return true; } } public bool SendVisionReady(string recipeName) { List sendData = new List(); List body = new List(); byte[] sendRecipeName = new byte[20]; Array.Copy(Encoding.ASCII.GetBytes(recipeName), sendRecipeName, recipeName.Length); body.InsertRange(body.Count, sendRecipeName); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.VisionReady)); sendData.InsertRange(sendData.Count, body); CommnadAcks[VisionToControlCommand.VisionReadyAck] = false; CommnadAcks[VisionToControlCommand.InspReadyEnd] = false; return SendData(sendData.ToArray()); } public bool SendInspReadyEndAck() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.InspReadyEndAck)); sendData.InsertRange(sendData.Count, body); return SendData(sendData.ToArray()); } public bool SendWaferDetectionReady() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.WaferDetectionReady)); sendData.InsertRange(sendData.Count, body); CommnadAcks[VisionToControlCommand.WaferDetectionReadyAck] = false; CommnadAcks[VisionToControlCommand.WaferDetectionReadyEnd] = false; return SendData(sendData.ToArray()); } public bool SendWaferDetectionReadyEndAck() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.WaferDetectionReadyEndAck)); sendData.InsertRange(sendData.Count, body); return SendData(sendData.ToArray()); } public bool SendWaferDetectionStart() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.WaferDetectionStart)); sendData.InsertRange(sendData.Count, body); CommnadAcks[VisionToControlCommand.WaferDetectionStartAck] = false; CommnadAcks[VisionToControlCommand.WaferDetectionResult] = false; return SendData(sendData.ToArray()); } public bool SendWaferDetectionResultAck() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.WaferDetectionResultAck)); sendData.InsertRange(sendData.Count, body); return SendData(sendData.ToArray()); } public bool SendRecipeSwitch(string recipeName) { List sendData = new List(); List body = new List(); byte[] sendRecipeName = new byte[20]; Array.Copy(Encoding.ASCII.GetBytes(recipeName), sendRecipeName, recipeName.Length); body.InsertRange(body.Count, sendRecipeName); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.RecipeSwitch)); sendData.InsertRange(sendData.Count, body); CommnadAcks[VisionToControlCommand.RecipeChangeSwitchAck] = false; CommnadAcks[VisionToControlCommand.RecipeChangeUpdate] = false; return SendData(sendData.ToArray()); } public bool SendRecipeUpdateAck() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.RecipeUpdateAck)); sendData.InsertRange(sendData.Count, body); return SendData(sendData.ToArray()); } public bool SendAlarmAck() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.AlarmAck)); sendData.InsertRange(sendData.Count, body); CommnadAcks[VisionToControlCommand.Alarm] = false; return SendData(sendData.ToArray()); } public bool SendRequestAlive() { List sendData = new List(); List body = new List(); sendData.InsertRange(sendData.Count, BitConverter.GetBytes(body.Count)); sendData.InsertRange(sendData.Count, BitConverter.GetBytes((short)ControlToVisionCommand.RequestAlive)); sendData.InsertRange(sendData.Count, body); CommnadAcks[VisionToControlCommand.AliveAck] = false; return SendData(sendData.ToArray()); } private new bool SendData(byte[] data) { try { if (isConnected) { string str = string.Empty; foreach (byte bt in data) { str += $"{bt} "; } return base.SendData(data); } else { return false; } } catch (Exception ex) { return false; } } //================================================================= private void RecvInspReadyEnd(byte[] recvData, out InspReadyEnd value) { byte[] size = new byte[4]; byte[] command = new byte[2]; byte[] recipeName = new byte[20]; int copylength = 0; Array.Copy(recvData, size, size.Length); copylength += size.Length; Array.Copy(recvData, copylength, command, 0, command.Length); copylength += command.Length; Array.Copy(recvData, copylength, recipeName, 0, recipeName.Length); copylength += recipeName.Length; string resultRecipeName = BitConverter.ToString(recipeName, 0); value = new InspReadyEnd(resultRecipeName); } private void RecvWaferDetectionResult(byte[] recvData, out WaferDetectionResult value) { byte[] size = new byte[4]; byte[] command = new byte[2]; byte[] byteResult = new byte[4]; byte[] byteResultX = new byte[8]; byte[] byteResultY = new byte[8]; byte[] byteResultT = new byte[8]; int copylength = 0; Array.Copy(recvData, size, size.Length); copylength += size.Length; Array.Copy(recvData, copylength, command, 0, command.Length); copylength += command.Length; Array.Copy(recvData, copylength, byteResult, 0, byteResult.Length); copylength += byteResult.Length; Array.Copy(recvData, copylength, byteResultX, 0, byteResultX.Length); copylength += byteResultX.Length; Array.Copy(recvData, copylength, byteResultY, 0, byteResultY.Length); copylength += byteResultY.Length; Array.Copy(recvData, copylength, byteResultT, 0, byteResultT.Length); copylength += byteResultT.Length; int result = BitConverter.ToInt32(byteResult, 0); double resultX = BitConverter.ToDouble(byteResultX, 0); double resultY = BitConverter.ToDouble(byteResultY, 0); double resultT = BitConverter.ToDouble(byteResultT, 0); resultY = -resultY; value = new WaferDetectionResult(result, resultX, resultY, resultT); } private void RecvRecipeSwitchAck(byte[] recvData, out RecipeSwitchAck value) { byte[] size = new byte[4]; byte[] command = new byte[2]; byte[] byteResult = new byte[4]; int copylength = 0; Array.Copy(recvData, size, size.Length); copylength += size.Length; Array.Copy(recvData, copylength, command, 0, command.Length); copylength += command.Length; Array.Copy(recvData, copylength, byteResult, 0, byteResult.Length); copylength += byteResult.Length; int result = BitConverter.ToInt32(byteResult, 0); value = new RecipeSwitchAck(result); } private void RecvRecipeUpdate(byte[] recvData, out RecipeUpdate value) { byte[] size = new byte[4]; byte[] command = new byte[2]; byte[] recipeName = new byte[20]; int copylength = 0; Array.Copy(recvData, size, size.Length); copylength += size.Length; Array.Copy(recvData, copylength, command, 0, command.Length); copylength += command.Length; Array.Copy(recvData, copylength, recipeName, 0, recipeName.Length); copylength += recipeName.Length; string resultRecipeName = BitConverter.ToString(recipeName, 0); value = new RecipeUpdate(resultRecipeName); } private void RecvAlarm(byte[] recvData, out AlarmOccured value) { byte[] size = new byte[4]; byte[] command = new byte[2]; byte[] byteAlarmCode = new byte[4]; int copylength = 0; Array.Copy(recvData, size, size.Length); copylength += size.Length; Array.Copy(recvData, copylength, command, 0, command.Length); copylength += command.Length; Array.Copy(recvData, copylength, byteAlarmCode, 0, byteAlarmCode.Length); copylength += byteAlarmCode.Length; int alarmCode = BitConverter.ToInt32(byteAlarmCode, 0); value = new AlarmOccured(alarmCode); } private void RecvAliveAck(byte[] recvData, out AliveAck value) { byte[] size = new byte[4]; byte[] command = new byte[2]; byte[] byteResult = new byte[4]; int copylength = 0; Array.Copy(recvData, size, size.Length); copylength += size.Length; Array.Copy(recvData, copylength, command, 0, command.Length); copylength += command.Length; Array.Copy(recvData, copylength, byteResult, 0, byteResult.Length); copylength += byteResult.Length; int result = BitConverter.ToInt32(byteResult, 0); value = new AliveAck(result); } } public struct VisionReadyAck { public int result { get; private set; } public VisionReadyAck(int result = 0) { this.result = result; } } public struct InspReadyEnd { public string RecipeName { get; private set; } public InspReadyEnd(string recipeName) { this.RecipeName = recipeName; } } public struct WaferDetectionResult { public int Result { get; private set; } public double ResultX { get; private set; } public double ResultY { get; private set; } public double ResultT { get; private set; } public WaferDetectionResult(int result, double resultX, double resultY, double resultT) { this.Result = result; this.ResultX = resultX; this.ResultY = resultY; this.ResultT = resultT; } } public struct RecipeSwitchAck { public int Result { get; private set; } public RecipeSwitchAck(int result) { this.Result = result; } } public struct RecipeUpdate { public string RecipeName { get; private set; } public RecipeUpdate(string recipeName) { this.RecipeName = recipeName; } } public struct AlarmOccured { public int AlarmCode { get; private set; } public AlarmOccured(int alarmCode) { this.AlarmCode = alarmCode; } } public struct AliveAck { public int Run { get; private set; } public AliveAck(int run) { this.Run = run; } } }