
//---------------------------------------------------------------------------
#include "AppGlobalF.h"
#include "DMCOMMF.h"
#include "VmsDataTypeF.h"
#include "FrmSysLogF.h"

#ifdef RUN_SERVER
    #include "VMSSThread.h"
#endif
#ifdef RUN_CLIENT
    #include "VMSCThread.h"
#endif

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TDMCOMM *DMCOMM;
//---------------------------------------------------------------------------
__fastcall TDMCOMM::TDMCOMM(TComponent* Owner)
	: TDataModule(Owner)
{
    FProcessStateMin = -1;
    FEquipStateMin   = -1;
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::DataModuleCreate(TObject *Sender)
{
//
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::DataModuleDestroy(TObject *Sender)
{
//
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::SetErrorString(String AErrorString)
{
    FErrorString = AErrorString;
    FDbLog->LogWrite(NULL, eLOG_ERROR, AnsiString(FErrorString).c_str());
    LERROR(AnsiString(FErrorString).c_str());
}
//---------------------------------------------------------------------------

int TDMCOMM::LogWrite(int ALogKind, char *AFmt, ...)
{
    va_list     ap;
    int         cnt = 0;
    char        szFmtData[MAX_LOG_BUFFER];
    AnsiString  sLogKind;
    int         nStep = 0;

    bool bLog = false;
    switch(ALogKind)
    {
    case eLOG_INFO   : bLog = g_LogCfg.Info;    sLogKind = " [INF] "; break;
    case eLOG_DATA   : bLog = g_LogCfg.Data;    sLogKind = " [DAT] "; break;
    case eLOG_ERROR  : bLog = g_LogCfg.Error;   sLogKind = " [ERR] "; break;
    case eLOG_WARNING: bLog = g_LogCfg.Warning; sLogKind = " [WAN] "; break;
    case eLOG_DEBUG  : bLog = g_LogCfg.Debug;   sLogKind = " [DBG] "; break;
    case eLOG_DETAIL : bLog = g_LogCfg.Detail;  sLogKind = " [DET] "; break;
    }
    if (!bLog) return -1;

    try
    {
        va_start(ap, AFmt);
        cnt = vsprintf(szFmtData, AFmt, ap);
        va_end(ap);

        nStep = 1;
        ITSLog->LogWrite(NULL, ALogKind, szFmtData);

        nStep = 2;
        //IPC_LOG_MESSAGE *pLog = new IPC_LOG_MESSAGE;
        IPC_LOG_MESSAGE *pLog = &FLogMsg;//(IPC_LOG_MESSAGE *)malloc(sizeof(IPC_LOG_MESSAGE));
        if (pLog)
        {
            pLog->Kind = ALogKind;
            pLog->Flag = 0;
            pLog->Len  = strlen(szFmtData);
            pLog->Tm   = Now();
            memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
            sprintf(pLog->Msg, "%sDCOM %s", sLogKind.c_str(), szFmtData);

        	DWORD   dwResult = 0;
            LRESULT lResult = SEND_LOGMSG(FrmSysLog->Handle, WM_LOG_DISPLAY, pLog, NULL, SMTO_NORMAL, 2000, dwResult);
            if (lResult == 0)
            {
                dwResult = GetLastError();
                if (dwResult == ERROR_TIMEOUT)
                {
                }
                //SAFE_DELETE(pLog);
            }
        }
    }
    catch(Exception &e)
    {
        LERROR("LogWrite: %d", nStep);
    }
    return cnt;
}
//---------------------------------------------------------------------------

bool __fastcall TDMCOMM::DbConnect(String AConnStr)
{
    bool bResult = false;

	try
    {
        //DbClose();

        FDbConn = new TADOConnection(NULL);
        if (!FDbConn) return false;

        FDbConn->ConnectionTimeout = 10;
        FDbConn->ConnectionString  = AConnStr;
        FDbConn->KeepConnection	   = true;
        FDbConn->LoginPrompt       = false;
        FDbConn->Open();
        bResult = true;
    }
    catch(EDatabaseError &E)
    {
        ErrorString = String(E.ClassName()) + E.Message;
        DBERRORLOG("DbConnect", String(E.ClassName()), E.Message, AConnStr);
    }
    catch (Exception &exception)
    {
        ErrorString = String(exception.ClassName()) + exception.Message;
        DBERRORLOG("DbConnect", String(exception.ClassName()), exception.Message, AConnStr);
    }
    return bResult;
}
//---------------------------------------------------------------------------

bool __fastcall TDMCOMM::DbClose()
{
    bool bResult = false;

	try
    {
        if (!FDbConn) return false;

        if (FDbConn->Connected)
        {
            FDbConn->Close();
            FDbConn->Connected = false;
        }
        delete FDbConn;
        FDbConn = NULL;
        bResult = true;
    }
    catch(EDatabaseError &E)
    {
        ErrorString = String(E.ClassName()) + E.Message;
        DBERRORLOG("DbClose", String(E.ClassName()), E.Message, " ");
    }
    catch (Exception &exception)
    {
        ErrorString = String(exception.ClassName()) + exception.Message;
        DBERRORLOG("DbClose", String(exception.ClassName()), exception.Message, " ");
    }
    return bResult;
}
//---------------------------------------------------------------------------

bool __fastcall TDMCOMM::SQLText(TADOQuery *adoQry, String sQry, bool AReadOnly/*=true*/)
{
    try
    {
        adoQry->Close();
        adoQry->SQL->Text = sQry;
        if (AReadOnly)
        {
            adoQry->CursorType = ctOpenForwardOnly;
            adoQry->LockType   = ltReadOnly;
            adoQry->DisableControls();
        }
        return true;
    }
    catch(EDatabaseError &E)
    {
        ErrorString = String(E.ClassName()) + E.Message;
        DBERRORLOG("SQLText", String(E.ClassName()), E.Message, sQry);
    }
    catch (Exception &exception)
    {
        ErrorString = String(exception.ClassName()) + exception.Message;
        DBERRORLOG("SQLText", String(exception.ClassName()), exception.Message, sQry);
    }
    return false;
}
//---------------------------------------------------------------------------

bool __fastcall TDMCOMM::SQLBind(TADOQuery *adoQry, String param, String var)
{
    try
    {
        adoQry->Parameters->ParamByName(param)->Value = var;
        return true;
    }
    catch(EDatabaseError &E)
    {
        ErrorString = String(E.ClassName()) + E.Message;
        DBERRORLOG("SQLBind", String(E.ClassName()), E.Message, adoQry->SQL->Text);
    }
    catch (Exception &exception)
    {
        ErrorString = String(exception.ClassName()) + exception.Message;
        DBERRORLOG("SQLBind", String(exception.ClassName()), exception.Message, adoQry->SQL->Text);
    }
    return false;
}
//---------------------------------------------------------------------------

bool __fastcall TDMCOMM::SQLClose(TADOQuery *adoQry)
{
    try
    {
        if (adoQry->Active)
        {
            adoQry->Recordset->Close();
            adoQry->Close();
            adoQry->Active = false;
        }
        adoQry->SQL->Clear();
        return true;
    }
    catch(EDatabaseError &E)
    {
        ErrorString = String(E.ClassName()) + E.Message;
        DBERRORLOG("SQLClose", String(E.ClassName()), E.Message, adoQry->SQL->Text);
    }
    catch (Exception &exception)
    {
        ErrorString = String(exception.ClassName()) + exception.Message;
        DBERRORLOG("SQLClose", String(exception.ClassName()), exception.Message, adoQry->SQL->Text);
    }
    return false;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SQLOpen(TADOQuery *adoQry)
{
    try
    {
        adoQry->Open();
        adoQry->First();
        return adoQry->RecordCount;
    }
    catch(EDatabaseError &E)
    {
        ErrorString = String(E.ClassName()) + E.Message;
        DBERRORLOG("SQLOpen", String(E.ClassName()), E.Message, adoQry->SQL->Text);
    }
    catch (Exception &exception)
    {
        ErrorString = String(exception.ClassName()) + exception.Message;
        DBERRORLOG("SQLOpen", String(exception.ClassName()), exception.Message, adoQry->SQL->Text);
    }
    return -1;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SQLExec(TADOQuery *adoQry)
{
    try
    {
        adoQry->ExecSQL();
        return adoQry->RowsAffected;
    }
    catch(EDatabaseError &E)
    {
        ErrorString = String(E.ClassName()) + E.Message;
        DBERRORLOG("SQLExec", String(E.ClassName()), E.Message, adoQry->SQL->Text);
    }
    catch (Exception &exception)
    {
        ErrorString = String(exception.ClassName()) + exception.Message;
        DBERRORLOG("SQLExec", String(exception.ClassName()), exception.Message, adoQry->SQL->Text);
    }
    return -1;
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::DbState(bool AFlag)
{
	if (AFlag)
    {
        SendMessage((HWND)g_AppCfg.lMainWinHandle, WM_USER, WM_DATABASE_OPEN, 0);
    }
    else
    {
        SendMessage((HWND)g_AppCfg.lMainWinHandle, WM_USER, WM_DATABASE_CLOSE, 0);
        LERROR("Database Error");
    }
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::TcpClientDisconnect(TObject *Sender)
{
#ifdef RUN_SERVER
    try
    {
        TCustomIpClient *pClientSocket = (TCustomIpClient*)Sender;
        AnsiString sRemoteHost = pClientSocket->RemoteHost;
        int        nRemotePort = pClientSocket->RemotePort.ToIntDef(0);
        LINFO("VMS Client Disconnect: %s.%d", sRemoteHost.c_str(), nRemotePort);
    }
    catch(Exception &e)
    {
    }
#endif
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::TcpServerGetThread(TObject *Sender, TClientSocketThread *&ClientSocketThread)
{
#ifdef RUN_SERVER
    TVmsCtlr        *pObj          = NULL;
    TCustomIpClient *pClientSocket = NULL;

    try
    {
        pClientSocket = new TCustomIpClient(NULL);
        //pClientSocket->OnDisconnect = TcpClientDisconnect;

        TcpServer->ServerSocketThread->ServerSocket->Accept(pClientSocket);

		pObj = FindVms(pClientSocket->RemoteHost, pClientSocket->RemotePort.ToIntDef(0));

        AnsiString sRemoteHost = pClientSocket->RemoteHost;
        int        nRemotePort = pClientSocket->RemotePort.ToIntDef(0);

    	LINFO("TCP Client connect request: %s.%d", sRemoteHost.c_str(), nRemotePort);

		if (!pObj)
        {
            LERROR("Unknown VMS Client connect request: %s.%d [socket closed]", sRemoteHost.c_str(), nRemotePort);
            ClientSocketThread = new TClientSocketThread(TcpServer->ServerSocketThread);
            ClientSocketThread->Terminate();
            pClientSocket->Close();
            delete pClientSocket;
            return;
        }

    	LINFO("%s VMS Client connect: %s.%d", pObj->VmsId.c_str(), sRemoteHost.c_str(), nRemotePort);
		ClientSocketThread = new TVMSSThread(TcpServer->ServerSocketThread, pClientSocket, (int)pObj, &pObj->Server.ActiveIndicator);
    }
    catch(Exception &e)
    {
        ClientSocketThread = NULL;
    	LERROR("TCP Client connect request exception: %s", e.Message.c_str());
    }

	pObj->Server.pThread = ClientSocketThread;

	if (pObj->Server.pThread == NULL)
    {
		pObj->Server.Status = process_fail;
    }
    else
	{
		pObj->Server.Status = process_run;
    }
	pObj->ChangeDate = Now().FormatString("yyyymmddhhnnss");
#endif
}
//---------------------------------------------------------------------------

TVmsCtlr* __fastcall TDMCOMM::FindVms(AnsiString AIpAddress, int APort)
{
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;

        if (pObj->IpAddress.AnsiCompare(AIpAddress) == 0)
        {
            if (pObj->Server.ActiveIndicator)
            {
                /* 기존 연결 해제 */
                LWARN("Already connected client: %s %s [closed].", pObj->VmsId.c_str(), AIpAddress.c_str());
                ControlVms(pObj, false);
            }
            return pObj;
        }
    }

    return NULL;
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::TerminateVms(void)
{
#ifdef RUN_SERVER
    int i;
	TVMSSThread *pVMSSThread;
    DWORD dwWaitResult;

    LINFO("TerminateVms start");
    if (TcpServer->Active)
    {
		TcpServer->Close();
    }
    LINFO("TerminateVms end");

    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;

        if (pObj->Server.ActiveIndicator)
        {
            ControlVms(pObj, false);
        }
    }
#endif
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::ControlVms(TVmsCtlr *AObj, bool ACreate)
{
#ifdef RUN_SERVER
	TVMSSThread *pVMSSThread;
    DWORD        dwWaitResult;

	if (!AObj) return;

	if (AObj->Server.UseFlag != bit_enable) return;

	if (ACreate) return;

    AObj->Server.Status = process_stop;
    AObj->ChangeDate    = Now().FormatString("yyyymmddhhnnss");

    if (AObj->Server.pThread         != NULL &&
        AObj->Server.ActiveIndicator == true )
    {
        try
        {
            pVMSSThread = (TVMSSThread *)AObj->Server.pThread;
            //pVMSSThread->Terminate();
            pVMSSThread->FDupClose = true;
            //Sleep(500);
            dwWaitResult = CommUtil_WaitThreadTerm(pVMSSThread->ThreadID, (HANDLE)pVMSSThread->Handle, WAIT_THREAD_TERMINATE_TIME);
            if (dwWaitResult == STILL_ACTIVE)
            {
                LERROR("VMS thread terminate fail: %s", AObj->VmsId.c_str());
            }

            AObj->Server.pThread = NULL;
        }
        catch(Exception &e)
        {
        }
    }
#endif
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::MonitoringVms(bool ServerRun)
{
#ifdef RUN_SERVER
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        if (pObj->Server.UseFlag != bit_enable) continue;

        switch(pObj->Server.Status)
        {
        case process_fail:
            break;
        case process_run:
            if (pObj->Server.pThread == NULL)
            {
                pObj->Server.Status = process_fail;
                pObj->ChangeDate    = Now().FormatString("yyyymmddhhnnss");
            }
            else
            {
                if (!pObj->Server.ActiveIndicator)
                {
                    pObj->Server.pThread = NULL;
                    pObj->Server.Status  = process_fail;
                    pObj->ChangeDate     = Now().FormatString("yyyymmddhhnnss");
                }
            }
            break;
        case process_stop:
            break;
        }
    }

	if (ServerRun)
	{
		try
		{
			if (!TcpServer->Active)
			{
				TcpServer->LocalPort = g_AppCfg.comm.nListenPort;
				TcpServer->BlockMode = bmThreadBlocking;

                int nReqThreadCacheSize = VMS_MAX_DEVICE + 10;
                int nThreadCacheSize = TcpServer->ServerSocketThread->ThreadCacheSize;
                if (nThreadCacheSize < nReqThreadCacheSize)
                {
                    TcpServer->ServerSocketThread->ThreadCacheSize = nReqThreadCacheSize;
                }
				//TcpServer->ServerSocketThread->ThreadCacheSize = VMS_MAX_DEVICE;

                //서버소켓 리슨 시작
				TcpServer->Open();

                nThreadCacheSize = TcpServer->ServerSocketThread->ThreadCacheSize;
			}
		}
		catch(Exception &e)
		{
		}
 	}
#endif
}
//---------------------------------------------------------------------------

#ifdef RUN_CLIENT
void __fastcall TDMCOMM::TerminateVmsClient(TVmsCtlr *AObj)
{
	TVMSCThread *pVMSCThread;
    DWORD        dwWaitResult;

	if (AObj == NULL || AObj->Client.UseFlag != bit_enable) return;


    AObj->Client.Status = process_stop;

    if ((AObj->Client.pThread         != NULL) &&
        (AObj->Client.ActiveIndicator == true))
    {
        try
        {
            pVMSCThread = (TVMSCThread *)AObj->Client.pThread;
            //pVMSCThread->Terminate();
            pVMSCThread->FUserTerm = true;
            //Sleep(500);
            dwWaitResult = CommUtil_WaitThreadTerm(pVMSCThread->ThreadID, (HANDLE)pVMSCThread->Handle, WAIT_THREAD_TERMINATE_TIME);
            if (dwWaitResult == STILL_ACTIVE)
            {
                LERROR("VMS thread terminate fail: %s", AObj->VmsId.c_str());
            }

            AObj->Client.pThread = NULL;
        }
        catch(Exception &e)
        {
        }

#ifndef RUN_SERVER
        AObj->ChangeDate    = Now().FormatString("yyyymmddhhnnss");
#endif
    }
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::TerminateVmsClient(void)
{
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;

        if (pObj->Server.ActiveIndicator)
        {
            TerminateVmsClient(pObj);
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::ControlVmsClient(TVmsCtlr *AObj, bool ACreate)
{
	TVMSCThread *pVMSCThread;
    DWORD        dwWaitResult;

	if (AObj == NULL || AObj->Client.UseFlag != bit_enable) return;

    //실행중이면 종료
    TerminateVmsClient(AObj);

    if (ACreate)
    {
        //VMS 제어기 접속 스레드 생성
        pVMSCThread = new TVMSCThread(true, (int)AObj, &AObj->Client.ActiveIndicator);
        AObj->Client.pThread = pVMSCThread;
        if (AObj->Client.pThread == NULL)
        {
            AObj->Client.Status = process_fail;
        }
        else
        {
            AObj->Client.wTimer = Now();
        }
        //LINFO("VMS Connect Thread create: %s", AObj->VmsId.c_str());
    }
}
//---------------------------------------------------------------------------

void __fastcall TDMCOMM::MonitoringVmsClient(bool ServerRun)
{
LDEBUG("MonitoringVmsClient");
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        if (pObj->Client.UseFlag != bit_enable) continue;

        switch(pObj->Client.Status)
        {
        case process_fail:
            if (ServerRun)
            {
#if 0
                //서버는 기동중인데 클라이언트 WatchDog Timer가 제어기 연결대기 시간보다 길경우
                //제어기접속 클라이언트스레드를 기동시킨다.
                if (CommUtil_TimeDiff(pObj->Client.wTimer) > g_AppCfg.comm.nConnectWait)
                {
                    ControlVmsClient(pObj, true);
                }
#else
                if ((pObj->Client.pThread         == NULL) ||
                    (pObj->Client.ActiveIndicator != true))
                {
                    ControlVmsClient(pObj, true);
                }
#endif
            }
            break;
        case process_run:
            if (pObj->Client.pThread == NULL)
            {
                pObj->Client.Status = process_fail;
#ifndef RUN_SERVER
                pObj->ChangeDate    = Now().FormatString("yyyymmddhhnnss");
#endif
            }
            else
            {
                if (!pObj->Client.ActiveIndicator)
                {
                    pObj->Client.pThread = NULL;
                    pObj->Client.Status  = process_fail;
#ifndef RUN_SERVER
                    pObj->ChangeDate     = Now().FormatString("yyyymmddhhnnss");
#endif
                }
            }
            break;
        case process_stop:
            break;
        }
    }
}
//---------------------------------------------------------------------------
#endif

int __fastcall TDMCOMM::GetDbSysdate()
{
	int         nResult;
	AnsiString  sQry;
    TADOQuery  *pADO = NULL;
    AnsiString  sSysDate = Now().FormatString("yyyymmddhhnnss");

	nResult = VERR_OTHER;

    LDEBUG("GetDbSysdate: Start");
	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            sQry = "SELECT TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') AS S_DATE  \r\n"
                   "  FROM DUAL                                            \r\n";

            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

			for( ; !pADO->Eof; pADO->Next())
			{
                sSysDate = pADO->FieldByName("S_DATE")->AsString;
                break;
			}

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            ErrorString = String(E.ClassName()) + E.Message;
		}
		catch(Exception &e)
		{
            ErrorString = String(e.ClassName()) + e.Message;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}
    LINFO("GetDbSysdate: %s", sSysDate.c_str());
	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetProcessInfo()
{
	int         nResult;
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

	nResult = VERR_OTHER;

    LDEBUG("GetProcessInfo: Start");
	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            sQry = "SELECT SYST_ID, SYST_TYPE,   \r\n"
                   "       SYST_IP_1, PRGM_PORT  \r\n"
                   "  FROM TB_UNIT_SYST          \r\n"
                   " WHERE DEL_YN = 'N'          \r\n"
                   " ORDER BY SYST_ID            \r\n";

            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString sProcessId = pADO->FieldByName("SYST_ID")->AsString;
                AnsiString sSystemTp  = pADO->FieldByName("SYST_TYPE")->AsString;
                AnsiString sIpAddress = pADO->FieldByName("SYST_IP_1")->AsString;
                AnsiString sUdpPort   = pADO->FieldByName("PRGM_PORT")->AsString;

                if (g_AppCfg.sSystemId == sProcessId)
                {
                    //자기자신은 목록에 추가하지 않는다...
                    //g_AppCfg.comm.nCenterPort = sUdpPort.ToIntDef(g_AppCfg.comm.nCenterPort);
                    continue;
                }
                if (VComm_AddProcess(sProcessId, sSystemTp, sIpAddress, sUdpPort) >= 0)
                {
                    if ("UOT" == sSystemTp)
                    {
                        int nPort = sUdpPort.ToIntDef(0);
                        VComm_AddProcess(sProcessId, sSystemTp, sIpAddress, AnsiString(nPort+1));
                    }
                }
                nSelCnt++;
			}

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            ErrorString = String(E.ClassName()) + E.Message;
		}
		catch(Exception &e)
		{
            ErrorString = String(e.ClassName()) + e.Message;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    LINFO("GetProcessInfo: %d", nSelCnt);

	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetFontInfo()
{
    String     sQry;
    TADOQuery *pADO = NULL;

    LDEBUG("GetFontInfo: Start");

    try
    {
        FontManager->FLists.Lock();
        FontManager->FLists.RemoveAll();
    }
    __finally
    {
        FontManager->FLists.UnLock();
    }

    sQry = "SELECT VMS_FONT_SHPE_CD AS CD,   \r\n"
           "       VMS_FONT_SHPE_NM AS NM,   \r\n"
           "       EDTN_CD                   \r\n"
           "  FROM TB_VMS_FONT_SHPE          \r\n"
           " ORDER BY CD ASC                 \r\n";
    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                int        FontCode = pADO->FieldByName("CD")->AsInteger;
                AnsiString FontName = pADO->FieldByName("NM")->AsString.Trim();

				TCDSFont *pObj = new TCDSFont();

                pObj->FontCode = FontCode;
                pObj->FontName = FontName;

				FontManager->FLists.Push(pObj->FontCode, pObj);
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    LINFO("GetFontInfo: %d EA", FontManager->FLists.Size());

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetVmsInfo()
{
    String     sQry;
    TADOQuery *pADO = NULL;

    LDEBUG("GetVmsInfo: Start");

    try
    {
        VmsManager->FLists.Lock();
        VmsManager->FLists.RemoveAll();
    }
    __finally
    {
        VmsManager->FLists.UnLock();
    }

#if 0
    sQry = "SELECT A.*,                                        \r\n"
           "       (SELECT NVL(ATRB1, '320')                   \r\n"
           "          FROM TB_CMMN_CD                          \r\n"
           "         WHERE CMMN_CLSF_CD = 'VMP'                \r\n"
           "           AND CMMN_CD = A.VMS_TYPE_CD) AS FORMW,  \r\n"
           "       (SELECT NVL(ATRB2,  '64')                   \r\n"
           "          FROM TB_CMMN_CD                          \r\n"
           "         WHERE CMMN_CLSF_CD = 'VMP'                \r\n"
           "           AND CMMN_CD = A.VMS_TYPE_CD) AS FORMH   \r\n"
           "  FROM TB_VMS_CTLR A                               \r\n"
           " WHERE A.DEL_YN = 'N'                              \r\n";
#else
    sQry = "SELECT A.*,                           \r\n"
           "       B.VMS_WDTH AS FORMW,           \r\n"
           "       B.VMS_HGHT AS FORMH,           \r\n"
           "       B.MODL_ROW_NUM AS MODV,        \r\n"
           "       B.MODL_COL_NUM AS MODH         \r\n"
           "  FROM TB_VMS_CTLR A, TB_VMS_TYPE B   \r\n"
           " WHERE A.DEL_YN = 'N'                 \r\n"
           "   AND A.VMS_TYPE_CD = B.VMS_TYPE_CD  \r\n";
#endif

    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VmsNo     = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();
                AnsiString VmsId     = pADO->FieldByName("VMS_CTLR_ID")->AsString.Trim();
                AnsiString VmsType   = pADO->FieldByName("VMS_USAG_TYPE_CD")->AsString.Trim();
                AnsiString Name      = pADO->FieldByName("VMS_NM")->AsString.Trim();
                AnsiString Location  = pADO->FieldByName("ISTL_LCTN_NM")->AsString.Trim();
                AnsiString LocalNo   = pADO->FieldByName("VMS_CMNC_PORT")->AsString;//.ToIntDef(0);
                AnsiString IpAddress = pADO->FieldByName("VMS_CTLR_IP")->AsString.Trim();
                AnsiString WlTelNo   = "";
                AnsiString WlIp      = "";
                AnsiString WlPort    = 0;
                int        VmsDownId = pADO->FieldByName("VMS_ID")->AsString.Trim().ToIntDef(0);

				TVmsCtlr *pObj = new TVmsCtlr();

                pObj->FBmpDownload = g_AppCfg.DownloadBitmap;

                pObj->Id        = pADO->FieldByName("VMS_ID")->AsString.Trim().ToIntDef(0);
                pObj->VmsNo     = VmsNo;
                pObj->VmsId     = VmsId;
                pObj->VmsDownId.printf("%02d", VmsDownId);
                pObj->VmsType   = VmsType;
                pObj->Name      = Name;
                pObj->Location  = Location;
                pObj->LocalNo   = LocalNo.ToIntDef(355);
                pObj->IpAddress = IpAddress;
                pObj->WlTelNo   = WlTelNo;
                pObj->WlIp      = WlIp;
                pObj->WlPort    = 0;

                pObj->OPER_MODE             = pADO->FieldByName("OPER_MODE")->AsString;

                pObj->MODULE.PowerOnTime    = Now().FormatString("yyyymmdd") + pADO->FieldByName("PANL_ON_TIME")->AsString;
                pObj->MODULE.PowerOffTime   = Now().FormatString("yyyymmdd") + pADO->FieldByName("PANL_OFF_TIME")->AsString;
                pObj->MODULE.Retry          = 0;

                pObj->LUMINANCE.SchTime = Now().FormatString("yyyymmdd");
                pObj->LUMINANCE.Value   = 0;
                pObj->LUMINANCE.Retry   = 0;

                pObj->VMS_PHSE_CHNG_CYCL    = pADO->FieldByName("VMS_PHSE_CHNG_CYCL")->AsInteger;
                pObj->VMS_CMNC_ERR_BASS_VAL = pADO->FieldByName("VMS_CMNC_ERR_BASS_VAL")->AsInteger;
                pObj->FAN_MTNS_TMPR         = pADO->FieldByName("FAN_MTNS_TMPR")->AsInteger;
                pObj->HETR_MTNS_TMPR        = pADO->FieldByName("HETR_MTNS_TMPR")->AsInteger;
                pObj->VMS_MODL_ERR_RATE     = pADO->FieldByName("VMS_MODL_ERR_RATE")->AsInteger;

                pObj->VMS_MAX_PHSE_NUM      = pADO->FieldByName("VMS_MAX_PHSE_NUM")->AsInteger;

                pObj->VMS_NGHT_BRGH_STEP    = pADO->FieldByName("VMS_NGHT_BRGH_STEP")->AsInteger;     // NUMBER(2)    Y            VMS 야간 휘도 단계
                pObj->VMS_WEEK_BRGH_STEP    = pADO->FieldByName("VMS_WEEK_BRGH_STEP")->AsInteger;     // NUMBER(2)    Y            VMS 주간 휘도 단계
                pObj->CMNCFAIL_SLOT_NMBR    = pADO->FieldByName("CMNCFAIL_SLOT_NMBR")->AsInteger;     // NUMBER(4)    Y    0        통신장애 SLOT 번호
                pObj->PWER_FAIL_SLOT_NMBR   = pADO->FieldByName("PWER_FAIL_SLOT_NMBR")->AsInteger;    // NUMBER(4)    Y    0        전원 장애 SLOT 번호

                pObj->WIDTH                 = pADO->FieldByName("FORMW")->AsInteger;
                pObj->HEIGHT                = pADO->FieldByName("FORMH")->AsInteger;

                pObj->ModVerCnt             = pADO->FieldByName("MODV")->AsInteger;
                pObj->ModHorCnt             = pADO->FieldByName("MODH")->AsInteger;

        		sprintf(pObj->DSTATE.VmsId, "%.*s", INT_VMS_MAX_ID, pObj->VmsNo.c_str());

                if (pObj->OPER_MODE == "A")
                    pObj->DSTATE.OprMode = 'A';
                else
                if (pObj->OPER_MODE == "B")
                    pObj->DSTATE.OprMode = 'B';
                else
                    pObj->DSTATE.OprMode = 'F';

                pObj->DSTATE.Comm  = vms_error;
                pObj->DSTATE.Wcomm = vms_error;

                pObj->DSTATE.ScheduledMessageOperatingTime = pObj->VMS_PHSE_CHNG_CYCL;    /* 필수 계획된 메시지의 동작시간(초) */
                pObj->RSTATE.ScheduledMessageOperatingTime = pObj->VMS_PHSE_CHNG_CYCL;    /* 필수 계획된 메시지의 동작시간(초) */

                pObj->DSTATE.ModuleOperatingTemperature    = pObj->VMS_CMNC_ERR_BASS_VAL; /* 필수 모듈 전원이 꺼지는 온도값(℃) */
                pObj->DSTATE.FanOperatingTemperature       = pObj->FAN_MTNS_TMPR;         /* 필수 Fan 동작 기준 온도값(℃) */
                pObj->DSTATE.HeaterOperatingTemperature    = pObj->HETR_MTNS_TMPR;        /* 필수 Heater 동작 기준 온도값(℃) */
                pObj->DSTATE.ModuleBasicFailureRate        = pObj->VMS_MODL_ERR_RATE;     /* 선택 모듈 장애율 (한 개의 모듈을 장애로 처리하기 위한 픽셀의 백분율값) */
                pObj->DSTATE.ExternalLightOperatingLuminance = 0;                         /* 선택 외부전등 동작 기준 휘도값 */
                pObj->DSTATE.MaximumRetry                    = 3;                         /* 선택 최대 재시도 횟수(회) */
                pObj->DSTATE.ResponseTimeOut                 = 30;                        /* 선택 최대응답대기시간 (초) */
                pObj->DSTATE.BlinkingCycleTime               = 100;                       /* 선택 점멸시간 주기 ( 1/10초단위) */
                memcpy(&pObj->RSTATE, &pObj->DSTATE, sizeof(pObj->RSTATE));
                pObj->RSTATE.Comm  = vms_error;
                pObj->RSTATE.Wcomm = vms_error;

                pObj->FSLog = new TITSLog(g_sLogDir + "Comm\\"+pObj->VmsId + "\\", pObj->VmsId+"S", g_AppCfg.sLogDay);
                pObj->FCLog = new TITSLog(g_sLogDir + "Comm\\"+pObj->VmsId + "\\", pObj->VmsId+"C", g_AppCfg.sLogDay);
                pObj->FSLog->FLogCfg = g_LogCfg;
                pObj->FCLog->FLogCfg = g_LogCfg;

                pObj->ChangeDate = Now().FormatString("yyyymmddhhnnss");
                pObj->pPackQueue = new TThreadList();

                if (VComm_CheckIpAddress(pObj->IpAddress.c_str()) &&
                    pObj->pPackQueue &&
                    pObj->FSLog      &&
                    pObj->FCLog      )
                {
                    pObj->Server.UseFlag = bit_enable;
                    pObj->Server.Status  = process_run;

                    pObj->Client.UseFlag = bit_enable;
                    pObj->Client.Status  = process_run;
                }

                pObj->SCHEDULE = new VMS_SCHEDULE_INFO;
                pObj->SCHEDULE->Count = 0;

                pObj->INCIDENT = new VMS_EVENT_INFO;
                pObj->INCIDENT->Count = 0;

                pObj->EVENT = new VMS_EVENT_INFO;
                pObj->EVENT->Count = 0;

                pObj->DOWNLOAD = new VMS_DOWNLOAD_INFO;
                InitDownLoadInfo(pObj->DOWNLOAD);

                pObj->CTLMODE = new VMS_CONTROL_MODE;
                InitCtlModeInfo(pObj->CTLMODE);

                if (pObj->VMS_MAX_PHSE_NUM > INT_MAX_VMS_FORM)
                    pObj->VMS_MAX_PHSE_NUM = INT_MAX_VMS_FORM;

                pObj->CTLMODE->MaxDisplayForm = pObj->VMS_MAX_PHSE_NUM;
                pObj->CTLMODE->Control        = pObj->DSTATE.OprMode;
#if 0
                if (pObj->CTLMODE->MaxDisplayForm > INT_MAX_VMS_FORM)
                    pObj->CTLMODE->MaxDisplayForm = INT_MAX_VMS_FORM;
#endif

                //VMS제공폼을 관리할 관리자 생성(VMS개별적으로 생성함)
                pObj->pForms = new TVmsFormManager();
                pObj->pForms->FormWidth = pObj->WIDTH;
                pObj->pForms->FormHeight= pObj->HEIGHT;

                String sFormDir = g_sFormDir + pObj->VmsId + "\\";
                ForceDirectories(sFormDir.c_str());

				VmsManager->FLists.Push(pObj->VmsNo, pObj);

#if 0
                String sFtpDir = g_sFtpDir + pObj->VmsId + "\\";
                ForceDirectories(sFtpDir.c_str());
#endif
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    LINFO("GetVmsInfo: %d EA", VmsManager->Count);

    //return VERR_NONE;
    return GetVmsStateInfo();
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetVmsStateInfo()
{
    String     sQry;
    TADOQuery *pADO = NULL;

    int        nSelCnt = 0;

    LDEBUG("GetVmsStateInfo: Start");

    sQry = "SELECT A.*                                \r\n"
           "  FROM TB_VMS_STTS_PRST A,                \r\n"
           "       TB_VMS_CTLR      B                 \r\n"
           " WHERE B.DEL_YN = 'N'                     \r\n"
           "   AND A.VMS_CTLR_NMBR = B.VMS_CTLR_NMBR  \r\n";

    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VmsNo = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();
                TVmsCtlr *pObj = VmsManager->FLists.Find(VmsNo);
                if (!pObj) continue;

                nSelCnt++;

                AnsiString CBOXDOOR_OPEN_STTS_CD = pADO->FieldByName("CBOXDOOR_OPEN_STTS_CD")->AsString.Trim();
                AnsiString PWER_STTS_CD          = pADO->FieldByName("PWER_STTS_CD")->AsString.Trim();
                AnsiString CBOX_TMPR             = pADO->FieldByName("CBOX_TMPR")->AsString.Trim();
                AnsiString CBOX_HMDT             = pADO->FieldByName("CBOX_HMDT")->AsString.Trim();
                AnsiString FAN_STTS_CD           = pADO->FieldByName("FAN_STTS_CD")->AsString.Trim();
                AnsiString HETR_STTS_CD          = pADO->FieldByName("HETR_STTS_CD")->AsString.Trim();
                AnsiString CBOXFAN_STTS_CD       = pADO->FieldByName("CBOXFAN_STTS_CD")->AsString.Trim();

                if (CBOXDOOR_OPEN_STTS_CD == "CDS0")
                {
                    pObj->DSTATE.DoorStatus = vms_close;
                }
                else
                {
                    pObj->DSTATE.DoorStatus = vms_open;
                }

                if (PWER_STTS_CD == "PWS0")
                {
                    pObj->DSTATE.ModulePowerStatus = vms_normal;
                }
                else
                {
                    pObj->DSTATE.ModulePowerStatus = vms_error;
                }
                pObj->DSTATE.BodyTemp = (short)CBOX_TMPR.ToIntDef(0);
                pObj->DSTATE.LuminanceStatus = (BYTE)CBOX_HMDT.ToIntDef(0);

                if (FAN_STTS_CD == "PAS0")
                {
                    pObj->DSTATE.FanStatus = vms_on;
                }
                else
                {
                    pObj->DSTATE.FanStatus = vms_off;
                }

                if (HETR_STTS_CD == "HTS0")
                {
                    pObj->DSTATE.HeaterStatus = vms_on;
                }
                else
                {
                    pObj->DSTATE.HeaterStatus = vms_off;
                }

                if (CBOXFAN_STTS_CD == "MOS0")
                {
                    pObj->DSTATE.ModuleState = vms_normal;
                }
                else
                {
                    pObj->DSTATE.HeaterStatus = vms_error;
                }

                memcpy(&pObj->RSTATE, &pObj->DSTATE, sizeof(pObj->RSTATE));
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    LINFO("GetVmsStateInfo: %d EA", nSelCnt);

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetVmsIfscInfo()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;

    LINFO("GetVmsIfscInfo: Start");

    try
    {
        VmsIterator it;
        for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
        {
            TVmsCtlr *pObj = (TVmsCtlr*)it->second;
            //if (pObj->Server.UseFlag != bit_enable) continue;
            //기존 제공구간정보를 모두 삭제
            pObj->FIfscLists.RemoveAll();
        }
    }
    catch(Exception &e)
    {
    }

    sQry = "SELECT A.VMS_CTLR_NMBR, B.VMS_IFSC_ID,    \r\n"
           "       B.DSPL_PRRT, C.AXIS_YN             \r\n"
           "  FROM TB_VMS_CTLR      A,                \r\n"
           "       TB_VMS_IFSC_RLTN B,                \r\n"
           "       TB_VMS_IFSC      C                 \r\n"
           " WHERE A.VMS_CTLR_NMBR = B.VMS_CTLR_NMBR  \r\n"
           "   AND B.VMS_IFSC_ID   = C.VMS_IFSC_ID    \r\n"
           "   AND C.EDTN_CD <> 'EDI2'                \r\n"
           "   AND A.DEL_YN = 'N'                     \r\n"
           " ORDER BY A.VMS_CTLR_NMBR, B.DSPL_PRRT    \r\n";

    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VMS_CTLR_NMBR = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();

				TVmsCtlr *pObj = VmsManager->FLists.Find(VMS_CTLR_NMBR);
                if (!pObj) continue;

                TVmsIfsc *pIfsc = new TVmsIfsc();
                pIfsc->VMS_IFSC_ID = pADO->FieldByName("VMS_IFSC_ID")->AsString;
                pIfsc->DSPL_PRRT   = pADO->FieldByName("DSPL_PRRT")->AsInteger;

                pObj->FIfscLists.Push(pIfsc->DSPL_PRRT, pIfsc);
                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }
    LINFO("GetVmsIfscInfo: %d", nSelCnt);
    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::LoadVmsOnOffTime()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;

    LINFO("   LoadVmsOnOffTime: Start");

    sQry = "SELECT A.VMS_CTLR_NMBR, \r\n"
           "       A.PANL_ON_TIME,  \r\n"
           "       A.PANL_OFF_TIME  \r\n"
           "  FROM TB_VMS_CTLR A    \r\n"
           " WHERE A.DEL_YN = 'N'   \r\n";
    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VmsNo = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();

				TVmsCtlr *pObj = VmsManager->FLists.Find(VmsNo);
                if (!pObj) continue;

                pObj->MODULE.PowerOnTime  = Now().FormatString("yyyymmdd") + pADO->FieldByName("PANL_ON_TIME")->AsString;
                pObj->MODULE.PowerOffTime = Now().FormatString("yyyymmdd") + pADO->FieldByName("PANL_OFF_TIME")->AsString;
                pObj->MODULE.Retry        = VMS_MAX_RETRY_COUNT;
                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    LINFO("   LoadVmsOnOffTime: %d", nSelCnt);

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetVmsLuminanceTime()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;

    LINFO("GetVmsLuminanceTime: Start");

    sQry = "SELECT A.VMS_CTLR_NMBR, A.SCH_TIME, A.LUMINANCE  \r\n"
           "  FROM TB_VMS_LUM_SET_SCH A,                     \r\n"
           "       TB_VMS_CTLR        B                      \r\n"
           " WHERE A.VMS_CTLR_NMBR = B.VMS_CTLR_NMBR         \r\n"
           "   AND B.DEL_YN = 'N'                            \r\n"
           "   AND A.USE_YN = 'Y'                            \r\n"
           "   AND A.SCH_TIME = TO_CHAR(SYSDATE, 'HH24MI')   \r\n";

    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VmsNo = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();
				TVmsCtlr *pObj = VmsManager->FLists.Find(VmsNo);
                if (!pObj) continue;

                pObj->LUMINANCE.SchTime = Now().FormatString("yyyymmdd") + pADO->FieldByName("SCH_TIME")->AsString;
                pObj->LUMINANCE.Value   = pADO->FieldByName("LUMINANCE")->AsInteger;
                pObj->LUMINANCE.Retry   = VMS_MAX_RETRY_COUNT;
                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    LINFO("GetVmsLuminanceTime: %d", nSelCnt);

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetVmsDownLoadInfo()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;
    int        nDnIdx;
    VMS_DOWNLOAD_INFO *pInfo;

return VERR_NONE;
    LDEBUG("GetVmsDownLoadInfo: Start");

    sQry = "SELECT A.VMS_CTLR_NMBR, A.RGST_DT,                               \r\n"
           "       A.FILETYPE, A.FILEID                                      \r\n"
           "  FROM TB_VMS_DOWNLOAD A                                         \r\n"
           " WHERE A.SENDSTARTDATE <= TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS')   \r\n"
           "   AND A.SENDRESULT = 0                                          \r\n"
           " ORDER BY A.VMS_CTLR_NMBR, A.RGST_DT DESC, A.FILETYPE, A.FILEID  \r\n";


    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        pInfo = pObj->DOWNLOAD;
        InitDownLoadInfo(pInfo);
    }

    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VmsNo     = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();
				TVmsCtlr *pObj = VmsManager->FLists.Find(VmsNo);
                if (!pObj) continue;

                if (pObj->DOWNLOAD->Count < VMS_MAX_DOWNLOAD)
                {
                    pInfo = pObj->DOWNLOAD;

                    nDnIdx = pInfo->Count++;
                    pInfo->Unit[nDnIdx].RegDate     = pADO->FieldByName("RGST_DT")->AsString;
                    pInfo->Unit[nDnIdx].FileType    = pADO->FieldByName("FILETYPE")->AsString;
                    pInfo->Unit[nDnIdx].FileId      = pADO->FieldByName("FILEID")->AsString;
                    pInfo->Unit[nDnIdx].SendEndDate = Now().FormatString("yyyymmddhhnnss");
                    pInfo->Unit[nDnIdx].SendStep    = send_wait;
                    pInfo->Unit[nDnIdx].SendResult  = vms_download_fail;
                }
                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        if (pObj->DOWNLOAD->Count > 0)
        {
            pObj->DOWNLOAD->Enable   = vms_download_enable;
            pObj->DOWNLOAD->SaveFlag = false;
        }
    }

    LINFO("GetVmsDownLoadInfo: %d", nSelCnt);

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetVmsImage()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    TStream   *pStream = NULL;
    int        nSelCnt = 0;

    LINFO("GetVmsImage: Start");

    sQry = "SELECT A.*               \r\n"
           "  FROM TB_VMS_SYMB_LIB A \r\n";
    try
    {
        TCDSImage *pVmsImg;
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString sSymbolNmbr  = "";
                bool bTrafSymbol = false;

                int nSymbolNmbr = pADO->FieldByName("SYMBLIB_NMBR")->AsInteger;
                if (nSymbolNmbr >= 8000 && nSymbolNmbr <= 8999)
                {
                    bTrafSymbol = true;
                }

                sSymbolNmbr = AnsiString(nSymbolNmbr) + "0";

				pVmsImg = ImageManager->FLists.Find(sSymbolNmbr);
                if (!pVmsImg)
                {
                    pVmsImg = new TCDSImage();
                    pVmsImg->Nmbr = sSymbolNmbr;
                    ImageManager->FLists.Push(pVmsImg->Nmbr, pVmsImg);
                }
                pVmsImg->FLists.RemoveAll();

                pVmsImg->Type    = vms_image_type_bmp;
                pVmsImg->VmsType = pADO->FieldByName("VMS_TYPE_CD")->AsString.Trim(); //VMP0: 심볼, VMP1: 소통정보배경, VMP1:소통정보
                if (bTrafSymbol) pVmsImg->VmsType = "VMP2";

                pVmsImg->Clear();
    			pVmsImg->pImage->Picture->Bitmap->PixelFormat = pf4bit;

                TStream *pStream = pADO->CreateBlobStream(pADO->FieldByName("IMAG_DATA"), bmRead);
                try
                {
                    if (pStream && pStream->Size > 0)
                    {
                        pStream->Position = 0;
                        switch(pVmsImg->Type)
                        {
                        case vms_image_type_bmp: AssignBmp(pVmsImg->pImage, pStream); break;
                        case vms_image_type_gif: AssignGif(pVmsImg->pImage, pStream); break;
                        case vms_image_type_jpg: AssignJpg(pVmsImg->pImage, pStream); break;
                        case vms_image_type_pcx: break;
                        default: break;
                        }
                    }
                }
                __finally
                {
                    SAFE_DELETE(pStream);
                }
                nSelCnt++;

                if (pVmsImg->VmsType == "VMP2")
                {
                    for (int nTrf = 1; nTrf <= 3; nTrf++)
                    {
                        sSymbolNmbr = AnsiString(nSymbolNmbr) + AnsiString(nTrf);
                        //좌표가 바뀌더라도 셀정보에서 업데이트 한다.
                        //이미지내용이 바뀌는 경우는 없다
                        pVmsImg = ImageManager->FLists.Find(sSymbolNmbr);
                        if (pVmsImg) continue;

                        pVmsImg = new TCDSImage();
                        pVmsImg->Nmbr = sSymbolNmbr;
                        ImageManager->FLists.Push(pVmsImg->Nmbr, pVmsImg);
                        pVmsImg->FLists.RemoveAll();

                        pVmsImg->Type    = vms_image_type_bmp;
                        pVmsImg->VmsType = "VMP2";

                        pVmsImg->Clear();
                        pVmsImg->pImage->Picture->Bitmap->PixelFormat = pf4bit;

                        TStream *pStream = pADO->CreateBlobStream(pADO->FieldByName("IMAG_DATA"), bmRead);
                        try
                        {
                            if (pStream && pStream->Size > 0)
                            {
                                pStream->Position = 0;
                                switch(pVmsImg->Type)
                                {
                                case vms_image_type_bmp: AssignBmp(pVmsImg->pImage, pStream); break;
                                case vms_image_type_gif: AssignGif(pVmsImg->pImage, pStream); break;
                                case vms_image_type_jpg: AssignJpg(pVmsImg->pImage, pStream); break;
                                case vms_image_type_pcx: break;
                                default: break;
                                }
                            }
                        }
                        __finally
                        {
                            SAFE_DELETE(pStream);
                        }
                    }
                }
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }


    int result = GetVmsImageCell();

    //if (g_LogCfg.Debug)
    //FTP로 다운로드 해야 하기 때문에 파일로 저장해야 한다.
    //소통정보 이미지 같은 경우 디비에는 하나만 등록하고 여기서 조회할때
    //소통등급별로 이미지를 만든다.
    {
        AnsiString sImgFile;
        FOR_STL(TCDSImage*, pTmp, ImageManager->FLists)
        {
            sImgFile = g_sImgDir + pTmp->Nmbr;
            try
            {
                switch(pTmp->Type)
                {
                case vms_image_type_bmp: sImgFile += ".bmp"; SaveToFileBmp(pTmp->pImage, sImgFile); break;
                case vms_image_type_gif: sImgFile += ".gif"; SaveToFileGif(pTmp->pImage, sImgFile); break;
                case vms_image_type_jpg: sImgFile += ".jpg"; SaveToFileJpg(pTmp->pImage, sImgFile); break;
                case vms_image_type_pcx: sImgFile += ".pcx"; break;
                default: break;
                }
            }
            catch(Exception &e)
            {
            }
#if 0
            sImgFile = g_sFtpDir + GetFtpImageId(pTmp->Nmbr);
            try
            {
                switch(pTmp->Type)
                {
                case vms_image_type_bmp: sImgFile += ".bmp"; SaveToFileBmp(pTmp->pImage, sImgFile); break;
                case vms_image_type_gif: sImgFile += ".gif"; SaveToFileGif(pTmp->pImage, sImgFile); break;
                case vms_image_type_jpg: sImgFile += ".jpg"; SaveToFileJpg(pTmp->pImage, sImgFile); break;
                case vms_image_type_pcx: sImgFile += ".pcx"; break;
                default: break;
                }
            }
            catch(Exception &e)
            {
            }
#endif
        }
    }

    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        pObj->FSymbolDownload = true;
    }
    LINFO("GetVmsImage: %d", nSelCnt);

    return result;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::GetVmsImageCell()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;

    LINFO("GetVmsImageCell: Start");

    sQry = "SELECT B.*                              \r\n"
           "  FROM TB_VMS_SYMB_LIB  A,              \r\n"
           "       TB_VMS_SYMB_IFSC B               \r\n"
           " WHERE A.SYMBLIB_NMBR = B.SYMBLIB_NMBR  \r\n"
           " ORDER BY B.SYMBLIB_NMBR, B.CELL_ID     \r\n";

    try
    {
        TCDSImage     *pVmsImg;
        TCDSImageCell *pImgCell;
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString SYMBLIB_NMBR = pADO->FieldByName("SYMBLIB_NMBR")->AsString.Trim();
				pVmsImg = ImageManager->FLists.Find(SYMBLIB_NMBR+"0");
                if (!pVmsImg)
                {
                    continue;
                }

                pImgCell = new TCDSImageCell();

                pImgCell->SYMBLIB_NMBR = SYMBLIB_NMBR;
                pImgCell->CELL_ID      = pADO->FieldByName("CELL_ID")->AsInteger;
                pImgCell->POSX         = pADO->FieldByName("POSX")->AsInteger;
                pImgCell->POSY         = pADO->FieldByName("POSY")->AsInteger;
                pImgCell->VMS_IFSC_ID  = pADO->FieldByName("VMS_IFSC_ID")->AsString;

                pVmsImg->FLists.Push(pImgCell->CELL_ID, pImgCell);

                //소통정보 이미지인 경우(원활,지체,정체 이미지 생성)
                if (pVmsImg->VmsType == "VMP2")
                {
                    for (int nTrf = 1; nTrf <= 3; nTrf++)
                    {
                        TCDSImage *pTmpImg = ImageManager->FLists.Find(SYMBLIB_NMBR+AnsiString(nTrf));
                        if (!pVmsImg) continue;

                        try
                        {
                            pTmpImg->pImage->Picture->Bitmap->Canvas->Lock();
                            pTmpImg->pImage->Picture->Bitmap->Canvas->Brush->Color = GradeToFillColor(nTrf);
                            TColor clColor = pTmpImg->pImage->Picture->Bitmap->Canvas->Pixels[pImgCell->POSX][pImgCell->POSY];
                            pTmpImg->pImage->Picture->Bitmap->Canvas->FloodFill(pImgCell->POSX, pImgCell->POSY, clColor, fsSurface);
                        }
                        __finally
                        {
                            pTmpImg->pImage->Picture->Bitmap->Canvas->Unlock();
                        }
                    }
                }
                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    if (0)
    {
        FOR_STL(TCDSImage*, pTmp, ImageManager->FLists)
        {
            if (pTmp->FLists.Size() == 0) continue;
            LDEBUG("Image Cell: %s, Objects: %d", pTmp->Nmbr.c_str(), pTmp->FLists.Size());
        }
    }

    LINFO("GetVmsImageCell: %d", nSelCnt);

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::LoadVmsForm()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    TStream   *pStream = NULL;
    int        nSelCnt = 0;

    LINFO("        LoadVmsForm: Start");

    sQry = "SELECT A.*           \r\n"
           "  FROM TB_VMS_FORM A \r\n";
    try
    {
        TCDSForm *pVmsForm;
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString sFormId = pADO->FieldByName("VMS_FORM_ID")->AsString.Trim();
				pVmsForm = FormManager->FLists.Find(sFormId);
                if (!pVmsForm)
                {
                    pVmsForm = new TCDSForm();
                    pVmsForm->VMS_FORM_ID = sFormId;
                    FormManager->FLists.Push(pVmsForm->VMS_FORM_ID, pVmsForm);
                }
                pVmsForm->FLists.RemoveAll();

                pVmsForm->TrfBakImgId = ""; //소통정보 배경 이미지 ID
                pVmsForm->VMS_TYPE_CD          = pADO->FieldByName("VMS_TYPE_CD")->AsString;
                pVmsForm->VMS_FORM_TYPE_CD     = pADO->FieldByName("VMS_FORM_TYPE_CD")->AsInteger;
                pVmsForm->VMS_FORM_BCKG_HUE_CD = pADO->FieldByName("VMS_FORM_BCKG_HUE_CD")->AsInteger;
                pVmsForm->VMS_MSG_DSPL_DRCT_CD = pADO->FieldByName("VMS_MSG_DSPL_DRCT_CD")->AsInteger;
                pVmsForm->VMS_MSG_DSPL_MTHD_CD = pADO->FieldByName("VMS_MSG_DSPL_MTHD_CD")->AsInteger;

                pVmsForm->TrfIfsc = false;
                pVmsForm->TrfAxis = false;

                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    LINFO("        LoadVmsForm: %d EA", nSelCnt);

    return LoadVmsFormObject();
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::LoadVmsFormObject()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    TStream   *pStream = NULL;
    int        nSelCnt = 0;

    LINFO("  LoadVmsFormObject: Start");

#if 0
    sQry = "SELECT B.*                                \r\n"
           "  FROM TB_VMS_FORM A,                     \r\n"
           "       TB_VMS_FORM_OBJECT B               \r\n"
           " WHERE A.VMS_FORM_ID = B.VMS_FORM_ID      \r\n"
           " ORDER BY B.VMS_FORM_ID, B.FORM_OBJECT_ID \r\n";
#else
    sQry = "SELECT B.*, NVL(C.IMAG_DATA, B.VMS_DSPL_FIGR) AS IMAG_DATA  \r\n"
           "  FROM TB_VMS_FORM        A,                                \r\n"
           "       TB_VMS_FORM_OBJECT B,                                \r\n"
           "       TB_VMS_SYMB_LIB    C                                 \r\n"
           " WHERE A.VMS_FORM_ID  = B.VMS_FORM_ID                       \r\n"
           "   AND B.SYMBLIB_NMBR = C.SYMBLIB_NMBR(+)                   \r\n"
           " ORDER BY B.VMS_FORM_ID, B.FORM_OBJECT_ID                   \r\n";
#endif

    try
    {
        TCDSForm    *pVmsForm;
        TCDSFormObj *pFormObj;
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString sFormId = pADO->FieldByName("VMS_FORM_ID")->AsString.Trim();
				pVmsForm = FormManager->FLists.Find(sFormId);
                if (!pVmsForm)
                {
                   continue;
                }
                nSelCnt++;

                pFormObj = new TCDSFormObj();

                pFormObj->FORM_OBJECT_ID          = pADO->FieldByName("FORM_OBJECT_ID")->AsInteger;
                pFormObj->VMS_FORM_ID             = pADO->FieldByName("VMS_FORM_ID")->AsString;
                pFormObj->VMS_FORM_DSPL_ROW       = pADO->FieldByName("VMS_FORM_DSPL_ROW")->AsInteger;
                pFormObj->VMS_FORM_DSPL_CLMN      = pADO->FieldByName("VMS_FORM_DSPL_CLMN")->AsInteger;
                pFormObj->VMS_FORM_OBJECT_TYPE_CD = pADO->FieldByName("VMS_FORM_OBJECT_TYPE_CD")->AsInteger;
                pFormObj->VMS_FONT_TYPE_CD        = pADO->FieldByName("VMS_FONT_TYPE_CD")->AsInteger;
                pFormObj->VMS_FONT_HUE_CD         = pADO->FieldByName("VMS_FONT_HUE_CD")->AsInteger;
                pFormObj->VMS_FONT_STYL_CD        = pADO->FieldByName("VMS_FONT_STYL_CD")->AsInteger;
                pFormObj->VMS_FONT_SIZE           = pADO->FieldByName("VMS_FONT_SIZE")->AsInteger;
                pFormObj->VMS_FONT_ALIGN          = pADO->FieldByName("VMS_FONT_ALIGN")->AsInteger;
                pFormObj->VMS_DSPL_TXT            = pADO->FieldByName("VMS_DSPL_TXT")->AsString;
                pFormObj->VMS_DSPL_XCRDN          = pADO->FieldByName("VMS_DSPL_XCRDN")->AsInteger;
                pFormObj->VMS_DSPL_YCRDN          = pADO->FieldByName("VMS_DSPL_YCRDN")->AsInteger;
                pFormObj->VMS_DSPL_WIDTH          = pADO->FieldByName("VMS_DSPL_WIDTH")->AsInteger;
                pFormObj->VMS_DSPL_HEIGHT         = pADO->FieldByName("VMS_DSPL_HEIGHT")->AsInteger;
                pFormObj->VMS_DSPL_BLINKING       = pADO->FieldByName("VMS_DSPL_BLINKING")->AsInteger;
                pFormObj->VMS_DSPL_BKCOLOR        = pADO->FieldByName("VMS_DSPL_BKCOLOR")->AsInteger;
                pFormObj->VMS_DSPL_SIZE           = pADO->FieldByName("VMS_DSPL_SIZE")->AsInteger;
                pFormObj->TRFC_FILL_CD            = pADO->FieldByName("TRFC_FILL_CD")->AsString;
                pFormObj->SYMBLIB_NMBR            = pADO->FieldByName("SYMBLIB_NMBR")->AsString;
                pFormObj->VMS_IFSC_ID             = pADO->FieldByName("VMS_IFSC_ID")->AsString;

                pVmsForm->FLists.Push(pFormObj->FORM_OBJECT_ID, pFormObj);

                int nObjType = pFormObj->VMS_FORM_OBJECT_TYPE_CD;

                if (pVmsForm->VMS_FORM_TYPE_CD == enFormKindTrfImg)
                {
                    //도형식 소통정보 폼인데 구간 소통정보를 하단에 표출하는 경우
                    //하나의 폼이 여러개의 소통정보를 표출되도록 하기 위함
                    switch(nObjType)
                    {
                    case 11://, '	@구간명
                    case 12://, '	@시점명
                    case 13://, '	@종점명
                    case 14://, '	@소통상황
                    case 15://, '	@통행시간
                    case 16://, '	@통행속도
                    case 17://, '	@소통정보이미지
                    case 18://, '	@지점명
                        pVmsForm->TrfIfsc = true;
                        break;
                    case 93://, '	@축시점명(순환)
                    case 94://, '	@축종점명(순환)
                    case 95://, '	@축소통상황(순환)
                    case 96://, '	@축통행시간(순환)
                        pVmsForm->TrfAxis = true;
                        break;
                    }
                }

                if (nObjType == 3)
                {
                    pVmsForm->TrfBakImgId = pFormObj->SYMBLIB_NMBR + "0";
                }

                if (nObjType ==  1 || //심볼
                    nObjType ==  2 || //이미지(파일에서 직접입력한것임)
                    nObjType ==  3 || //소통정보배경이미지
                    nObjType == 17 || //소통정보이미지1
                    nObjType == 27 || //소통정보이미지2
                    nObjType == 37 || //소통정보이미지3
                    nObjType == 47 )  //소통정보이미지4
                {
                    pFormObj->Clear();
                    pFormObj->pImage->Picture->Bitmap->PixelFormat = pf4bit;
                    //심볼에서 읽지 않고 폼오브젝트에 있는 이미지를 사용함
#if 0
                    TStream *pStream = pADO->CreateBlobStream(pADO->FieldByName("VMS_DSPL_FIGR"), bmRead);
#else
                    TStream *pStream = pADO->CreateBlobStream(pADO->FieldByName("IMAG_DATA"), bmRead);
#endif
                    try
                    {
                        if (pStream && pStream->Size > 0)
                        {
                            pStream->Position = 0;
                            AssignBmp(pFormObj->pImage, pStream);
                        }
                    }
                    __finally
                    {
                        SAFE_DELETE(pStream);
                    }
                }
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    if (0)//g_LogCfg.Debug)
    {
        FOR_STL(TCDSForm*, pTmp, FormManager->FLists)
        {
            LDEBUG("Vms Form: %s, Objects: %d", pTmp->VMS_FORM_ID.c_str(), pTmp->FLists.Size());
        }
    }

    LINFO("  LoadVmsFormObject: %d EA", nSelCnt);

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SaveProcessStateProc(void)
{
	int               nResult;
	AnsiString        sQry;
	DB_STATUS_PROCESS sp;
	TADOQuery        *pADO = NULL;

	nResult = VERR_OTHER;

	//sp.PROCESSID = g_AppCfg.strProcessID;
	sp.RUNVERSION = "1";
	sp.STATUS     = g_SysInfo->State.Action;
	sp.COMM       = g_SysInfo->State.Comm;
	sp.DB         = g_SysInfo->State.DB;

    bool bHistIns = false;
    AnsiString SYST_ID      = g_AppCfg.sSystemId;
    AnsiString SYST_STTS_CD = "SPS1";
	try
	{
        pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            pADO->Connection->BeginTrans();

            if (g_SysInfo->State.Action == state_error)
            {
                SYST_STTS_CD = "SPS3";
                bHistIns = true;
            }

			sQry = "UPDATE TB_UNIT_SYST_STTS                                   \r\n"
                   "   SET SYST_STTS_CD = :p02,                                \r\n"
                   "       UPDT_DT      = TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') \r\n"
                   " WHERE SYST_ID = :p01                                      \r\n";

            SQLText(pADO, sQry, false);
            SQLBind(pADO, "p01", SYST_ID);
            SQLBind(pADO, "p02", SYST_STTS_CD);
            SQLExec(pADO);

            //이력 정보는 기본적으로 5분마다 입력한다(상태정보가 바뀌면 바로 입력).
            int nCurMin = StrToInt(Now().FormatString("nn"));
            if (FProcessStateMin < 0)
            {
                //프로세스 최초 기동시...
                FProcessStateMin = nCurMin;
                bHistIns = true;
            }
            else
            if (!(nCurMin%5))
            {
                //5분주기 체크
                if (FProcessStateMin != nCurMin)
                {
                    FProcessStateMin = nCurMin;
                    bHistIns = true;
                }
            }

            if (bHistIns)
            {
                sQry = "INSERT INTO TB_UNIT_SYST_STTS_HS(SYST_ID, CRTN_DT, SYST_STTS_CD) \r\n"
                       "   VALUES(:p01, TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS'), :p02)      \r\n";

                SQLText(pADO, sQry, false);
                SQLBind(pADO, "p01", SYST_ID);
                SQLBind(pADO, "p02", SYST_STTS_CD);
                SQLExec(pADO);
            }

            pADO->Connection->CommitTrans();

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(E.ClassName()) + E.Message;
            DBERRORLOG("SaveProcessStateProc", String(E.ClassName()), E.Message, sQry);
		}
		catch(Exception &e)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(e.ClassName()) + e.Message;
            DBERRORLOG("SaveProcessStateProc", String(e.ClassName()), e.Message, sQry);
		}
	}
	__finally
	{
        if (pADO)
        {
            SQLClose(pADO);
            SAFE_DELETE(pADO);
        }
	}

    LDEBUG("SYST_ID: %s, STTS_CD: %s", SYST_ID.c_str(), SYST_STTS_CD.c_str());

    return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SaveEquipStateAllProc(void)
{
	int        nResult = VERR_NONE;
	AnsiString sQry, iQry;
	TADOQuery *pADO  = NULL;
//	TADOQuery *pADOI = NULL;


    // 상태가 변경되면 바로 입력, 기타 5분마다 이력정보를 입력한다.
    bool bSaveHist = false;

    int nCurrMin = StrToInt(Now().FormatString("nn"));
    if ((nCurrMin % 5) == 0) //매 5분마다 무조건 입력
    {
        if (FEquipStateMin != nCurrMin)
        {
            bSaveHist = true;
            FEquipStateMin = nCurrMin;
        }
    }

    String sSysTime = Now().FormatString("yyyymmddhhnnss");

    sQry = "MERGE INTO TB_VMS_STTS_PRST L                                     \r\n"
           "USING (SELECT :p01 AS VMS_CTLR_NMBR,                              \r\n"
           "              :p02 AS RGST_DT,                                    \r\n"
           "              :p03 AS CONN_STTS_CD,                               \r\n"
           "              :p04 AS CBOXDOOR_OPEN_STTS_CD,                      \r\n"
           "              :p05 AS PWER_STTS_CD,                               \r\n"
           "              :p06 AS CBOX_TMPR,                                  \r\n"
           "              :p07 AS CBOX_HMDT,                                  \r\n"
           "              :p08 AS FAN_STTS_CD,                                \r\n"
           "              :p09 AS HETR_STTS_CD,                               \r\n"
           "              :p10 AS CBOXFAN_STTS_CD,                            \r\n"
           "              :p11 AS HIST_INS                                    \r\n"
           "         FROM DUAL) M                                             \r\n"
           "ON (L.VMS_CTLR_NMBR = M.VMS_CTLR_NMBR)                            \r\n"
           "WHEN MATCHED THEN                                                 \r\n"
           "    UPDATE SET L.RGST_DT               = M.RGST_DT,               \r\n"
           "               L.CONN_STTS_CD          = M.CONN_STTS_CD,          \r\n"
           "               L.CBOXDOOR_OPEN_STTS_CD = M.CBOXDOOR_OPEN_STTS_CD, \r\n"
           "               L.PWER_STTS_CD          = M.PWER_STTS_CD,          \r\n"
           "               L.CBOX_TMPR             = M.CBOX_TMPR,             \r\n"
           "               L.CBOX_HMDT             = M.CBOX_HMDT,             \r\n"
           "               L.FAN_STTS_CD           = M.FAN_STTS_CD,           \r\n"
           "               L.HETR_STTS_CD          = M.HETR_STTS_CD,          \r\n"
           "               L.CBOXFAN_STTS_CD       = M.CBOXFAN_STTS_CD,       \r\n"
           "               L.HIST_INS              = M.HIST_INS               \r\n"
           "WHEN NOT MATCHED THEN                                             \r\n"
           "    INSERT (L.VMS_CTLR_NMBR,                                      \r\n"
           "            L.RGST_DT,                                            \r\n"
           "            L.CONN_STTS_CD,                                       \r\n"
           "            L.CBOXDOOR_OPEN_STTS_CD,                              \r\n"
           "            L.PWER_STTS_CD,                                       \r\n"
           "            L.CBOX_TMPR,                                          \r\n"
           "            L.CBOX_HMDT,                                          \r\n"
           "            L.FAN_STTS_CD,                                        \r\n"
           "            L.HETR_STTS_CD,                                       \r\n"
           "            L.CBOXFAN_STTS_CD, L.HIST_INS)                        \r\n"
           "    VALUES (M.VMS_CTLR_NMBR,                                      \r\n"
           "            M.RGST_DT,                                            \r\n"
           "            M.CONN_STTS_CD,                                       \r\n"
           "            M.CBOXDOOR_OPEN_STTS_CD,                              \r\n"
           "            M.PWER_STTS_CD,                                       \r\n"
           "            M.CBOX_TMPR,                                          \r\n"
           "            M.CBOX_HMDT,                                          \r\n"
           "            M.FAN_STTS_CD,                                        \r\n"
           "            M.HETR_STTS_CD,                                       \r\n"
           "            M.CBOXFAN_STTS_CD, M.HIST_INS)                        \r\n";

    iQry = "INSERT INTO TB_VMS_STTS_HS         \r\n"
           "           (VMS_CTLR_NMBR,         \r\n"
           "            RGST_DT,               \r\n"
           "            CONN_STTS_CD,          \r\n"
           "            CBOXDOOR_OPEN_STTS_CD, \r\n"
           "            PWER_STTS_CD,          \r\n"
           "            CBOX_TMPR,             \r\n"
           "            CBOX_HMDT,             \r\n"
           "            FAN_STTS_CD,           \r\n"
           "            HETR_STTS_CD,          \r\n"
           "            CBOXFAN_STTS_CD)       \r\n"
           "    VALUES (:p01,                  \r\n"
           "            :p02,                  \r\n"
           "            :p03,                  \r\n"
           "            :p04,                  \r\n"
           "            :p05,                  \r\n"
           "            :p06,                  \r\n"
           "            :p07,                  \r\n"
           "            :p08,                  \r\n"
           "            :p09,                  \r\n"
           "            :p10)                  \r\n";
	try
	{
        pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

//        pADOI = new TADOQuery(NULL);
//        pADOI->Connection = GetDbConnection();

		try
		{
            pADO->Connection->BeginTrans();

            SQLText(pADO,  sQry, false);
//            SQLText(pADOI, iQry, false);

            VmsIterator it;
            for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
            {
                TVmsCtlr *pObj = (TVmsCtlr*)it->second;
                if (pObj->Server.UseFlag != bit_enable) continue;

                String HIST_INS;
                if (bSaveHist)
                {
                    pObj->FSaveState = true;
                    HIST_INS = "1";
                }
                else
                {
                    pObj->FSaveState = ChangedState(&pObj->DSTATE, &pObj->RSTATE);
                    HIST_INS = "0";
                }
                //pObj->RSTATE.Comm = pObj->DSTATE.Comm;
                if (pObj->FSaveState)
                {
                    memcpy(&pObj->DSTATE, &pObj->RSTATE, sizeof(pObj->DSTATE));
                }
                pObj->DSTATE.Comm = pObj->Client.Comm == state_open ? vms_normal : vms_error;;//pObj->Server.Status == process_run ? vms_normal : vms_error;

                String VMS_CTLR_NMBR         = pObj->VmsNo;
                String RGST_DT               = sSysTime;
                String CONN_STTS_CD          = pObj->DSTATE.Comm              == vms_normal ? "CMS0" : "CMS1";
                String CBOXFAN_STTS_CD       = pObj->DSTATE.ModuleState       == vms_normal ? "MOS0" : "MOS1";
                String PWER_STTS_CD          = pObj->DSTATE.ModulePowerStatus == vms_normal ? "PWS0" : "PWS1";
                String CBOXDOOR_OPEN_STTS_CD = pObj->DSTATE.DoorStatus        == vms_close  ? "CDS0" : "CDS1";
                String FAN_STTS_CD           = pObj->DSTATE.FanStatus         == vms_on     ? "PAS0" : "PAS1";
                String HETR_STTS_CD          = pObj->DSTATE.HeaterStatus      == vms_on     ? "HTS0" : "HTS1";
                String CBOX_TMPR             = String(pObj->DSTATE.BodyTemp);
                String CBOX_HMDT             = String(pObj->DSTATE.LuminanceStatus);
                if (CONN_STTS_CD != "CMS0")
                {
                    CBOXDOOR_OPEN_STTS_CD = "CDS2";
                    PWER_STTS_CD          = "PWS2";
                    CBOX_TMPR             = "0";
                    CBOX_HMDT             = "0";
                    FAN_STTS_CD           = "PAS2";
                    HETR_STTS_CD          = "HTS2";
                    CBOXFAN_STTS_CD       = "MOS2";
                }

                SQLBind(pADO, "p01", VMS_CTLR_NMBR);
                SQLBind(pADO, "p02", RGST_DT);
                SQLBind(pADO, "p03", CONN_STTS_CD);
                SQLBind(pADO, "p04", CBOXDOOR_OPEN_STTS_CD);
                SQLBind(pADO, "p05", PWER_STTS_CD);
                SQLBind(pADO, "p06", CBOX_TMPR);
                SQLBind(pADO, "p07", CBOX_HMDT);
                SQLBind(pADO, "p08", FAN_STTS_CD);
                SQLBind(pADO, "p09", HETR_STTS_CD);
                SQLBind(pADO, "p10", CBOXFAN_STTS_CD);
                SQLBind(pADO, "p11", HIST_INS);

                SQLExec(pADO);

#if 0
                if (pObj->FSaveState)
                {
                    //이전주기에 통신이상 이력을 입력하였고 이번에도 통신이상이면
                    //이력으로 저장하지 않는다.
                    if (pObj->DSTATE.Comm == vms_error &&
                        pObj->FOldState   == vms_error)
                    {
                        continue;
                    }

                    SQLBind(pADOI, "p01", VMS_CTLR_NMBR);
                    SQLBind(pADOI, "p02", RGST_DT);
                    SQLBind(pADOI, "p03", CONN_STTS_CD);
                    SQLBind(pADOI, "p04", CBOXDOOR_OPEN_STTS_CD);
                    SQLBind(pADOI, "p05", PWER_STTS_CD);
                    SQLBind(pADOI, "p06", CBOX_TMPR);
                    SQLBind(pADOI, "p07", CBOX_HMDT);
                    SQLBind(pADOI, "p08", FAN_STTS_CD);
                    SQLBind(pADOI, "p09", HETR_STTS_CD);
                    SQLBind(pADOI, "p10", CBOXFAN_STTS_CD);

                    SQLExec(pADOI);

                    pObj->FOldState = pObj->DSTATE.Comm;
                }
#endif
            }

            pADO->Connection->CommitTrans();

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(E.ClassName()) + E.Message;
            DBERRORLOG("SaveEquipStateAllProc", String(E.ClassName()), E.Message, sQry);
		}
		catch(Exception &e)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(e.ClassName()) + e.Message;
            DBERRORLOG("SaveEquipStateAllProc", String(e.ClassName()), e.Message, sQry);
		}
	}
	__finally
	{
        if (pADO)
        {
            SQLClose(pADO);
            SAFE_DELETE(pADO);
        }
#if 0
        if (pADOI)
        {
            SQLClose(pADOI);
            SAFE_DELETE(pADOI);
        }
#endif
	}

	return SendEquipStateAllProc();
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SendEquipStateAllProc(void)
{
	int               nResult = VERR_NONE;
    INT_VMS_STATE_RES Res;
    INT_VMS_STATE    *pVms;

    memset((char*)&Res, 0x00, sizeof(Res));
    Res.Total = VmsManager->Total;
    Res.Error = VmsManager->Error;
    Res.Normal= VmsManager->Normal;
    Res.Module= VmsManager->Module;

    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        if (pObj->Server.UseFlag != bit_enable) continue;

        pVms = &Res.Unit[Res.Count++];
        memcpy((char*)pVms, (char*)&pObj->DSTATE, sizeof(INT_VMS_STATE));
        if (Res.Count >= INT_MAX_VMS_STATE)
        {
            nResult = VComm_VmsStateNotify(&Res);

            memset((char*)&Res, 0x00, sizeof(Res));
            Res.Total = VmsManager->Total;
            Res.Error = VmsManager->Error;
            Res.Normal= VmsManager->Normal;
            Res.Module= VmsManager->Module;
        }
    }

    if (Res.Count > 0)
    {
        nResult = VComm_VmsStateNotify(&Res);
    }

	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SaveEquipStateProc(TVmsCtlr *AObj, int AServerState)
{
	int        nResult = VERR_NONE;
	AnsiString sQry;
	TADOQuery *pADO = NULL;

    if (!AObj) return nResult;

    TVmsCtlr *pObj = AObj;

    if (AServerState)
    {
        //VMS가 접속또는 종료인 경우(조건없이 업데이트)
        memcpy(&pObj->DSTATE, &pObj->RSTATE, sizeof(pObj->DSTATE));
    }
    else
    {
        //VMS클라이언트가 상태정보를 수집한 경우
        //상태정보가 바뀐경우만 업데이트
        pObj->FSaveState = ChangedState(&pObj->DSTATE, &pObj->RSTATE);
        if (!pObj->FSaveState) return nResult;
        //if (pObj->Server.Status != process_run) return nResult;
        memcpy(&pObj->DSTATE, &pObj->RSTATE, sizeof(pObj->DSTATE));
    }
    pObj->DSTATE.Comm = pObj->Client.Comm == state_open ? vms_normal : vms_error;//pObj->Server.Status == process_run ? vms_normal : vms_error;
    //pObj->FOldState = pObj->DSTATE.Comm;    //이전상태저장

    String sSysTime = Now().FormatString("yyyymmddhhnnss");

    sQry = "MERGE INTO TB_VMS_STTS_PRST L                                     \r\n"
           "USING (SELECT :p01 AS VMS_CTLR_NMBR,                              \r\n"
           "              :p02 AS RGST_DT,                                    \r\n"
           "              :p03 AS CONN_STTS_CD,                               \r\n"
           "              :p04 AS CBOXDOOR_OPEN_STTS_CD,                      \r\n"
           "              :p05 AS PWER_STTS_CD,                               \r\n"
           "              :p06 AS CBOX_TMPR,                                  \r\n"
           "              :p07 AS CBOX_HMDT,                                  \r\n"
           "              :p08 AS FAN_STTS_CD,                                \r\n"
           "              :p09 AS HETR_STTS_CD,                               \r\n"
           "              :p10 AS CBOXFAN_STTS_CD                             \r\n"
           "         FROM DUAL) M                                             \r\n"
           "ON (L.VMS_CTLR_NMBR = M.VMS_CTLR_NMBR)                            \r\n"
           "WHEN MATCHED THEN                                                 \r\n"
           "    UPDATE SET L.RGST_DT               = M.RGST_DT,               \r\n"
           "               L.CONN_STTS_CD          = M.CONN_STTS_CD,          \r\n"
           "               L.CBOXDOOR_OPEN_STTS_CD = M.CBOXDOOR_OPEN_STTS_CD, \r\n"
           "               L.PWER_STTS_CD          = M.PWER_STTS_CD,          \r\n"
           "               L.CBOX_TMPR             = M.CBOX_TMPR,             \r\n"
           "               L.CBOX_HMDT             = M.CBOX_HMDT,             \r\n"
           "               L.FAN_STTS_CD           = M.FAN_STTS_CD,           \r\n"
           "               L.HETR_STTS_CD          = M.HETR_STTS_CD,          \r\n"
           "               L.CBOXFAN_STTS_CD       = M.CBOXFAN_STTS_CD,       \r\n"
           "               L.HIST_INS              = '0'                      \r\n"
           "WHEN NOT MATCHED THEN                                             \r\n"
           "    INSERT (L.VMS_CTLR_NMBR,                                      \r\n"
           "            L.RGST_DT,                                            \r\n"
           "            L.CONN_STTS_CD,                                       \r\n"
           "            L.CBOXDOOR_OPEN_STTS_CD,                              \r\n"
           "            L.PWER_STTS_CD,                                       \r\n"
           "            L.CBOX_TMPR,                                          \r\n"
           "            L.CBOX_HMDT,                                          \r\n"
           "            L.FAN_STTS_CD,                                        \r\n"
           "            L.HETR_STTS_CD,                                       \r\n"
           "            L.CBOXFAN_STTS_CD, L.HIST_INS)                        \r\n"
           "    VALUES (M.VMS_CTLR_NMBR,                                      \r\n"
           "            M.RGST_DT,                                            \r\n"
           "            M.CONN_STTS_CD,                                       \r\n"
           "            M.CBOXDOOR_OPEN_STTS_CD,                              \r\n"
           "            M.PWER_STTS_CD,                                       \r\n"
           "            M.CBOX_TMPR,                                          \r\n"
           "            M.CBOX_HMDT,                                          \r\n"
           "            M.FAN_STTS_CD,                                        \r\n"
           "            M.HETR_STTS_CD,                                       \r\n"
           "            M.CBOXFAN_STTS_CD, '0')                               \r\n";

	try
	{
        pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            pADO->Connection->BeginTrans();

            SQLText(pADO, sQry, false);

            {
                String VMS_CTLR_NMBR         = pObj->VmsNo;
                String RGST_DT               = sSysTime;
                String CONN_STTS_CD          = pObj->DSTATE.Comm              == vms_normal ? "CMS0" : "CMS1";
                String CBOXFAN_STTS_CD       = pObj->DSTATE.ModuleState       == vms_normal ? "MOS0" : "MOS1";
                String PWER_STTS_CD          = pObj->DSTATE.ModulePowerStatus == vms_normal ? "PWS0" : "PWS1";
                String CBOXDOOR_OPEN_STTS_CD = pObj->DSTATE.DoorStatus        == vms_close  ? "CDS0" : "CDS1";
                String FAN_STTS_CD           = pObj->DSTATE.FanStatus         == vms_on     ? "PAS0" : "PAS1";
                String HETR_STTS_CD          = pObj->DSTATE.HeaterStatus      == vms_on     ? "HTS0" : "HTS1";
                String CBOX_TMPR             = String(pObj->DSTATE.BodyTemp);
                String CBOX_HMDT             = String(pObj->DSTATE.LuminanceStatus);

                if (CONN_STTS_CD != "CMS0" ||
                    AServerState == 1) //통신이 비정상이거나 VMS가 최초로 접속한 경우(상태정보를 알수 없다)
                {
                    CBOXDOOR_OPEN_STTS_CD = "CDS2";
                    PWER_STTS_CD          = "PWS2";
                    CBOX_TMPR             = "0";
                    CBOX_HMDT             = "0";
                    FAN_STTS_CD           = "PAS2";
                    HETR_STTS_CD          = "HTS2";
                    CBOXFAN_STTS_CD       = "MOS2";
                }

                SQLBind(pADO, "p01", VMS_CTLR_NMBR);
                SQLBind(pADO, "p02", RGST_DT);
                SQLBind(pADO, "p03", CONN_STTS_CD);
                SQLBind(pADO, "p04", CBOXDOOR_OPEN_STTS_CD);
                SQLBind(pADO, "p05", PWER_STTS_CD);
                SQLBind(pADO, "p06", CBOX_TMPR);
                SQLBind(pADO, "p07", CBOX_HMDT);
                SQLBind(pADO, "p08", FAN_STTS_CD);
                SQLBind(pADO, "p09", HETR_STTS_CD);
                SQLBind(pADO, "p10", CBOXFAN_STTS_CD);

                SQLExec(pADO);


#if 0
    // FOR PASIG
    sQry = "UPDATE TB_VMS_CTLR                   \r\n"
           "   SET VMS_PHSE_CHNG_CYCL    = :p01, \r\n"
           "       VMS_CMNC_ERR_BASS_VAL = :p02, \r\n"
           "       FAN_MTNS_TMPR         = :p03, \r\n"
           "       HETR_MTNS_TMPR        = :p04, \r\n"
           "       VMS_MODL_ERR_RATE     = :p05  \r\n"
           " WHERE VMS_CTLR_NMBR = :p06          \r\n";

                if (AServerState == 0)  //상태정보를 정상적으로 수집한 경우에만
                {
                    if (pObj->VMS_PHSE_CHNG_CYCL    != pObj->DSTATE.ScheduledMessageOperatingTime ||
                        pObj->VMS_CMNC_ERR_BASS_VAL != pObj->DSTATE.ModuleOperatingTemperature    ||
                        pObj->FAN_MTNS_TMPR         != pObj->DSTATE.FanOperatingTemperature       ||
                        pObj->HETR_MTNS_TMPR        != pObj->DSTATE.HeaterOperatingTemperature    ||
                        pObj->VMS_MODL_ERR_RATE     != pObj->DSTATE.ModuleBasicFailureRate        )
                    {
                        pObj->VMS_PHSE_CHNG_CYCL    = pObj->DSTATE.ScheduledMessageOperatingTime;
                        pObj->VMS_CMNC_ERR_BASS_VAL = pObj->DSTATE.ModuleOperatingTemperature;
                        pObj->FAN_MTNS_TMPR         = pObj->DSTATE.FanOperatingTemperature;
                        pObj->HETR_MTNS_TMPR        = pObj->DSTATE.HeaterOperatingTemperature;
                        pObj->VMS_MODL_ERR_RATE     = pObj->DSTATE.ModuleBasicFailureRate;

                        SQLText(pADO, sQry, false);

                        SQLBind(pADO, "p01", pObj->VMS_PHSE_CHNG_CYCL);
                        SQLBind(pADO, "p02", pObj->VMS_CMNC_ERR_BASS_VAL);
                        SQLBind(pADO, "p03", pObj->FAN_MTNS_TMPR);
                        SQLBind(pADO, "p04", pObj->HETR_MTNS_TMPR);
                        SQLBind(pADO, "p05", pObj->VMS_MODL_ERR_RATE);
                        SQLBind(pADO, "p06", VMS_CTLR_NMBR);

                        SQLExec(pADO);
                    }
                }
#endif
            }
            pADO->Connection->CommitTrans();

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(E.ClassName()) + E.Message;
            DBERRORLOG("SaveEquipStateProc", String(E.ClassName()), E.Message, sQry);
		}
		catch(Exception &e)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(e.ClassName()) + e.Message;
            DBERRORLOG("SaveEquipStateProc", String(e.ClassName()), e.Message, sQry);
		}
	}
	__finally
	{
        if (pADO)
        {
            SQLClose(pADO);
            SAFE_DELETE(pADO);
        }
	}

    //상태정보를 클라이언트로 전송
    INT_VMS_STATE_RES Res;
    memset((char*)&Res, 0x00, sizeof(Res));
    Res.Total = VmsManager->Total;
    Res.Error = VmsManager->Error;
    Res.Normal= VmsManager->Normal;
    Res.Module= VmsManager->Module;
    Res.Count = 1;
    memcpy((char*)&Res.Unit[0], (char*)&pObj->DSTATE, sizeof(INT_VMS_STATE));
    nResult = VComm_VmsStateNotify(&Res);
	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::DataSaveProc(void *pData)
{
#if 0
	int              nResult;
	SET_INFO_STRUCT *pSet;

	nResult = VERR_NONE;

    if (!pData) return VERR_OTHER;

    try
    {
        pSet = (SET_INFO_STRUCT *)pData;

        switch(pSet->CtlType)
        {
        case CTL_TYPE_PARA_SET:
            break;
        case CTL_TYPE_MODULE_ON:
        case CTL_TYPE_MODULE_OFF:
        case CTL_TYPE_RESET:
            break;
        }
    }
    __finally
    {
        delete[] (char *)pData;
    }

	return nResult;
#else
return 0;
#endif
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::LoadIfscTrafficInfo()
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;

    LINFO("LoadIfscTrafficInfo: Start");

    sQry = "SELECT A.VMS_IFSC_ID, A.VMS_IFSC_NM, A.DSPL_STRT_NODE_NM, A.DSPL_END_NODE_NM, \r\n"
           "       A.ROAD_NM, A.SPOT_NM,                                                  \r\n"
           "       A.DETR_ID, A.AXIS_YN,                                                  \r\n"
           "       NVL(B.RGST_DT,       '') AS RGST_DT,                                   \r\n"
           "       NVL(B.CMTR_GRAD_CD, '0') AS CMTR_GRAD_CD,                              \r\n"
           "       NVL(B.SPED,           0) AS SPED,                                      \r\n"
           "       NVL(B.TRVL_HH,        0) AS TRVL_HH                                    \r\n"
           "  FROM TB_VMS_IFSC A,                                                         \r\n"
           "       (SELECT *                                                              \r\n"
           "          FROM TB_VMS_CMTRINFR                                                \r\n"
           "         WHERE RGST_DT >= TO_CHAR(SYSDATE-10/1440, 'YYYYMMDDHH24MISS') ) B    \r\n"
           " WHERE A.VMS_IFSC_ID = B.VMS_IFSC_ID(+)                                       \r\n";

    FOR_STL(TCDSIfsc*, pObj, IfscManager->FLists)
    {
        pObj->CMTR_GRAD_CD = "0";
        pObj->TRVL_HH      = 0;
        pObj->SPED         = 0;
    }

    try
    {
        TCDSIfsc *pIfsc;
        try
        {
            pADO = new TADOQuery(NULL);
			pADO->Close();
            pADO->Connection = GetDbConnection();
			pADO->SQL->Clear();
			pADO->SQL->Text = sQry;

			pADO->Open();
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VMS_IFSC_ID = pADO->FieldByName("VMS_IFSC_ID")->AsString.Trim();
				pIfsc = IfscManager->FLists.Find(VMS_IFSC_ID);
                if (!pIfsc)
                {
                    pIfsc = new TCDSIfsc();
                    pIfsc->VMS_IFSC_ID = VMS_IFSC_ID;
                    IfscManager->FLists.Push(pIfsc->VMS_IFSC_ID, pIfsc);
                }

                pIfsc->VMS_IFSC_NM       = pADO->FieldByName("VMS_IFSC_NM")->AsString;
                pIfsc->DSPL_STRT_NODE_NM = pADO->FieldByName("DSPL_STRT_NODE_NM")->AsString;
                pIfsc->DSPL_END_NODE_NM  = pADO->FieldByName("DSPL_END_NODE_NM")->AsString;
                pIfsc->DETR_ID           = pADO->FieldByName("DETR_ID")->AsString;
                pIfsc->ROAD_NM           = pADO->FieldByName("ROAD_NM")->AsString;
                pIfsc->SPOT_NM           = pADO->FieldByName("SPOT_NM")->AsString;
                pIfsc->AXIS_YN           = pADO->FieldByName("AXIS_YN")->AsString;

                pIfsc->RGST_DT      = pADO->FieldByName("RGST_DT")->AsString;
                pIfsc->CMTR_GRAD_CD = pADO->FieldByName("CMTR_GRAD_CD")->AsString;
                pIfsc->SPED         = pADO->FieldByName("SPED")->AsInteger;
                pIfsc->TRVL_HH      = pADO->FieldByName("TRVL_HH")->AsInteger;

                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            ErrorString = String(E.ClassName()) + E.Message;
            return VERR_OTHER;
        }
        catch(Exception &e)
        {
            ErrorString = String(e.ClassName()) + e.Message;
            return VERR_OTHER;
        }
    }
    __finally
    {
        if (pADO)
        {
            pADO->Close();
            delete pADO;
        }
    }

    if (0)
    {
        FOR_STL(TCDSIfsc*, pTmp, IfscManager->FLists)
        {
            try
            {
                LDEBUG("Ifsc: %s, Grad: %s", pTmp->VMS_IFSC_ID.c_str(), pTmp->CMTR_GRAD_CD.c_str());
            }
            catch(Exception &e)
            {
            }
        }
    }

    LINFO("LoadIfscTrafficInfo: %d EA", nSelCnt);

    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::ClearVmsProvideMode(AnsiString AVmsId)
{
    int        nSelCnt= 0;

    LINFO("ClearVmsProvideMode: Start");

    FFormDsplDt = Now().FormatString("yyyymmddhhnnss");

    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;

        if (!pObj->FProvide) continue;

        pObj->CTLMODE->MaxDisplayForm = 0;//pObj->VMS_MAX_PHSE_NUM; //0
        pObj->CTLMODE->Enable         = object_disable;
        pObj->CTLMODE->SvcDate        = FFormDsplDt;
        pObj->CTLMODE->SaveFlag       = -1;
        pObj->CTLMODE->pTimer         = Now();
        pObj->CTLMODE->Result         = false;

        ScheduleInit(pObj->SCHEDULE);   //스케줄정보
        EventInit(pObj->INCIDENT);      //돌발정보
        EventInit(pObj->EVENT);         //이벤트(공사/행사)정보

        pObj->pForms->Clear();

        nSelCnt++;
    }
    LINFO("ClearVmsProvideMode: %d EA", nSelCnt);
    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::LoadVmsScheduleInfo(AnsiString AVmsId)
{
	int         nResult;
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

	nResult = VERR_OTHER;

    LINFO("LoadVmsScheduleInfo: Start");

    sQry = "SELECT B.*, DECODE(B.TRFC_SITU_TYPE_CD, '0', 7,               \r\n"
           "                                        '1', 3,               \r\n"
           "                                        '2', 4,               \r\n"
           "                                        '3', 5,               \r\n"
           "                                        '4', 6,               \r\n"
           "                                        '5', 1,               \r\n"
           "                                        '6', 0,               \r\n"
           "                                        '7', 8, 9) AS SCHPRIT \r\n"
           "  FROM TB_VMS_CTLR A,                                         \r\n"
           "       TB_VMS_TRFC_INFR_DSPL_SCH B,                           \r\n"
           "       TB_VMS_FORM C                                          \r\n"
           " WHERE A.DEL_YN = 'N'                                         \r\n"
           "   AND A.VMS_CTLR_NMBR = B.VMS_CTLR_NMBR                      \r\n"
           "   AND B.VMS_FORM_ID   = C.VMS_FORM_ID                        \r\n"
           "   AND B.USE_YN        = 'Y'                                  \r\n"
           "   AND TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') BETWEEN           \r\n"
           "       B.DSPL_STRT_HH AND B.DSPL_END_HH                       \r\n";

    sQry = "SELECT * \r\n"
           "  FROM ( \r\n" + sQry +
           "       ) \r\n"
           " ORDER BY VMS_CTLR_NMBR ASC, SCHPRIT ASC, PHASE ASC \r\n";

	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

            int  nIdx;
            int  TRFC_SITU_TYPE_CD;
            bool bBottomTraffic;
            TCDSIfsc *pCDSIfsc;

			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString sVmsNmbr    = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;
                AnsiString VMS_FORM_ID = pADO->FieldByName("VMS_FORM_ID")->AsString;

                //스케줄 유형 코드(0:교통정보,1:돌발,2:공사/행사문안,3:홍보문안,4:우회도로,5:고정스케줄, 6:기본스케줄, 7:정체상황)
                TRFC_SITU_TYPE_CD = pADO->FieldByName("TRFC_SITU_TYPE_CD")->AsString.ToIntDef(-1);

                if (TRFC_SITU_TYPE_CD < enFormTraffic||
                    TRFC_SITU_TYPE_CD > enFormCongest)
                {
                    LERROR("VMS Schedule Unknown Type: VmsNmbr(%s)-[%s.%d]", sVmsNmbr.c_str(), VMS_FORM_ID.c_str(), TRFC_SITU_TYPE_CD);
                    continue;
                }

                TVmsCtlr *pObj = VmsManager->FLists.Find(sVmsNmbr);
                if (!pObj) continue;

                if (!pObj->FProvide) continue;

                TCDSForm *pForm = FormManager->FLists.Find(VMS_FORM_ID);
                if (!pForm)
                {
                    LERROR("VMS Schedule Not Found Form: VmsNmbr(%s)-[%s]", sVmsNmbr.c_str(), VMS_FORM_ID.c_str());
                    continue;
                }

                if (pObj->SCHEDULE->Count >= VMS_MAX_SCHEDULE)
                {
                    LERROR("VMS Schedule Count Over: %s, %d", sVmsNmbr.c_str(), pObj->SCHEDULE->Count);
                    continue;
                }

                if (pObj->CTLMODE->Control == 'F')
                {
                    //고정스케쥴인 경우 고정스케쥴정보만 등록한다.
                    if (TRFC_SITU_TYPE_CD != enFormFixed) continue;
                }
                else
                if (pObj->CTLMODE->Control == 'B')
                {
                    //기본스케쥴인 경우 기본스케쥴정보만 등록한다.
                    if (TRFC_SITU_TYPE_CD != enFormBase) continue;
                }
                else
                {
                    //자동시케쥴인 경우 고정스케쥴, 기본스케쥴 체크
                    if (TRFC_SITU_TYPE_CD == enFormFixed || TRFC_SITU_TYPE_CD == enFormBase)
                    {
                        continue; //여기 걸리면 프로그램적으로 오류가 발생한 거임
                    }
                }

                //TODO: 조회정렬은 기본,고정,자동(돌발,공사,행사,우회,교통,정체폼) 순으로 조회된다.
                //      따라서 각 폼에 대한처리를 수행하면 된다.

                if (TRFC_SITU_TYPE_CD == enFormTraffic && pForm->VMS_FORM_TYPE_CD == enFormKindTrfRow1)
                {
                    //교통정보스케쥴이고 폼의 유형이  소통정보(1단) 인경우....
                    //해당 폼이 돌발이나 이벤트가 등록되어 있다면
                    //폼을 생성하지 않는다.

                    AnsiString FRST_VMS_IFSC_ID = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;

                    if (FRST_VMS_IFSC_ID != "")
                    {
                        for (int ii = 0; ii < pObj->SCHEDULE->Count && ii < VMS_MAX_SCHEDULE; ii++)
                        {
                            if (pObj->SCHEDULE->Unit[ii].TRFC_SITU_TYPE_CD == enFormDolbal ||  //돌발
                                pObj->SCHEDULE->Unit[ii].TRFC_SITU_TYPE_CD == enFormGongsa ||  //공사/행사
                                pObj->SCHEDULE->Unit[ii].TRFC_SITU_TYPE_CD == enFormDeture )   //우회
                            {
                                if (pObj->SCHEDULE->Unit[ii].EVENT)
                                {
                                    if (FRST_VMS_IFSC_ID == pObj->SCHEDULE->Unit[ii].EVENT->VMS_IFSC_ID)
                                    {
                                        //폼을 생성하지 않는다.
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                }

                bBottomTraffic = false;
                switch(TRFC_SITU_TYPE_CD)
                {
                case enFormTraffic:     //교통정보
                    //정보제공구간 하단 소통정보
                    if (pForm->VMS_FORM_TYPE_CD == enFormKindTrfImg && pForm->TrfIfsc)
                    {
                        //도형식 VMS인 경우 하단에 소통정보를 표출하는 경우 다중폼이 생성됨
                        //제공구간소통정보가 정체, 지체인 경우만 하단 소통정보를 표출함
#if 0
                        FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                        {
                            pCDSIfsc = IfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                            if (!pCDSIfsc) continue;

                            if (pCDSIfsc->AXIS_YN == "Y") continue;
                            if (pCDSIfsc->CMTR_GRAD_CD == "3" || pCDSIfsc->CMTR_GRAD_CD == "2")
                            {
                                bBottomTraffic = true;
                                break;
                            }
                        }
#else
                        //도형식 배경셀에 등록된 구간에 대해서 표출하도록 수정(20161124)
                        TCDSImage *pBakTrfImg = ImageManager->FLists.Find(pForm->TrfBakImgId);
                        if (pBakTrfImg)
                        {
                            FOR_STL(TCDSImageCell*, pCell, pBakTrfImg->FLists)
                            {
                                TCDSIfsc *pTmpIfsc1 = IfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                if (pTmpIfsc1)
                                {
                                    if (pTmpIfsc1->CMTR_GRAD_CD == "3" || pTmpIfsc1->CMTR_GRAD_CD == "2")
                                    {
                                        bBottomTraffic = true;
                                        break;
                                    }
                                }
                            }
                        }
#endif
                    }

                    //정보제공구간 축 하단 소통정보
                    if (pForm->VMS_FORM_TYPE_CD == enFormKindTrfImg && pForm->TrfAxis)
                    {
                        //도형식 VMS인 경우 하단에 소통정보를 표출하는 경우 다중폼이 생성됨
                        //축 소통정보인 경우 모든 축에 대해 소통정보를 표출
                        FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                        {
                            pCDSIfsc = IfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                            if (!pCDSIfsc) continue;

                            if (pCDSIfsc->AXIS_YN != "Y") continue;
                            if (pCDSIfsc->CMTR_GRAD_CD != "0")
                            {
                                bBottomTraffic = true;
                                break;
                            }
                        }
                    }

                    if (bBottomTraffic)
                    {
                        //도형식 다중 소통정보 표출인 경우
                        //하단소통정보를 표출하는경우 정체, 지체 순으로 표출
                        if (pForm->TrfIfsc)
                        {
                            //정보제공구간 소통정보 순환표출(정체)
#if 0
                            FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                            {
                                pCDSIfsc = IfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                                if (!pCDSIfsc) continue;

                                if (pCDSIfsc->AXIS_YN == "Y") continue;
                                if (pCDSIfsc->CMTR_GRAD_CD != "3") continue;

                                nIdx = pObj->SCHEDULE->Count;
                                if (nIdx < VMS_MAX_SCHEDULE)
                                {
                                    nIdx = pObj->SCHEDULE->Count;
                                    pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                                    pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pIfsc->VMS_IFSC_ID;  //하단 제공구간 ID
                                    pObj->SCHEDULE->Count++;
                                    nSelCnt++;
                                }
                            }
#else
                            //도형식 배경셀에 등록된 구간에 대해서 표출하도록 수정(20161124)
                            TCDSImage *pBakTrfImg1 = ImageManager->FLists.Find(pForm->TrfBakImgId);
                            if (pBakTrfImg1)
                            {
                                FOR_STL(TCDSImageCell*, pCell, pBakTrfImg1->FLists)
                                {
                                    TCDSIfsc *pTmpIfsc1 = IfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                    if (!pTmpIfsc1) continue;

                                    if (pTmpIfsc1->CMTR_GRAD_CD != "3") continue;

                                    nIdx = pObj->SCHEDULE->Count;
                                    if (nIdx < VMS_MAX_SCHEDULE)
                                    {
                                        nIdx = pObj->SCHEDULE->Count;
                                        pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                                        pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                        pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pCell->VMS_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pCell->VMS_IFSC_ID;  //하단 제공구간 ID
                                        pObj->SCHEDULE->Count++;
                                        nSelCnt++;
                                    }
                                }
                            }
#endif
                            //정보제공구간 소통정보 순환표출(지체)
#if 0
                            FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                            {
                                pCDSIfsc = IfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                                if (!pCDSIfsc) continue;

                                if (pCDSIfsc->AXIS_YN == "Y") continue;
                                if (pCDSIfsc->CMTR_GRAD_CD != "2") continue;

                                nIdx = pObj->SCHEDULE->Count;
                                if (nIdx < VMS_MAX_SCHEDULE)
                                {
                                    nIdx = pObj->SCHEDULE->Count;
                                    pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                                    pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pIfsc->VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pIfsc->VMS_IFSC_ID;  //하단 제공구간 ID
                                    pObj->SCHEDULE->Count++;
                                    nSelCnt++;
                                }
                            }
#else
                            //도형식 배경셀에 등록된 구간에 대해서 표출하도록 수정(20161124)
                            TCDSImage *pBakTrfImg2 = ImageManager->FLists.Find(pForm->TrfBakImgId);
                            if (pBakTrfImg2)
                            {
                                FOR_STL(TCDSImageCell*, pCell, pBakTrfImg2->FLists)
                                {
                                    TCDSIfsc *pTmpIfsc1 = IfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                    if (!pTmpIfsc1) continue;

                                    if (pTmpIfsc1->CMTR_GRAD_CD != "2") continue;

                                    nIdx = pObj->SCHEDULE->Count;
                                    if (nIdx < VMS_MAX_SCHEDULE)
                                    {
                                    nIdx = pObj->SCHEDULE->Count;
                                    pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                                    pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pCell->VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pCell->VMS_IFSC_ID;  //하단 제공구간 ID
                                    pObj->SCHEDULE->Count++;
                                    nSelCnt++;
                                    }
                                }
                            }
#endif
                        }

                        if (pForm->TrfAxis)
                        {
                            //축소통정보 순환표출
                            FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                            {
                                pCDSIfsc = IfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                                if (!pCDSIfsc) continue;

                                if (pCDSIfsc->AXIS_YN != "Y") continue;
                                if (pCDSIfsc->CMTR_GRAD_CD == "0") continue;

                                nIdx = pObj->SCHEDULE->Count;
                                if (nIdx < VMS_MAX_SCHEDULE)
                                {
                                    nIdx = pObj->SCHEDULE->Count;
                                    pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                                    pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pIfsc->VMS_IFSC_ID;  //하단 제공구간 ID
                                    pObj->SCHEDULE->Count++;
                                    nSelCnt++;
                                }
                            }
                        }
                    }
                    else
                    {
                        //도형식 다중표출이 아닌경우(하단소통정보가 없는 경우)
                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case enFormDolbal:  //돌발
                    //돌발 스케줄인 경우 해당 VMS에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가
                    for (int ii = 0; ii < pObj->INCIDENT->Count; ii++)
                    {
                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->INCIDENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->INCIDENT->Unit[ii];
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case enFormGongsa:  //공사/행사문안
                    //공사/행사 스케줄인 경우 해당 VMS에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가
                    for (int ii = 0; ii < pObj->EVENT->Count; ii++)
                    {
                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->EVENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->EVENT->Unit[ii];
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case enFormDeture:  //우회도로
                    //돌발발생한 구간중 우회도로 구간이 있는경우
                    for (int ii = 0; ii < pObj->INCIDENT->Count; ii++)
                    {
                        if (pObj->INCIDENT->Unit[ii].DETR_ID == "0") continue;

                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->INCIDENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->INCIDENT->Unit[ii];
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }

                    //공사/행사 발생한 구간중 우회도로 구간이 있는경우
                    for (int ii = 0; ii < pObj->EVENT->Count; ii++)
                    {
                        if (pObj->EVENT->Unit[ii].DETR_ID == "0") continue;

                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->EVENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->EVENT->Unit[ii];
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case enFormHongbo:  //홍보
                case enFormFixed:   //고정스케줄
                case enFormBase:    //기본스케줄
                    nIdx = pObj->SCHEDULE->Count;
                    if (nIdx < VMS_MAX_SCHEDULE)
                    {
                        pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                        pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                        pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                        pObj->SCHEDULE->Count++;
                        nSelCnt++;
                    }
                    break;
                case enFormCongest: //정체상황
                    //스케쥴에 등록된 제공구간의 속도가 5km/h 이하인 경우에만 표출
                    {
                        bool bDup = false;
                        AnsiString sVmsIfscId[4];
                        int nObjCnt = pObj->SCHEDULE->Count;

                        for (int ii = 0; ii < nObjCnt && ii < VMS_MAX_SCHEDULE; ii++)
                        {
                            sVmsIfscId[0] = "";
                            sVmsIfscId[1] = "";
                            sVmsIfscId[2] = "";
                            sVmsIfscId[3] = "";

                            switch(pObj->SCHEDULE->Unit[ii].TRFC_SITU_TYPE_CD)
                            {
                            case enFormDolbal: //돌발
                            case enFormGongsa: //공사/행사
                            case enFormDeture: //우회
                                sVmsIfscId[0] = pObj->SCHEDULE->Unit[ii].VMS_IFSC_ID;
                                break;
                            case enFormTraffic:
                                sVmsIfscId[0] = pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID;
                                sVmsIfscId[1] = pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID;
                                sVmsIfscId[2] = pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID;
                                sVmsIfscId[3] = pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID;
                                //도형식인 경우 체크확인 해야함
                                break;
                            case enFormHongbo:
                            case enFormFixed:
                            case enFormBase:
                            case enFormCongest:
                            default: continue;
                            }

                            for (int kk = 0; kk < 4; kk++)
                            {
                                if (sVmsIfscId[kk] == "") continue;

                                pCDSIfsc = IfscManager->FLists.Find(sVmsIfscId[kk]);
                                if (pCDSIfsc)
                                {
                                    if (pCDSIfsc->CMTR_GRAD_CD == "3" && pCDSIfsc->SPED <= 5)
                                    {
                                        bDup = false;
                                        for (int jj = nObjCnt-1; jj < pObj->SCHEDULE->Count && ii < VMS_MAX_SCHEDULE; ii++)
                                        {
                                            if (pObj->SCHEDULE->Unit[jj].TRFC_SITU_TYPE_CD != enFormCongest) continue;
                                            if (pObj->SCHEDULE->Unit[jj].VMS_IFSC_ID == sVmsIfscId[kk])
                                            {
                                                bDup = true;
                                                break;
                                            }
                                        }

                                        if (bDup) continue;

                                        nIdx = pObj->SCHEDULE->Count;
                                        if (nIdx < VMS_MAX_SCHEDULE)
                                        {
                                            pObj->SCHEDULE->Unit[nIdx].TRFC_SITU_TYPE_CD = TRFC_SITU_TYPE_CD;
                                            pObj->SCHEDULE->Unit[nIdx].PHASE             = pADO->FieldByName("PHASE")->AsInteger;
                                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = pADO->FieldByName("DSPL_HH")->AsInteger;
                                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_PRRT_CD  = pADO->FieldByName("VMS_FORM_PRRT_CD")->AsString;
                                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = sVmsIfscId[kk];
                                            pObj->SCHEDULE->Count++;
                                            nSelCnt++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
			}

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            ErrorString = String(E.ClassName()) + E.Message;
		}
		catch(Exception &e)
		{
            ErrorString = String(e.ClassName()) + e.Message;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    if (0)
    {
        VmsIterator it;
        for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
        {
            TVmsCtlr *pObj = (TVmsCtlr*)it->second;

            if (pObj->Server.UseFlag != bit_enable) continue;
            LDEBUG("VMS Schedule: %s, %d EA", pObj->VmsNo.c_str(), pObj->SCHEDULE->Count);
        }
    }

    LINFO("LoadVmsScheduleInfo: %d EA", nSelCnt);

	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::LoadVmsEventOccrInf(AnsiString AVmsId)
{
	int         nResult;
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

	nResult = VERR_OTHER;

    LINFO("LoadVmsEventOccrInf: Start");

    sQry = "SELECT V.VMS_CTLR_NMBR, V.LINK_ID, V.IFSC_ID, V.VMS_IFSC_ID,   \r\n"
           "       V.VMS_IFSC_NM, V.DSPL_STRT_NODE_NM, V.DSPL_END_NODE_NM, \r\n"
           "       V.DETR_ID, V.DSPL_PRRT, I.INCD_OCRR_ID, I.STRT_LCTN_NM, \r\n"
           "       V.ROAD_NM, V.SPOT_NM,                                   \r\n"
           "       I.END_LCTN_NM, I.OCRR_LCTN_NM,                          \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                  \r\n"
           "         FROM TB_CMMN_CD                                       \r\n"
           "        WHERE CMMN_CD = I.VMS_INCD_TYPE_CD                     \r\n"
           "          AND CMMN_CLSF_CD = 'VIT') AS VMS_INCD_TYPE_NM,       \r\n"
           "       I.VMS_INCD_TYPE_CD,                                     \r\n"
           "       CASE WHEN I.VMS_INCD_TYPE_CD = 'VIT1' THEN              \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                  \r\n"
           "          FROM TB_CMMN_CD                                      \r\n"
           "         WHERE CMMN_CD      = I.VMS_INCD_DETL_TYPE_CD          \r\n"
           "           AND CMMN_CLSF_CD = 'IDT')                           \r\n"
           "       ELSE                                                    \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                  \r\n"
           "          FROM TB_CMMN_CD                                      \r\n"
           "         WHERE CMMN_CD      = I.VMS_INCD_DETL_TYPE_CD          \r\n"
           "           AND CMMN_CLSF_CD = 'EDT')                           \r\n"
           "       END AS VMS_INCD_DETL_NM,                                \r\n"
           "       I.VMS_INCD_DETL_TYPE_CD,                                \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                  \r\n"
           "          FROM TB_CMMN_CD                                      \r\n"
           "         WHERE CMMN_CD      = I.CMTR_GRAD_CD                   \r\n"
           "           AND CMMN_CLSF_CD = 'LTC') AS CMTR_GRAD_NM,          \r\n"
           "       I.CMTR_GRAD_CD,                                         \r\n"
           "       I.INCD_CLSR_LANE,                                       \r\n"
           "       I.INCD_STRT_DT,                                         \r\n"
           "       I.INCD_END_PRAR_DT                                      \r\n"
           "  FROM (SELECT D.VMS_CTLR_NMBR, A.LINK_ID,                     \r\n"
           "               A.IFSC_ID, B.VMS_IFSC_ID,                       \r\n"
           "               C.VMS_IFSC_NM,                                  \r\n"
           "               C.DSPL_STRT_NODE_NM,                            \r\n"
           "               C.DSPL_END_NODE_NM,                             \r\n"
           "               NVL(C.DETR_ID, 0) AS DETR_ID,                   \r\n"
           "               C.ROAD_NM, C.SPOT_NM,                           \r\n"
           "               D.DSPL_PRRT                                     \r\n"
           "          FROM TB_IFSC_LINK_RLTN A,                            \r\n"
           "               TB_VMS_LINK_IFSC  B,                            \r\n"
           "               TB_VMS_IFSC       C,                            \r\n"
           "               TB_VMS_IFSC_RLTN  D                             \r\n"
           "         WHERE A.IFSC_ID     = B.IFSC_ID                       \r\n"
           "           AND B.VMS_IFSC_ID = C.VMS_IFSC_ID                   \r\n"
           "           AND C.VMS_IFSC_ID = D.VMS_IFSC_ID ) V,              \r\n"
           "       (SELECT *                                               \r\n"
           "          FROM TB_INCD_OCRR_VMS                                \r\n"
           "         WHERE INCD_PRGR_STEP_CD = 'ISS2'                      \r\n"
           "           AND VMS_DSPL_YN       = 'Y'                         \r\n"
           "           AND VMS_INCD_TYPE_CD IN ('VIT1', 'VIT2') ) I        \r\n"
           " WHERE V.LINK_ID = I.LINK_ID                                   \r\n"
           " ORDER BY V.VMS_CTLR_NMBR                                      \r\n";

	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

            int nIdx;
			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString sVmsNmbr = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;

                TVmsCtlr *pObj = VmsManager->FLists.Find(sVmsNmbr);
                if (!pObj) continue;

                if (!pObj->FProvide) continue;

                AnsiString VMS_INCD_TYPE_CD = pADO->FieldByName("VMS_INCD_TYPE_CD")->AsString;
                AnsiString INCD_OCRR_ID     = pADO->FieldByName("INCD_OCRR_ID")->AsString;

                VMS_EVENT_INFO *pEvt;
                if (VMS_INCD_TYPE_CD ==  "VIT1")
                {
                    if (pObj->INCIDENT->Count >= VMS_MAX_EVENT)
                    {
                        LERROR("VMS Incident Over: %s, %d", pObj->VmsNo.c_str(), pObj->INCIDENT->Count);
                        continue;
                    }
                    bool bDup = false;
                    for (int ii = 0; ii < pObj->INCIDENT->Count; ii++)
                    {
                        if (INCD_OCRR_ID == pObj->INCIDENT->Unit[ii].INCD_OCRR_ID)
                        {
                            bDup = true;
                            break;
                        }
                    }
                    if (bDup)
                    {
                        LERROR("VMS Incident dup: %s, %s", pObj->VmsNo.c_str(), INCD_OCRR_ID.c_str());
                        continue;
                    }
                    nIdx = pObj->INCIDENT->Count;
                    pEvt = pObj->INCIDENT;
                }
                else
                {
                    if (pObj->EVENT->Count >= VMS_MAX_EVENT)
                    {
                        LERROR("VMS Event Over: %s, %d", pObj->VmsNo.c_str(), pObj->EVENT->Count);
                        continue;
                    }
                    bool bDup = false;
                    for (int ii = 0; ii < pObj->EVENT->Count; ii++)
                    {
                        if (INCD_OCRR_ID == pObj->EVENT->Unit[ii].INCD_OCRR_ID)
                        {
                            bDup = true;
                            break;
                        }
                    }
                    if (bDup)
                    {
                        LERROR("VMS Event dup: %s, %s", pObj->VmsNo.c_str(), INCD_OCRR_ID.c_str());
                        continue;
                    }
                    nIdx = pObj->EVENT->Count;
                    pEvt = pObj->EVENT;
                }

                pEvt->Unit[nIdx].LINK_ID                = pADO->FieldByName("LINK_ID")->AsString;
                pEvt->Unit[nIdx].IFSC_ID                = pADO->FieldByName("IFSC_ID")->AsString;
                pEvt->Unit[nIdx].VMS_IFSC_ID            = pADO->FieldByName("VMS_IFSC_ID")->AsString;
                pEvt->Unit[nIdx].VMS_IFSC_NM            = pADO->FieldByName("VMS_IFSC_NM")->AsString;
                pEvt->Unit[nIdx].DSPL_STRT_NODE_NM      = pADO->FieldByName("DSPL_STRT_NODE_NM")->AsString;
                pEvt->Unit[nIdx].DSPL_END_NODE_NM       = pADO->FieldByName("DSPL_END_NODE_NM")->AsString;
                pEvt->Unit[nIdx].DETR_ID                = pADO->FieldByName("DETR_ID")->AsString.Trim();
                pEvt->Unit[nIdx].DSPL_PRRT              = pADO->FieldByName("DSPL_PRRT")->AsString;
                pEvt->Unit[nIdx].INCD_OCRR_ID           = INCD_OCRR_ID;
                pEvt->Unit[nIdx].STRT_LCTN_NM           = pADO->FieldByName("STRT_LCTN_NM")->AsString;
                pEvt->Unit[nIdx].END_LCTN_NM            = pADO->FieldByName("END_LCTN_NM")->AsString;

                if (pEvt->Unit[nIdx].STRT_LCTN_NM == "")
                {
                    pEvt->Unit[nIdx].STRT_LCTN_NM = pEvt->Unit[nIdx].DSPL_STRT_NODE_NM;
                }
                if (pEvt->Unit[nIdx].END_LCTN_NM == "")
                {
                    pEvt->Unit[nIdx].END_LCTN_NM = pEvt->Unit[nIdx].DSPL_END_NODE_NM;
                }

                pEvt->Unit[nIdx].OCRR_LCTN_NM           = pADO->FieldByName("OCRR_LCTN_NM")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_TYPE_NM       = pADO->FieldByName("VMS_INCD_TYPE_NM")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_TYPE_CD       = pADO->FieldByName("VMS_INCD_TYPE_CD")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_DETL_NM       = pADO->FieldByName("VMS_INCD_DETL_NM")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_DETL_TYPE_CD  = pADO->FieldByName("VMS_INCD_DETL_TYPE_CD")->AsString;
                pEvt->Unit[nIdx].CMTR_GRAD_NM           = pADO->FieldByName("CMTR_GRAD_NM")->AsString;
                pEvt->Unit[nIdx].CMTR_GRAD_CD           = pADO->FieldByName("CMTR_GRAD_CD")->AsString;
                pEvt->Unit[nIdx].INCD_CLSR_LANE         = pADO->FieldByName("INCD_CLSR_LANE")->AsString;
                pEvt->Unit[nIdx].INCD_STRT_DT           = pADO->FieldByName("INCD_STRT_DT")->AsString;
                pEvt->Unit[nIdx].INCD_END_PRAR_DT       = pADO->FieldByName("INCD_END_PRAR_DT")->AsString;
                pEvt->Unit[nIdx].ROAD_NM                = pADO->FieldByName("ROAD_NM")->AsString;
                pEvt->Unit[nIdx].SPOT_NM                = pADO->FieldByName("SPOT_NM")->AsString;

                pEvt->Count++;

                nSelCnt++;
			}

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            ErrorString = String(E.ClassName()) + E.Message;
		}
		catch(Exception &e)
		{
            ErrorString = String(e.ClassName()) + e.Message;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    if (0)
    {
        VmsIterator it;
        for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
        {
            TVmsCtlr *pObj = (TVmsCtlr*)it->second;

            if (pObj->Server.UseFlag != bit_enable) continue;
            LDEBUG("VMS Event(I/E): %s, %d/%d EA", pObj->VmsNo.c_str(), pObj->INCIDENT->Count, pObj->EVENT->Count);
        }
    }

    LINFO("LoadVmsEventOccrInf: %d EA", nSelCnt);

	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::MakeVmsScenarioForm(AnsiString AVmsId)
{
	int nResult = VERR_NONE;

    LINFO("MakeVmsScenarioForm: Start");

	ClearVmsProvideMode(AVmsId);

    //TODO
    //if (LOAD_DB)
    {
        LoadVmsForm();
        GetVmsIfscInfo();
    }

    //돌발/공사/행사가 발생한 정보를 VMS에 맵핑한다.
    nResult = LoadVmsEventOccrInf(AVmsId);
    if (nResult != VERR_NONE)
    {
        LERROR("LoadVmsEventOccrInf: error: %d", nResult);
    }

    // VMS구간 소통정보를 모두 읽어오자..(데이터가 많을 경우 해당되는 정보만 읽어오도록 수정
    nResult = LoadIfscTrafficInfo();
    if (nResult != VERR_NONE)
    {
        LERROR("LoadIfscTrafficInfo: error: %d", nResult);
    }

    //VMS의 스케줄정보를 조회한다.
    nResult = LoadVmsScheduleInfo(AVmsId);
    if (nResult != VERR_NONE)
    {
        LERROR("LoadVmsScheduleInfo: error: %d", nResult);
    }

    LINFO("MakeVmsScenarioForm: End");
    return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SaveVmsDownloadForm()
{
	int nResult = VERR_NONE;
    int nSaveVmsCnt, nSaveFormCnt;

    LINFO("SaveVmsDownloadForm: Start");

    nSaveVmsCnt = 0;
    nSaveFormCnt= 0;

    //생성한 폼을 데이터베이스에 저장한다.
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;
        if (!pObj->FProvide) continue;

        nSaveFormCnt += SaveVmsDatabaseForm(pObj);
        nSaveVmsCnt++;
    }

    //생성한 폼을 제어기에 전송할 수 있도록 플래그를 설정한다.
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;
        if (!pObj->FProvide) continue;

        if (pObj->pForms->Count() > 0)
        {
            pObj->CTLMODE->Enable   = object_enable;
            pObj->CTLMODE->SaveFlag = false;
            pObj->CTLMODE->Result   = false;
        }
    }

    INT_VMS_FORM_SAVE_REQ Req;
    memset((char*)&Req, 0x00, sizeof(Req));
    memcpy(Req.Date, FFormDsplDt.c_str(), INT_VMS_MAX_DATETIME);
    VComm_VmsFormSaveNotify(&Req);

    LINFO("SaveVmsDownloadForm: End. (VMS: %d EA, Forms %d EA)", nSaveVmsCnt, nSaveFormCnt);
    LINFO("*** VMS Msg create end.");
	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SetVmsMode()
{
	int         nResult;
	int         nSelCnt = 0;

	nResult = VERR_OTHER;

    LINFO("SetVmsMode: Start");

    try
    {
        VmsIterator it;
        for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
        {
            TVmsCtlr *pObj = (TVmsCtlr*)it->second;

            if (pObj->Server.UseFlag != bit_enable) continue;

            if (!pObj->FProvide) continue;

            if (!pObj->FModeChange) continue;   //모드가 변경이 안되어 있으면 업데이트할 필요 없음

            AnsiString VMS_CTLR_NMBR = pObj->VmsNo;
            AnsiString OPER_MODE     = "A";

            if (pObj->CTLMODE->Control == 'F')
                OPER_MODE = "F";
            else
            if (pObj->CTLMODE->Control == 'B')
                OPER_MODE = "B";

            pObj->RSTATE.OprMode = pObj->CTLMODE->Control;

            nSelCnt++;
        }

        nResult = VERR_NONE;
    }
    catch(Exception &e)
    {
        ErrorString = String(e.ClassName()) + e.Message;
    }

    LINFO("SetVmsMode: %d", nSelCnt);

	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::LoadVmsOperatorMode()
{
	int         nResult;
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

	nResult = VERR_OTHER;

    LINFO("LoadVmsOperatorMode: Start");

    sQry = "SELECT A.VMS_CTLR_NMBR, A.OPER_MODE,                       \r\n"
           "       NVL(A.VMS_MAX_PHSE_NUM,  16) AS VMS_MAX_PHSE_NUM,   \r\n"
           "       NVL(A.VMS_PHSE_CHNG_CYCL, 5) AS VMS_PHSE_CHNG_CYCL  \r\n"
           "  FROM TB_VMS_CTLR A                                       \r\n"
           " WHERE A.DEL_YN = 'N'                                      \r\n";

	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString sVmsNmbr = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;

                TVmsCtlr *pObj = VmsManager->FLists.Find(sVmsNmbr);
                if (!pObj) continue;

                pObj->OPER_MODE = pADO->FieldByName("OPER_MODE")->AsString;
                int nMaxFormCnt = pADO->FieldByName("VMS_MAX_PHSE_NUM")->AsInteger;

                if (pObj->OPER_MODE == "A")
                    pObj->DSTATE.OprMode = 'A';
                else
                if (pObj->OPER_MODE == "B")
                    pObj->DSTATE.OprMode = 'B';
                else
                    pObj->DSTATE.OprMode = 'F';

                if (pObj->CTLMODE->Control == pObj->DSTATE.OprMode)
                    pObj->FModeChange = false;
                else
                    pObj->FModeChange = true;

                pObj->VMS_PHSE_CHNG_CYCL = pADO->FieldByName("VMS_PHSE_CHNG_CYCL")->AsInteger;

                pObj->CTLMODE->Control = pObj->DSTATE.OprMode;
                pObj->RSTATE.OprMode   = pObj->CTLMODE->Control;

                pObj->VMS_MAX_PHSE_NUM = nMaxFormCnt;
                if (pObj->VMS_MAX_PHSE_NUM > INT_MAX_VMS_FORM)
                    pObj->VMS_MAX_PHSE_NUM = INT_MAX_VMS_FORM;

                pObj->CTLMODE->MaxDisplayForm = pObj->VMS_MAX_PHSE_NUM;
#if 0
                if (pObj->CTLMODE->MaxDisplayForm > INT_MAX_VMS_FORM)
                    pObj->CTLMODE->MaxDisplayForm = INT_MAX_VMS_FORM;
#endif

                nSelCnt++;
			}

			nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            ErrorString = String(E.ClassName()) + E.Message;
		}
		catch(Exception &e)
		{
            ErrorString = String(e.ClassName()) + e.Message;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    LINFO("LoadVmsOperatorMode: %d EA", nSelCnt);

	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::ProvideProc(void *AData)
{
	int             nResult;
	PROVIDE_STRUCT *pPro;

    LINFO("********ProvideProc: Start");

	nResult = VERR_NONE;

	pPro = (PROVIDE_STRUCT*)AData;
    if (!pPro)
    {
        return VERR_OTHER;
    }

    try
    {
        switch(pPro->Type)
        {
        case provide_event: //자동스케줄타임에 의한 메시지 생성
            {
                LINFO("--From Traffic Timer");

                if ((nResult = LoadVmsOperatorMode()) != VERR_NONE)
                {
                    break;
                }

                //모든 VMS에 메시지다운로드 플래그 활성화 시킴
                VmsManager->InitProvide(true);

                if ((nResult = MakeVmsScenarioForm(ALL_VMS_ID)) != VERR_NONE)
                {
                }
            }
            break;
        case provide_mode:  //개별 VMS 제어(모드변경)
            {
                LINFO("-From OprMode Change");

                AnsiString sVmsNmbr;

                //모든 VMS에 메시지다운로드 플래그 비활성화 시킴
                VmsManager->InitProvide(false);

                for(int ii = 0; ii < pPro->Count && ii < INT_MAX_VMS_MODE; ii++)
                {
                    sVmsNmbr.sprintf("%.*s", INT_VMS_MAX_ID, pPro->Unit[ii].VmsId);

                    TVmsCtlr *pObj = VmsManager->FLists.Find(sVmsNmbr);
                    if (!pObj) continue;
                    if (pObj->Server.UseFlag != bit_enable) continue;

                    if (pObj->CTLMODE->Control == pPro->Unit[ii].Mode)
                        pObj->FModeChange = false;
                    else
                        pObj->FModeChange = true;

                    pObj->CTLMODE->Control = pPro->Unit[ii].Mode;
                    pObj->DSTATE.OprMode = pObj->CTLMODE->Control;
                    pObj->RSTATE.OprMode = pObj->CTLMODE->Control;
                    if      (pObj->CTLMODE->Control == 'A') pObj->OPER_MODE = "A";
                    else if (pObj->CTLMODE->Control == 'B') pObj->OPER_MODE = "B";
                    else                                    pObj->OPER_MODE = "F";
                    pObj->FProvide = true;
                }

                if ((nResult = MakeVmsScenarioForm(ALL_VMS_ID)) != VERR_NONE)
                {
                }
            }
            break;
        }
    }
    __finally
    {
        delete[] (char *)AData;
    }

    LINFO("********ProvideProc: End");

	return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SaveVmsDownLoad(TVmsCtlr *AObj)
{
	int         nResult;
	AnsiString  sQry;
	TADOQuery  *pADO = NULL;

	nResult = VERR_OTHER;

    LINFO("SaveVmsDownLoad: Start");

    if (!AObj) return VERR_MEMORY_ALLOC;

    sQry = "UPDATE TB_VMS_DOWNLOAD        \r\n"
           "   SET SENDENDDATE   = :p05,  \r\n"
           "       SENDSTEP	     = :p06,  \r\n"
           "       SENDRESULT    = :p07   \r\n"
           " WHERE RGST_DT       = :p01   \r\n"
           "   AND VMS_CTLR_NMBR = :p02   \r\n"
           "   AND FILETYPE      = :p03   \r\n"
           "   AND FILEID        = :p04   \r\n";
	try
	{
        pADO = new TADOQuery(NULL);
        pADO->Connection = GetDbConnection();

		try
		{
            pADO->Connection->BeginTrans();

            SQLText(pADO, sQry, false);

            for (int ii = 0; ii < AObj->DOWNLOAD->Count && ii < VMS_MAX_DOWNLOAD; ii++)
            {
                SQLBind(pADO, "p01", AObj->DOWNLOAD->Unit[ii].RegDate);
                SQLBind(pADO, "p02", AObj->VmsNo);
                SQLBind(pADO, "p03", AObj->DOWNLOAD->Unit[ii].FileType);
                SQLBind(pADO, "p04", AObj->DOWNLOAD->Unit[ii].FileId);
                SQLBind(pADO, "p05", AObj->DOWNLOAD->Unit[ii].SendEndDate);
                SQLBind(pADO, "p06", AObj->DOWNLOAD->Unit[ii].SendStep);
                SQLBind(pADO, "p07", AObj->DOWNLOAD->Unit[ii].SendResult);

                SQLExec(pADO);
            }
            pADO->Connection->CommitTrans();
            nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(E.ClassName()) + E.Message;
            DBERRORLOG("SaveVmsDownLoad", String(E.ClassName()), E.Message, sQry);
            nResult = VERR_OTHER;
		}
		catch(Exception &e)
		{
            pADO->Connection->RollbackTrans();
            ErrorString = String(e.ClassName()) + e.Message;
            DBERRORLOG("SaveVmsDownLoad", String(e.ClassName()), e.Message, sQry);
		}
	}
	__finally
	{
        if (pADO)
        {
            SQLClose(pADO);
            SAFE_DELETE(pADO);
        }
	}
    LDEBUG("SaveVmsDownLoad: End, %s", AObj->VmsNo.c_str());
    return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::UpdateVmsProvideResult(TVmsCtlr *AObj)
{
	int         nResult;
	AnsiString  sQry;
	TADOQuery  *pSADO = NULL;
    int         nFormCnt = 0;

	nResult = VERR_OTHER;

    LDEBUG("UpdateVmsProvideResult: Start");

    if (!AObj) return VERR_MEMORY_ALLOC;

//LINFO("UpdateVmsProvideResult[U]: %s", AObj->VmsId.c_str());

    sQry = "UPDATE TB_VMS_DSPL_PRST      \r\n"
           "   SET DSPL_DT       = :p03, \r\n"
           "       DNLD_YN       = :p04  \r\n"
           " WHERE VMS_CTLR_NMBR = :p01  \r\n"
           "   AND PHASE        <= :p02  \r\n";

    String VMS_CTLR_NMBR;
    String PHASE;
    String DSPL_DT;
    String DNLD_YN;

	try
	{
        nFormCnt = AObj->pForms->Count();

        if (nFormCnt == 0) return VERR_NONE;

        pSADO = new TADOQuery(NULL);
        pSADO->Connection = GetDbConnection();

        VMS_CTLR_NMBR = AObj->VmsNo;
        PHASE         = String(nFormCnt);
        DSPL_DT       = AObj->CTLMODE->SvcDate;
        DNLD_YN       = AObj->CTLMODE->Result ? "Y" : "N";

		try
		{
            pSADO->Connection->BeginTrans();

            SQLText(pSADO, sQry, false);

            SQLBind(pSADO, "p01", VMS_CTLR_NMBR);
            SQLBind(pSADO, "p02", PHASE);
            SQLBind(pSADO, "p03", DSPL_DT);
            SQLBind(pSADO, "p04", DNLD_YN);
            SQLExec(pSADO);

            //pSADO->Connection->CommitTrans();

            nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            pSADO->Connection->RollbackTrans();
            ErrorString = String(E.ClassName()) + E.Message;
            DBERRORLOG("UpdateVmsProvideResult", String(E.ClassName()), E.Message, sQry);
            nResult = VERR_OTHER;
		}
		catch(Exception &e)
		{
            pSADO->Connection->RollbackTrans();
            ErrorString = String(e.ClassName()) + e.Message;
            DBERRORLOG("UpdateVmsProvideResult", String(e.ClassName()), e.Message, sQry);
		}

//LINFO("UpdateVmsProvideResult[I]: %s", AObj->VmsId.c_str());
        // 이력 저장--제공시각이 동일한게 이력으로 저장될수 있기때문에 트랜잭션을 다시시작한다.
        // 이전 VMS인 경우 임...
    sQry = "INSERT INTO TB_VMS_DSPL_HS                           \r\n"
           "           (VMS_CTLR_NMBR, DSPL_PHASE_NUM, DSPL_DT,  \r\n"
           "            VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,     \r\n"
           "            TRFC_SITU_TYPE_CD, VMS_MSG_DSPL_DRCT_CD, \r\n"
           "            VMS_MSG_DSPL_MTHD_CD, DSPL_HH,           \r\n"
           "            VMS_FORM_ID, DNLD_YN)                    \r\n"
           "SELECT VMS_CTLR_NMBR, PHASE, DSPL_DT,                \r\n"
           "       VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,          \r\n"
           "       TRFC_SITU_TYPE_CD, VMS_MSG_DSPL_DRCT_CD,      \r\n"
           "       VMS_MSG_DSPL_MTHD_CD, DSPL_HH,                \r\n"
           "       VMS_FORM_ID, DNLD_YN                          \r\n"
           "  FROM TB_VMS_DSPL_PRST                              \r\n"
           " WHERE VMS_CTLR_NMBR = :p01                          \r\n"
           "   AND PHASE        <= :p02                          \r\n";

		try
		{
            //pSADO->Connection->BeginTrans();

            SQLText(pSADO, sQry, false);

            SQLBind(pSADO, "p01", VMS_CTLR_NMBR);
            SQLBind(pSADO, "p02", PHASE);
            SQLExec(pSADO);

            pSADO->Connection->CommitTrans();

            nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            pSADO->Connection->RollbackTrans();
            ErrorString = String(E.ClassName()) + E.Message;
            //DBERRORLOG("UpdateVmsProvideResult-Hist", String(E.ClassName()), E.Message, sQry);
            nResult = VERR_OTHER;
		}
		catch(Exception &e)
		{
            pSADO->Connection->RollbackTrans();
            ErrorString = String(e.ClassName()) + e.Message;
            //DBERRORLOG("UpdateVmsProvideResult-Hist", String(e.ClassName()), e.Message, sQry);
		}
	}
	__finally
	{
        if (pSADO)
        {
            SQLClose(pSADO);
            SAFE_DELETE(pSADO);
        }
	}
LDEBUG("UpdateVmsProvideResult: End, %s, %d EA [%s]", AObj->VmsNo.c_str(), nFormCnt, DNLD_YN.c_str());
    return nResult;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::SaveVmsDatabaseForm(TVmsCtlr *AObj)
{
	int         nResult;
	AnsiString  sQry;
	AnsiString  uQry;
//	AnsiString  iQry;
	TADOQuery  *pSADO = NULL;
	TADOQuery  *pUADO = NULL;
//	TADOQuery  *pIADO = NULL;
    int         nSelCnt = 0;


	nResult = VERR_OTHER;

//LINFO("[%s]SaveVmsDatabaseForm: Start", AObj->VmsNo.c_str());

    if (!AObj) return VERR_MEMORY_ALLOC;

//LINFO("SaveVmsDatabaseForm[M]: %s", AObj->VmsId.c_str());
    int nFormCnt = AObj->pForms->Count();
    if (nFormCnt == 0) return VERR_NONE;

    sQry = "MERGE INTO TB_VMS_DSPL_PRST L                                  \r\n"
           "USING (SELECT :p01 AS VMS_CTLR_NMBR,                           \r\n"
           "              :p02 AS PHASE,                                   \r\n"
           "              :p03 AS DSPL_DT,                                 \r\n"
           "              :p04 AS VMS_DSPL_MSG_DATA,                       \r\n"
           "              :p05 AS VMS_DSPL_MSG_TXT,                        \r\n"
           "              :p06 AS TRFC_SITU_TYPE_CD,                       \r\n"
           "              :p07 AS VMS_MSG_DSPL_DRCT_CD,                    \r\n"
           "              :p08 AS VMS_MSG_DSPL_MTHD_CD,                    \r\n"
           "              :p09 AS DSPL_HH,                                 \r\n"
           "              :p10 AS VMS_FORM_ID,                             \r\n"
           "              :p11 AS DNLD_YN                                  \r\n"
           "         FROM DUAL) M                                          \r\n"
           " ON (L.VMS_CTLR_NMBR = M.VMS_CTLR_NMBR AND L.PHASE = M.PHASE)  \r\n"
           "WHEN MATCHED THEN                                              \r\n"
           "UPDATE SET L.DSPL_DT              = M.DSPL_DT,                 \r\n"
           "           L.VMS_DSPL_MSG_DATA    = M.VMS_DSPL_MSG_DATA,       \r\n"
           "           L.VMS_DSPL_MSG_TXT     = M.VMS_DSPL_MSG_TXT,        \r\n"
           "           L.TRFC_SITU_TYPE_CD    = M.TRFC_SITU_TYPE_CD,       \r\n"
           "           L.VMS_MSG_DSPL_DRCT_CD = M.VMS_MSG_DSPL_DRCT_CD,    \r\n"
           "           L.VMS_MSG_DSPL_MTHD_CD = M.VMS_MSG_DSPL_MTHD_CD,    \r\n"
           "           L.DSPL_HH              = M.DSPL_HH,                 \r\n"
           "           L.VMS_FORM_ID          = M.VMS_FORM_ID,             \r\n"
           "           L.DNLD_YN              = M.DNLD_YN                  \r\n"
           "WHEN NOT MATCHED THEN                                          \r\n"
           "INSERT (VMS_CTLR_NMBR, PHASE, DSPL_DT,                         \r\n"
           "        VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,                   \r\n"
           "        TRFC_SITU_TYPE_CD, VMS_MSG_DSPL_DRCT_CD,               \r\n"
           "        VMS_MSG_DSPL_MTHD_CD, DSPL_HH,                         \r\n"
           "        VMS_FORM_ID, DNLD_YN)                                  \r\n"
           "VALUES (M.VMS_CTLR_NMBR, M.PHASE, M.DSPL_DT,                   \r\n"
           "        M.VMS_DSPL_MSG_DATA, M.VMS_DSPL_MSG_TXT,               \r\n"
           "        M.TRFC_SITU_TYPE_CD, M.VMS_MSG_DSPL_DRCT_CD,           \r\n"
           "        M.VMS_MSG_DSPL_MTHD_CD, M.DSPL_HH,                     \r\n"
           "        M.VMS_FORM_ID, M.DNLD_YN)                              \r\n";

    uQry = "UPDATE TB_VMS_DSPL_PRST         \r\n"
           "   SET VMS_DSPL_MSG_IMAG = :p03 \r\n"
           " WHERE VMS_CTLR_NMBR = :p01     \r\n"
           "   AND PHASE         = :p02     \r\n";

#if 0
    iQry = "INSERT INTO TB_VMS_DSPL_HS                         \r\n"
           "       (VMS_CTLR_NMBR, DSPL_PHASE_NUM, DSPL_DT,    \r\n"
           "        VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,       \r\n"
           "        TRFC_SITU_TYPE_CD, VMS_MSG_DSPL_DRCT_CD,   \r\n"
           "        VMS_MSG_DSPL_MTHD_CD, DSPL_HH,             \r\n"
           "        VMS_FORM_ID, DNLD_YN)                      \r\n"
           "VALUES (:p01, :p02, :p03,                          \r\n"
           "        :p04, :p05,                                \r\n"
           "        :p06, :p07,                                \r\n"
           "        :p08, :p09,                                \r\n"
           "        :p10, :p11)                                \r\n";
#endif

	try
	{
        pSADO = new TADOQuery(NULL);
        pSADO->Connection = GetDbConnection();
        pUADO = new TADOQuery(NULL);
        pUADO->Connection = GetDbConnection();
#if 0
        pIADO = new TADOQuery(NULL);
        pIADO->Connection = GetDbConnection();
#endif

		try
		{
            AObj->pForms->Lock();

            pSADO->Connection->BeginTrans();

            SQLText(pSADO, sQry, false);
            SQLText(pUADO, uQry, false);
//            SQLText(pIADO, iQry, false);

    //LDEBUG("SaveVmsProvide: %s, Forms: %d EA", AObj->VmsNo.c_str(), nFormCnt);
            for (int ii = 0; ii < nFormCnt; ii++)
            {
				TVmsForm *pForm = AObj->pForms->GetItem(ii);

    //LDEBUG("SaveVmsProvide: %s, %d", AObj->VmsNo.c_str(), ii+1);
                String VMS_CTLR_NMBR        = AObj->VmsNo;
                String PHASE                = String(ii+1);
                String DSPL_DT              = AObj->CTLMODE->SvcDate;
                String VMS_DSPL_MSG_DATA    = "";
                String VMS_DSPL_MSG_TXT     = "";
                String TRFC_SITU_TYPE_CD    = String(pForm->FormKind);
                String VMS_MSG_DSPL_DRCT_CD = pForm->DisplayDir;
                String VMS_MSG_DSPL_MTHD_CD = pForm->DisplayMode;
                String DSPL_HH              = String(pForm->DisplayTime);
                String VMS_FORM_ID          = pForm->FormId;
                String DNLD_YN              = pForm->SvcRes ? "Y" : "N";

                AnsiString sTmp  = "";
                AnsiString sCont = "";

                int nObjCnt, nObjType;
                try
                {
                    //폼종류/표출시간/배경색상
                    sCont.printf("%02X%02X%02X|", pForm->FormKind, pForm->DisplayTime, pForm->BkColor);
                    VMS_DSPL_MSG_DATA += sCont;

                    nObjCnt = pForm->Count();
    //LDEBUG("SaveVmsProvide: %s, %d, object: %d EA", AObj->VmsNo.c_str(), ii+1, nObjCnt);

                    for (int jj = 0; jj < nObjCnt; jj++)
                    {
                        TVmsFormObj *pFormObj = pForm->GetItem(jj);
                        switch(pFormObj->ObjectType)
                        {
                        case 1: //심볼
                        case 2: //이미지
                            nObjType = vms_obj_bitmap;
                            sTmp.printf("%02X%04X%04X%02X%s|",
                                pFormObj->IsBlinking,
                                pFormObj->PosX,
                                pFormObj->PosY,
                                pFormObj->BkColor,
                                pFormObj->ImageId.SubString(1,4).c_str());

                            sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                            VMS_DSPL_MSG_DATA += sCont;
                            break;
                        case 17: //소통정보이미지1
                        case 27: //소통정보이미지2
                        case 37: //소통정보이미지3
                        case 47: //소통정보이미지4
                        case 3: //소통정보배경이미지
                            {
                                nObjType = vms_obj_draw;
                                sTmp.printf("%02X%04X%04X%02X%s+",
                                    pFormObj->IsBlinking,
                                    pFormObj->PosX,
                                    pFormObj->PosY,
                                    pFormObj->BkColor,
                                    pFormObj->ImageId.SubString(1,4).c_str());

                                sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                                VMS_DSPL_MSG_DATA += sCont;

                                AnsiString sVertex = "";
                                TCDSImage *pSymbol = ImageManager->FLists.Find(pFormObj->ImageId);
                                if (pSymbol)
                                {
                                    sTmp = "";
                                    int nCnt = 0;

                                    FOR_STL(TCDSImageCell*, pCell, pSymbol->FLists)
                                    {
                                        TCDSIfsc *pIfsc = NULL;
                                        if (pFormObj->ObjectType == 3)
                                            pIfsc = IfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                        else
                                            pIfsc = IfscManager->FLists.Find(pFormObj->IFSC_ID);

                                        if (pIfsc)
                                        {
                                            sVertex.sprintf("%03d%03d%d", pCell->POSX, pCell->POSY, pIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                            sTmp += sVertex;
                                            nCnt++;
                                        }
                                    }
                                    sCont.printf("%02X%s|", nCnt, sTmp.c_str());
                                    VMS_DSPL_MSG_DATA += sCont;
                                }
                                else
                                {
                                    VMS_DSPL_MSG_DATA += "X|";
                                }
                            }
                            break;
                        default://기타 문자열
                            VMS_DSPL_MSG_TXT += pFormObj->TextData;
                            VMS_DSPL_MSG_TXT += " ";

                            nObjType = vms_obj_text;
                            sTmp.printf("%02X%04X%04X%02X%02X%02X%02X%02X%02X%s|",
                                pFormObj->IsBlinking,
                                pFormObj->PosX,
                                pFormObj->PosY,
                                pFormObj->BkColor,
                                pFormObj->TextFontSize,
                                pFormObj->TextFontColor,
                                pFormObj->TextFontName,
                                pFormObj->TextFontBold,
                                pFormObj->TextData.Length(),
                                pFormObj->TextData);

                            sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                            VMS_DSPL_MSG_DATA += sCont;
                            break;
                        }
                    }

                    if (VMS_DSPL_MSG_DATA.Length() > 400) VMS_DSPL_MSG_DATA = VMS_DSPL_MSG_DATA.SubString(1, 399);
                    if (VMS_DSPL_MSG_TXT.Length()  > 200) VMS_DSPL_MSG_TXT  = VMS_DSPL_MSG_TXT.SubString(1, 199);

//LDEBUG("SaveVmsProvide: %s, %d Merge", AObj->VmsNo.c_str(), ii+1);
                    SQLBind(pSADO, "p01", VMS_CTLR_NMBR);
                    SQLBind(pSADO, "p02", PHASE);
                    SQLBind(pSADO, "p03", DSPL_DT);
                    SQLBind(pSADO, "p04", VMS_DSPL_MSG_DATA);
                    SQLBind(pSADO, "p05", VMS_DSPL_MSG_TXT);
                    SQLBind(pSADO, "p06", TRFC_SITU_TYPE_CD);
                    SQLBind(pSADO, "p07", VMS_MSG_DSPL_DRCT_CD);
                    SQLBind(pSADO, "p08", VMS_MSG_DSPL_MTHD_CD);
                    SQLBind(pSADO, "p09", DSPL_HH);
                    SQLBind(pSADO, "p10", VMS_FORM_ID);
                    SQLBind(pSADO, "p11", DNLD_YN);
                    SQLExec(pSADO);

                    try
                    {
//LDEBUG("SaveVmsProvide: %s, %d Update", AObj->VmsNo.c_str(), ii+1);
                        SQLBind(pUADO, "p01", VMS_CTLR_NMBR);
                        SQLBind(pUADO, "p02", PHASE);
                        //pUADO->Parameters->ParamByName("p03")->LoadFromStream(pStream, ftBlob);
                        pUADO->Parameters->ParamByName("p03")->LoadFromStream(pForm->pStream, ftBlob);
                        SQLExec(pUADO);

//LINFO("[%s] FormImage Size: %d", AObj->VmsNo.c_str(), pForm->pStream->Size);
                        //pForm->pBitmap->SaveToFile(g_sFormDir + AObj->VmsId + "\\" + PHASE + ".bmp");
                        //pImage->Picture->SaveToFile(g_sFormDir + AObj->VmsId + "\\" + PHASE + ".bmp");
                    }
                    catch(Exception &e)
                    {
                    }

//LDEBUG("SaveVmsProvide: %s, %d Insert", AObj->VmsNo.c_str(), ii+1);
#if 0
                    SQLBind(pIADO, "p01", VMS_CTLR_NMBR);
                    SQLBind(pIADO, "p02", PHASE);
                    SQLBind(pIADO, "p03", DSPL_DT);
                    SQLBind(pIADO, "p04", VMS_DSPL_MSG_DATA);
                    SQLBind(pIADO, "p05", VMS_DSPL_MSG_TXT);
                    SQLBind(pIADO, "p06", TRFC_SITU_TYPE_CD);
                    SQLBind(pIADO, "p07", VMS_MSG_DSPL_DRCT_CD);
                    SQLBind(pIADO, "p08", VMS_MSG_DSPL_MTHD_CD);
                    SQLBind(pIADO, "p09", DSPL_HH);
                    SQLBind(pIADO, "p10", VMS_FORM_ID);
                    SQLBind(pIADO, "p11", DNLD_YN);
                    SQLExec(pIADO);
#endif

                    nSelCnt++;
                }
                __finally
                {
                }
            }

            pSADO->Connection->CommitTrans();

            nResult = VERR_NONE;
		}
		catch(EDatabaseError &E)
		{
            pSADO->Connection->RollbackTrans();
            ErrorString = String(E.ClassName()) + E.Message;
            DBERRORLOG("SaveVmsProvide", String(E.ClassName()), E.Message, sQry);
            nResult = VERR_OTHER;
		}
		catch(Exception &e)
		{
            pSADO->Connection->RollbackTrans();
            ErrorString = String(e.ClassName()) + e.Message;
            DBERRORLOG("SaveVmsProvide", String(e.ClassName()), e.Message, sQry);
		}
	}
	__finally
	{
        AObj->pForms->UnLock();

        if (pSADO)
        {
            SQLClose(pSADO);
            SAFE_DELETE(pSADO);
        }
        if (pUADO)
        {
            SQLClose(pUADO);
            SAFE_DELETE(pUADO);
        }
#if 0
        if (pIADO)
        {
            SQLClose(pIADO);
            SAFE_DELETE(pIADO);
        }
#endif
	}
    LINFO("SaveVmsDatabaseForm: End, %s, %d EA", AObj->VmsNo.c_str(), nSelCnt);
    return nSelCnt;
}
//---------------------------------------------------------------------------

int __fastcall TDMCOMM::ProvideSave(void *AData)
{
	int          nResult, ii;
    TVmsCtlr    *pObj;
	SAVE_STRUCT *pSave;
    int          nJobCnt = 0;

	nResult = VERR_NONE;

    LINFO("ProvideSave: Start");

    pSave = (SAVE_STRUCT*)AData;
    if (!pSave)
    {
        LERROR("ProvideSave: Data NULL");
        return VERR_MEMORY_ALLOC;
    }

    try
    {
        switch(pSave->Type)
        {
        case save_download:
            for (ii = 0; ii < pSave->Count && ii < INT_MAX_VMS_STATE; ii++)
            {
                pObj = (TVmsCtlr*)pSave->pObj[ii];
                if (!pObj) continue;
                if ((nResult = SaveVmsDownLoad(pObj)) != VERR_NONE)
                {
                    LERROR("ProvideSave: SaveVmsDownLoad failed");
                }
            }
            break;
        case save_provide:
            {
                INT_VMS_FORM_DOWNLOAD_REQ VmsSave;

                memset(&VmsSave, 0x00, sizeof(VmsSave));
                VmsSave.Count = 0;

                LINFO("VMS Msg Dnld Result Save: %d EA", pSave->Count);
                for (ii = 0; ii < pSave->Count && ii < INT_MAX_VMS_FORM_DOWNLOAD; ii++)
                {
                    pObj = (TVmsCtlr*)pSave->pObj[ii];
                    if (!pObj) continue;
#if 0
                    if ((nResult = SaveVmsProvide(pObj)) != VERR_NONE)
#else
                    if ((nResult = UpdateVmsProvideResult(pObj)) != VERR_NONE)
#endif
                    {
                        LERROR("ProvideSave: UpdateVmsProvideResult failed");
                    }
                    else
                    {
                        nJobCnt++;

                        memcpy(VmsSave.Unit[VmsSave.Count].VmsId, pObj->VmsNo.c_str(), INT_VMS_MAX_ID);
                        memcpy(VmsSave.Unit[VmsSave.Count].Date,  pObj->CTLMODE->SvcDate.c_str(), INT_VMS_MAX_DATETIME);
                        VmsSave.Unit[VmsSave.Count].Result = pObj->CTLMODE->Result ? vms_download_succ : vms_download_fail;
                        VmsSave.Count++;

                        if (VmsSave.Count >= INT_MAX_VMS_FORM_DOWNLOAD)
                        {
                            VComm_VmsFormDownLoadNotify(&VmsSave);
                            VmsSave.Count = 0;
                        }
                    }
                }
                if (VmsSave.Count > 0)
                {
                    VComm_VmsFormDownLoadNotify(&VmsSave);
                }
            }
            break;
        }
    }
    __finally
    {
        delete[] (char *)AData;
    }
    LINFO("ProvideSave: %d EA", nJobCnt);
	return nResult;
}
//---------------------------------------------------------------------------


