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<VisionToControlCommand, bool> _commnadAcks = new Dictionary<VisionToControlCommand, bool>();
|
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<VisionToControlCommand, bool> 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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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<byte> sendData = new List<byte>();
|
List<byte> body = new List<byte>();
|
|
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;
|
}
|
}
|
}
|