//---------------------------------------------------------------------------
// For SELMA100/200, 20180223, moon, 완료
// USB->TCP/IP
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#define MAX_RETRY_COUNT			3

#include "CommControl_Form.h"
#include "Message_Form.h"
#include "USBMessage_Form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

bool CommSimulationMode = false;
bool SvrConFlag = false; //sjm tcpip
bool TcpSndFlag = false; //sjm tcpip

TCommControlForm *CommControlForm = NULL;

//---------------------------------------------------------------------------
__fastcall TCommControlForm::TCommControlForm(TComponent* Owner)
	: TForm(Owner)
{
	activemode = ApplicationStartOption.SelectedCommType; // 1-usb all 2-hcb-usb/tcp-spb  3-tcp all
  for (int commIndex = 0; commIndex < MAX_COMM_COUNT; commIndex++)
	{
		FBusy[commIndex] = false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::Connect(int commIndex)
{
	if (activemode == 1)
	{
	AnsiString deviceName = "";
	switch (commIndex)
	{
		case COMM_HCB:
			deviceName = "\\\\.\\USBFAE_HCB_1";
			break;
		case COMM_SPB_1:
			deviceName = "\\\\.\\USBFAE_SPB_1";
			break;
		case COMM_SPB_2:
			deviceName = "\\\\.\\USBFAE_SPB_2";
			break;
		case COMM_SPB_3:
			deviceName = "\\\\.\\USBFAE_SPB_3";
			break;
		case COMM_SPB_4:
			deviceName = "\\\\.\\USBFAE_SPB_4";
			break;
	}
	if (deviceName != "")
	{
			if (!CommSimulationMode)
			{
				if(TcpConnection[commIndex].USBConnect(deviceName))
        {
				  //TcpConnection[commIndex].ProtocolCheck(commIndex);
        }
			}
		}
	}
	else if (activemode == 2) 
	{
		AnsiString deviceName = ""; // add hcbusb
		AnsiString  sIpAddr = "";
		int        nPort;
    int Index;
		switch (commIndex)
		{
			case COMM_HCB:
				deviceName = "\\\\.\\USBFAE_HCB_1";
				break;
			case COMM_SPB_1:
			case COMM_SPB_2:
			case COMM_SPB_3:
			case COMM_SPB_4:
      case COMM_SPB_5:
      case COMM_SPB_6:
      case COMM_SPB_7:
      case COMM_SPB_8:
				sIpAddr = CommParameter[commIndex].IpAddress;
				nPort = CommParameter[commIndex].TcpPort;
				break;
		}
		///// hcb usb add /////
		if (commIndex == 0)
		{
			if (deviceName != "")
			{
				if (!CommSimulationMode)
				{
					if(TcpConnection[commIndex].USBConnect(deviceName))
          {
					  //TcpConnection[commIndex].ProtocolCheck(commIndex);
          }
				}
			}
		}
		else
		{
			if (sIpAddr != "")
			{
				if (!CommSimulationMode)
				{
					if(TcpConnection[commIndex].TCPConnect(sIpAddr, nPort))
          {
					  //TcpConnection[commIndex].ProtocolCheck(commIndex);
          }
				}
			}
		}
	}
	else 
	{
		AnsiString  sIpAddr = "";
		int         nPort;

    sIpAddr = CommParameter[commIndex].IpAddress;
    nPort   = CommParameter[commIndex].TcpPort;

		if (sIpAddr != "")
		{
			if (!CommSimulationMode)
			{
				if(TcpConnection[commIndex].TCPConnect(sIpAddr, nPort))
        {
				  //TcpConnection[commIndex].ProtocolCheck(commIndex);
        }
			}
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::Disconnect(int commIndex)
{
		if (activemode == 1 || (activemode == 2 && commIndex == 0))
	{
		TcpConnection[commIndex].USBDisconnect();
	}
	else {
		TcpConnection[commIndex].TCPDisconnect();
	}
}
//---------------------------------------------------------------------------
bool __fastcall TCommControlForm::IsConnected(int commIndex)
{
	bool bConnected = false;
	if (commIndex >= 0 && commIndex < MAX_COMM_COUNT)
	{
		bConnected = TcpConnection[commIndex].Connected;
	}
	return bConnected;
}
//---------------------------------------------------------------------------
bool __fastcall TCommControlForm::Request(int commIndex, unsigned short command, void *data, unsigned int dataLength,
	void *receiveBuffer, unsigned int receiveBufferMaxSize)
{
	int result, retryCount;
	AnsiString boardName;
	if (TcpConnection[commIndex].VirtualState)
	{
		return true;
	}
	if (FBusy[commIndex])
	{
		return false;
	}
	FBusy[commIndex] = true;
	// check busy
	retryCount = 0;
retry:
	if (TcpConnection[commIndex].RequestCommand(commIndex, command, data, dataLength, receiveBuffer, receiveBufferMaxSize))
	{
		FBusy[commIndex] = false;
		return true;
	}
	else
	{
		if (TcpConnection[commIndex].IgnoreState)
		{
			FBusy[commIndex] = false;
			return false;
		}

		retryCount++;
		if (retryCount < MAX_RETRY_COUNT)
		{
			Comm_Connect(commIndex);
			goto retry;
		}
		else
		{
			FBusy[commIndex] = false;
			return false;
		}
		return false;
	}
}
//---------------------------------------------------------------------------
bool __fastcall TCommControlForm::RequestEx(int commIndex, unsigned short command, void *shortData, unsigned int shortDataLength,
	void *longData, unsigned int longDataLength, void *receiveBuffer, unsigned int receiveBufferMaxSize,
	TUSBCompletionRoutine CompletionRoutine, TOverlapIOStr *OverlapIOStr)
{
	int result, retryCount;
	AnsiString boardName;
	if (TcpConnection[commIndex].VirtualState)
	{
		return true;
	}	
	if (FBusy[commIndex])
	{
		return false;
	}
	FBusy[commIndex] = true;
	retryCount = 0;
retry:
	if (TcpConnection[commIndex].RequestCommandEx(commIndex, command, shortData, shortDataLength, longData, longDataLength,
		receiveBuffer, receiveBufferMaxSize, CompletionRoutine, OverlapIOStr))
	{
		FBusy[commIndex] = false;
		return true;
	}
	else
	{
		if (TcpConnection[commIndex].IgnoreState)
		{
			FBusy[commIndex] = false;
			return false;
		}

		retryCount++;
		if (retryCount < MAX_RETRY_COUNT)
		{
			Comm_Connect(commIndex);
			goto retry;
		}
		else
		{
			FBusy[commIndex] = false;
			return false;
		}
		return false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::SetMaxWaitingTime(int commIndex, int waitingTime)
{
	TcpConnection[commIndex].MaxWaitingTime = waitingTime;
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::SetDefaultMaxWaitingTime(int commIndex)
{
	TcpConnection[commIndex].SetDefaultMaxWaitingTime();
}
//---------------------------------------------------------------------------
bool __fastcall TCommControlForm::Recover(int commIndex)
{
	if (TcpConnection[commIndex].RecoverDevice(commIndex))
	{
		return true;
	}
	else
	{
		ShowMessageFA(TcpConnection[commIndex].GetLastErrorMessage());
		return false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::Reconnect(int commIndex)
{
	Connect(commIndex);
	CheckStatus();
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::RequestStallTest(int commIndex, int testMode)
{
	TcpConnection[commIndex].RequestStallTest(testMode);
}
//---------------------------------------------------------------------------
//	external functions
//---------------------------------------------------------------------------
void __fastcall Comm_Connect(int commIndex)
{
  if (CommControlForm != NULL)
  {
    CommControlForm->Connect(commIndex);
  }
}
//---------------------------------------------------------------------------
void __fastcall Comm_Disconnect(int commIndex)
{
  if (CommControlForm != NULL)
  {
    CommControlForm->Disconnect(commIndex);
  }
}
//---------------------------------------------------------------------------
void __fastcall Comm_ConnectAll(void)
{
	if (CommControlForm == NULL)
	{
		CommControlForm = new TCommControlForm(NULL);
		CommControlForm->Connect(COMM_HCB);
		CommControlForm->Connect(COMM_SPB_1);
		CommControlForm->Connect(COMM_SPB_2);
		CommControlForm->Connect(COMM_SPB_3);
		CommControlForm->Connect(COMM_SPB_4);
    CommControlForm->Connect(COMM_SPB_5);
    CommControlForm->Connect(COMM_SPB_6);
    CommControlForm->Connect(COMM_SPB_7);
    CommControlForm->Connect(COMM_SPB_8);
	}
}
//---------------------------------------------------------------------------
void __fastcall Comm_DisconnectAll(void)
{
	if (CommControlForm != NULL)
	{
		CommControlForm->Disconnect(COMM_HCB);
		CommControlForm->Disconnect(COMM_SPB_1);
		CommControlForm->Disconnect(COMM_SPB_2);
		CommControlForm->Disconnect(COMM_SPB_3);
		CommControlForm->Disconnect(COMM_SPB_4);
    CommControlForm->Disconnect(COMM_SPB_5);
    CommControlForm->Disconnect(COMM_SPB_6);
    CommControlForm->Disconnect(COMM_SPB_7);
    CommControlForm->Disconnect(COMM_SPB_8);
		delete CommControlForm;
		CommControlForm = NULL;

	}
}
//---------------------------------------------------------------------------
bool __fastcall Comm_IsConnected(int commIndex)
{
	if (!CommSimulationMode)
	{
	bool bConnected = false;
	if (CommControlForm != NULL)
	{
		bConnected = CommControlForm->IsConnected(commIndex);
	}
	return bConnected;
}
	else
	{
		return true;
	}
}
//---------------------------------------------------------------------------
bool __fastcall Comm_Request(int commIndex, unsigned short command, void *data, unsigned int dataLength,
	void *receiveBuffer, unsigned int receiveBufferMaxSize)
{
	return CommControlForm->Request(commIndex, command, data, dataLength, receiveBuffer, receiveBufferMaxSize);
}
//---------------------------------------------------------------------------
bool __fastcall Comm_RequestEx(int commIndex, unsigned short command, void *shortData, unsigned int shortDataLength,
	void *longData, unsigned int longDataLength, void *receiveBuffer, unsigned int receiveBufferMaxSize,
	TUSBCompletionRoutine CompletionRoutine, TOverlapIOStr *OverlapIOStr)
{
	return CommControlForm->RequestEx(commIndex, command, shortData, shortDataLength, longData, longDataLength,
		receiveBuffer, receiveBufferMaxSize, CompletionRoutine, OverlapIOStr);
}
//---------------------------------------------------------------------------
void __fastcall Comm_SetMaxWaitingTime(int commIndex, int waitingTime)
{
	CommControlForm->SetMaxWaitingTime(commIndex, waitingTime);
}
//---------------------------------------------------------------------------
void __fastcall Comm_SetDefaultMaxWaitingTime(int commIndex)
{
	CommControlForm->SetDefaultMaxWaitingTime(commIndex);
}
//---------------------------------------------------------------------------
bool __fastcall Comm_Recover(int commIndex)
{
	CommControlForm->Recover(commIndex);
}
//---------------------------------------------------------------------------
void __fastcall Comm_RequestStallTest(int commIndex, int testMode)
{
	CommControlForm->RequestStallTest(commIndex, testMode);
}
//---------------------------------------------------------------------------
void __fastcall Comm_Reconnect(int commIndex)
{
    CommControlForm->Reconnect(commIndex);
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::StatusTimerTimer(TObject *Sender)
{
	CheckStatus();
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::CheckStatus(void)
{
	if (TcpConnection[COMM_HCB].VirtualState)
	{
		HCBConnectionLabel->Font->Color = clBlue;
		HCBConnectionLabel->Caption = "-Virtual Mode-";
	}
	else if (TcpConnection[COMM_HCB].Connected)
	{
		if (TcpConnection[COMM_HCB].IgnoreState)
		{
			HCBConnectionLabel->Font->Color = clFuchsia;
			HCBConnectionLabel->Caption = "Disconnected";
		}
		else
		{
			HCBConnectionLabel->Font->Color = clLime;
			HCBConnectionLabel->Caption = "Connected";
		}
	}
	else
	{
		HCBConnectionLabel->Font->Color = clRed;
		HCBConnectionLabel->Caption = "Disconnected";
	}

	for (int spbIndex = 0; spbIndex < SYSTEM_SPB_COUNT; spbIndex++)
	{
		TLabel *connectionLabel = (TLabel *) FindComponent("SPBConnectionLabel" + IntToStr(spbIndex + 1));
		if (connectionLabel)
		{
			if (TcpConnection[COMM_SPB + spbIndex].VirtualState)
			{
				connectionLabel->Font->Color = clBlue;
				connectionLabel->Caption = "-Virtual Mode-";
			}
			else if (TcpConnection[COMM_SPB + spbIndex].Connected)
			{
				if (TcpConnection[COMM_SPB + spbIndex].IgnoreState)
				{
					connectionLabel->Font->Color = clFuchsia;
					connectionLabel->Caption = "Disconnected";
				}
				else
				{
					connectionLabel->Font->Color = clLime;
					connectionLabel->Caption = "Connected";
				}
			}
			else
			{
				connectionLabel->Font->Color = clRed;
				connectionLabel->Caption = "Disconnected";
			}
		}
	}

}
//---------------------------------------------------------------------------


void __fastcall TCommControlForm::FormCreate(TObject *Sender)
{
	CheckStatus();
}
//---------------------------------------------------------------------------

void __fastcall TCommControlForm::CloseButtonClick(TObject *Sender)
{
	this->Close();
}
//---------------------------------------------------------------------------

void __fastcall TCommControlForm::ReconnectButtonClick(TObject *Sender)
{
	TButton *theButton = (TButton *) Sender;
	int commIndex = theButton->Tag;
	Connect(commIndex);
	CheckStatus();
}
//---------------------------------------------------------------------------

void __fastcall TCommControlForm::RecoverButtonClick(TObject *Sender)
{
	TButton *theButton = (TButton *) Sender;
	int commIndex = theButton->Tag;
	Recover(commIndex);
	CheckStatus();
}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::Panel1DblClick(TObject *Sender)
{
	if (!TcpConnection[COMM_HCB].VirtualState)
	{
		if (MessageDlgFA("Want to Switch to Virtual Mode?", mtConfirmation, TMsgDlgButtons() << mbOK << mbCancel) == mrOk)
		{
			TcpConnection[COMM_HCB].VirtualState = true;
			TcpConnection[COMM_SPB_1].VirtualState = true;
			TcpConnection[COMM_SPB_2].VirtualState = true;
			TcpConnection[COMM_SPB_3].VirtualState = true;
			TcpConnection[COMM_SPB_4].VirtualState = true;
      TcpConnection[COMM_SPB_5].VirtualState = true;
      TcpConnection[COMM_SPB_6].VirtualState = true;
      TcpConnection[COMM_SPB_7].VirtualState = true;
      TcpConnection[COMM_SPB_8].VirtualState = true;
		}
	}
	else
	{
		TcpConnection[COMM_HCB].VirtualState = false;
		TcpConnection[COMM_SPB_1].VirtualState = false;
		TcpConnection[COMM_SPB_2].VirtualState = false;
		TcpConnection[COMM_SPB_3].VirtualState = false;
		TcpConnection[COMM_SPB_4].VirtualState = false;
    TcpConnection[COMM_SPB_5].VirtualState = false;
    TcpConnection[COMM_SPB_6].VirtualState = false;
    TcpConnection[COMM_SPB_7].VirtualState = false;
    TcpConnection[COMM_SPB_8].VirtualState = false;
	}
	CheckStatus();
}
//---------------------------------------------------------------------------

void __fastcall TCommControlForm::Label9DblClick(TObject *Sender)
{
	if (!TcpConnection[COMM_SPB_4].VirtualState)
	{
		if (MessageDlgFA("Want to Switch to Virtual Mode?", mtConfirmation, TMsgDlgButtons() << mbOK << mbCancel) == mrOk)
		{
			TcpConnection[COMM_SPB_4].VirtualState = true;
		}
	}
	else
	{
		TcpConnection[COMM_SPB_4].VirtualState = false;
	}
	CheckStatus();	
}
//---------------------------------------------------------------------------
//===========================================================================
//====================== SJM TCP/IP ADD  ====================================
//    ClientSocket1->Socket->SendText("ABCDEFG");    // 문자열 데이터 전송시
//
//    char    Data[10];
//    ClientSocket1->Socket->SendBuf(Data, 10);     //메모리 버퍼로 전송시
//
//    ClientSocket1->Socket->SendStream()    		//스트림으로 전송시
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
int __fastcall TCommControlForm::TxDatalength(AnsiString str)
{
	int	lng;

    lng =  str.Length();

    return lng;

}
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::TxAlarmDataToTcp(int code, AnsiString str)
{
	/*AnsiString strData;

    if(str.Length() < 1) return;
    if(SvrConFlag == false ) return;

    //ShowMessage(str);

 	//MODUS_HEAD.transaction_id1 	= 0;
    //MODUS_HEAD.transaction_id2 	= 0;
    MODUS_HEAD.protocol_id1	 	= 0;
    MODUS_HEAD.protocol_id2	 	= 0;
    MODUS_HEAD.length1			= 0;
    MODUS_HEAD.length2 			= str.Length() + 2;    //str + unit ID + FC
    MODUS_HEAD.unit_id 			= 0;

    if(code == 0)
    {
    	MODUS_HEAD.function_code	= "@";     //Error
    }
    else if(code == 1)
    {
    	MODUS_HEAD.function_code	= "A";    //Alarm
    }
    strData =  IntToStr(MODUS_HEAD.transaction_id1)
    			+IntToStr(MODUS_HEAD.transaction_id2)
    			+IntToStr(MODUS_HEAD.protocol_id1)
                +IntToStr(MODUS_HEAD.protocol_id2)
                +IntToStr(MODUS_HEAD.length1)
                +IntToStr(MODUS_HEAD.length2)
                +IntToStr(MODUS_HEAD.unit_id)
                +MODUS_HEAD.function_code
                +str;

    TCustomWinSocket *soc;
    for(int c=0;c< SOCLST->Count;c++)
    {
        soc=(TCustomWinSocket *)SOCLST->Items[c];
        if(soc->Connected)soc->SendText(strData);
    }                 */
}
/* /---------------------------------------------------------------------------
void __fastcall TCommControlForm::AlarmDataToTcp(int code, Byte acode)
{
    Byte TData[6];

    if(SvrConFlag == false ) return;

    TData[0] = 0x00;		//transaction ID
    TData[1] = 0x00;		//protocol ID
    TData[2] = 0x02;    	//Length
    TData[3] = 0x00;    	//Unit ID
    if(code == 0)
    {
    	TData[4] = 0x40;    //Function code (Packet Error)
    }
    else if(code == 1)
    {
    	TData[4] = 0x41;    //Function code (Alarm)
    }
    TData[5] = acode;		//Alarm Code

    TCustomWinSocket *soc;
    for(int c=0;c< SOCLST->Count;c++)
    {
        soc=(TCustomWinSocket *)SOCLST->Items[c];
        if(soc->Connected)soc->SendBuf(TData, 6);
    }
} */
//---------------------------------------------------------------------------
void __fastcall TCommControlForm::TxDataToTcp(AnsiString str)
{
    if(str.Length() < 1) return;
    if(SvrConFlag == false ) return;
    //ShowMessage(str.Length());

    TCustomWinSocket *soc;
    for(int c=0;c< SOCLST->Count;c++)
    {
        soc=(TCustomWinSocket *)SOCLST->Items[c];
        if(soc->Connected)soc->SendText(str);
    }
}
//---------------------------------------------------------------------------
AnsiString __fastcall BufferToHexSpace(unsigned char *Buf, int BufSize)
{
    String Result="";
    String HexStr="0x";

    if(BufSize<1)return "";

    for ( int i=0; i < BufSize -1; i++)
    {
        Result = Result + (IntToHex(Buf[i], 2)-30) ;
    }

    return Result;
}

