//---------------------------------------------------------------------------

#include <DateUtils.hpp>
#pragma hdrstop

#include "CDSCtlrF.h"
#include "VMSCommLibF.h"

//---------------------------------------------------------------------------
#define     MEMMOVE(x)              memmove(x+1, x, sizeof(x)-sizeof(x[0]))
#define     MEMZERO(x)              memset((char *)&x[0], 0x00, sizeof(x[0]))
//---------------------------------------------------------------------------

#pragma package(smart_init)
String g_sMerge = "MERGE INTO TB_VMS_CTLR_STTS L                             \r\n"
                  "USING (SELECT :p01 AS VMS_CTLR_NMBR,                      \r\n"
                  "              :p02 AS UPDT_DT,                            \r\n"
                  "              :p03 AS CMNC_STTS_CD,                       \r\n"
                  "              :p04 AS PWER_STTS_CD,                       \r\n"
                  "              :p05 AS MODL_STTS_CD,                       \r\n"
                  "              :p06 AS CBOX_DOOR_STTS_CD,                  \r\n"
                  "              :p07 AS FAN_STTS_CD,                        \r\n"
                  "              :p08 AS HETR_STTS_CD,                       \r\n"
                  "              :p09 AS CBOX_TMPR,                          \r\n"
                  "              :p10 AS BRGH_VAL,                           \r\n"
                  "              :p11 AS COMM_STTS_CD,                       \r\n"
                  "              :p12 AS MODL_STTS,                          \r\n"
                  "              :p13 AS PWER_STTS                           \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.UPDT_DT           = M.UPDT_DT,            \r\n"
                  "              L.CMNC_STTS_CD      = M.CMNC_STTS_CD,       \r\n"
                  "              L.PWER_STTS_CD      = M.PWER_STTS_CD,       \r\n"
                  "              L.MODL_STTS_CD      = M.MODL_STTS_CD,       \r\n"
                  "              L.CBOX_DOOR_STTS_CD = M.CBOX_DOOR_STTS_CD,  \r\n"
                  "              L.FAN_STTS_CD       = M.FAN_STTS_CD,        \r\n"
                  "              L.HETR_STTS_CD      = M.HETR_STTS_CD,       \r\n"
                  "              L.CBOX_TMPR         = M.CBOX_TMPR,          \r\n"
                  "              L.BRGH_VAL          = M.BRGH_VAL,           \r\n"
                  "              L.COMM_STTS_CD      = M.COMM_STTS_CD,       \r\n"
                  "              L.MODL_STTS         = M.MODL_STTS,          \r\n"
                  "              L.PWER_STTS         = M.PWER_STTS           \r\n"
                  "WHEN NOT MATCHED THEN                                     \r\n"
                  "   INSERT (VMS_CTLR_NMBR,                                 \r\n"
                  "           UPDT_DT,                                       \r\n"
                  "           CMNC_STTS_CD,                                  \r\n"
                  "           PWER_STTS_CD,                                  \r\n"
                  "           MODL_STTS_CD,                                  \r\n"
                  "           CBOX_DOOR_STTS_CD,                             \r\n"
                  "           FAN_STTS_CD,                                   \r\n"
                  "           HETR_STTS_CD,                                  \r\n"
                  "           CBOX_TMPR,                                     \r\n"
                  "           BRGH_VAL,                                      \r\n"
                  "           COMM_STTS_CD,                                  \r\n"
                  "           MODL_STTS,                                     \r\n"
                  "           PWER_STTS )                                    \r\n"
                  "   VALUES (M.VMS_CTLR_NMBR,                               \r\n"
                  "           M.UPDT_DT,                                     \r\n"
                  "           M.CMNC_STTS_CD,                                \r\n"
                  "           M.PWER_STTS_CD,                                \r\n"
                  "           M.MODL_STTS_CD,                                \r\n"
                  "           M.CBOX_DOOR_STTS_CD,                           \r\n"
                  "           M.FAN_STTS_CD,                                 \r\n"
                  "           M.HETR_STTS_CD,                                \r\n"
                  "           M.CBOX_TMPR,                                   \r\n"
                  "           M.BRGH_VAL,                                    \r\n"
                  "           M.COMM_STTS_CD,                                \r\n"
                  "           M.MODL_STTS,                                   \r\n"
                  "           M.PWER_STTS )                                  \r\n";
String g_sUpdate= "UPDATE TB_VMS_CTLR_STTS                               \r\n"
                  "   SET UPDT_DT           = :p02,  \r\n"
                  "       CMNC_STTS_CD      = :p03,  \r\n"
                  "       PWER_STTS_CD      = :p04,  \r\n"
                  "       MODL_STTS_CD      = :p05,  \r\n"
                  "       CBOX_DOOR_STTS_CD = :p06,  \r\n"
                  "       FAN_STTS_CD       = :p07,  \r\n"
                  "       HETR_STTS_CD      = :p08,  \r\n"
                  "       CBOX_TMPR         = :p09,  \r\n"
                  "       BRGH_VAL          = :p10,  \r\n"
                  "       COMM_STTS_CD      = :p11,  \r\n"
                  "       MODL_STTS         = :p12,  \r\n"
                  "       PWER_STTS         = :p13   \r\n"
                  " WHERE VMS_CTLR_NMBR = :p01       \r\n";


//---------------------------------------------------------------------------
TCDSCtlr::TCDSCtlr()
{
    InitializeCriticalSection(&FCS);

    pPackQueue = new TThreadList();

    FDispLog = false;
    FSLog = NULL;
    FCLog = NULL;

    FSession = NULL;

    Server.Init();
    Client.Init();
    dwConnectCnt = 0;
    //LOGIN_IPADDR = "";
}
//---------------------------------------------------------------------------

TCDSCtlr::~TCDSCtlr()
{
    SAFE_DELETE(pPackQueue); /* 패킷 버퍼 */
    SAFE_DELETE(FSLog);
    SAFE_DELETE(FCLog);

    DeleteCriticalSection(&FCS);
}
//---------------------------------------------------------------------------
void TCDSCtlr::Lock()
{
    EnterCriticalSection(&FCS);
}
//---------------------------------------------------------------------------
void TCDSCtlr::UnLock()
{
    LeaveCriticalSection(&FCS);
}
//---------------------------------------------------------------------------
void TCDSCtlr::InitCtrlMode()
{
    VMS_CONTROL_MODE *AInfo = CTRLMODE;
    AInfo->SaveFlag = true;
    AInfo->pTimer   = Now();
}
//---------------------------------------------------------------------------
void TCDSCtlr::InitEVehicle()
{
    VMS_EVEHICLE_INFO *AInfo = EVEHICLE;
    AInfo->Count = 0;
    for (int ii = 0; ii < VMS_MAX_EVEHICLE; ii++)
    {
        AInfo->Unit[ii].SRVC_ID = "";
        AInfo->Unit[ii].IXR_CNT = 0;
        AInfo->Unit[ii].SRVC_TM = "";
        AInfo->Unit[ii].END_YN  = "";
    }
}
//---------------------------------------------------------------------------
void TCDSCtlr::InitEvent()
{
    VMS_EVENT_INFO *AInfo = EVENT;
    AInfo->Count = 0;
    for (int ii = 0; ii < VMS_MAX_EVENT; ii++)
    {
        AInfo->Unit[ii].LINK_ID               = "";
        AInfo->Unit[ii].IFSC_ID               = "";
        AInfo->Unit[ii].VMS_IFSC_ID           = "";
        AInfo->Unit[ii].VMS_IFSC_NM           = "";
        AInfo->Unit[ii].DSPL_STRT_NODE_NM     = "";
        AInfo->Unit[ii].DSPL_END_NODE_NM      = "";
        AInfo->Unit[ii].DETR_ID               = "";
        AInfo->Unit[ii].DSPL_PRRT             = "";
        AInfo->Unit[ii].INCD_OCRR_ID          = "";
        AInfo->Unit[ii].STRT_LCTN_NM          = "";
        AInfo->Unit[ii].END_LCTN_NM           = "";
        AInfo->Unit[ii].OCRR_LCTN_NM          = "";
        AInfo->Unit[ii].VMS_INCD_TYPE_NM      = "";
        AInfo->Unit[ii].VMS_INCD_TYPE_CD      = "";
        AInfo->Unit[ii].VMS_INCD_DETL_NM      = "";
        AInfo->Unit[ii].VMS_INCD_DETL_TYPE_CD = "";
        AInfo->Unit[ii].CMTR_GRAD_NM          = "";
        AInfo->Unit[ii].CMTR_GRAD_CD          = "";
        AInfo->Unit[ii].INCD_CLSR_LANE        = "";
        AInfo->Unit[ii].INCD_STRT_DT          = "";
        AInfo->Unit[ii].INCD_END_PRAR_DT      = "";
    }
}
//---------------------------------------------------------------------------
void TCDSCtlr::InitIncident()
{
    VMS_EVENT_INFO *AInfo = INCIDENT;
    AInfo->Count = 0;
    for (int ii = 0; ii < VMS_MAX_EVENT; ii++)
    {
        AInfo->Unit[ii].LINK_ID               = "";
        AInfo->Unit[ii].IFSC_ID               = "";
        AInfo->Unit[ii].VMS_IFSC_ID           = "";
        AInfo->Unit[ii].VMS_IFSC_NM           = "";
        AInfo->Unit[ii].DSPL_STRT_NODE_NM     = "";
        AInfo->Unit[ii].DSPL_END_NODE_NM      = "";
        AInfo->Unit[ii].DETR_ID               = "";
        AInfo->Unit[ii].DSPL_PRRT             = "";
        AInfo->Unit[ii].INCD_OCRR_ID          = "";
        AInfo->Unit[ii].STRT_LCTN_NM          = "";
        AInfo->Unit[ii].END_LCTN_NM           = "";
        AInfo->Unit[ii].OCRR_LCTN_NM          = "";
        AInfo->Unit[ii].VMS_INCD_TYPE_NM      = "";
        AInfo->Unit[ii].VMS_INCD_TYPE_CD      = "";
        AInfo->Unit[ii].VMS_INCD_DETL_NM      = "";
        AInfo->Unit[ii].VMS_INCD_DETL_TYPE_CD = "";
        AInfo->Unit[ii].CMTR_GRAD_NM          = "";
        AInfo->Unit[ii].CMTR_GRAD_CD          = "";
        AInfo->Unit[ii].INCD_CLSR_LANE        = "";
        AInfo->Unit[ii].INCD_STRT_DT          = "";
        AInfo->Unit[ii].INCD_END_PRAR_DT      = "";
    }
}
//---------------------------------------------------------------------------
void TCDSCtlr::InitSchedule()
{
    IsEVehIngForm = false;
    IsEVehEndForm = false;

    VMS_SCHEDULE_INFO *AInfo = SCHEDULE;
    AInfo->Count = 0;
    for (int ii = 0; ii < VMS_MAX_SCHEDULE; ii++)
    {
        AInfo->Unit[ii].VMS_SCH_TYPE      = "";
        AInfo->Unit[ii].VMS_SCH_FORM_TYPE = 0;
        AInfo->Unit[ii].PHASE             = 0;
        AInfo->Unit[ii].VMS_FORM_ID       = "";
        AInfo->Unit[ii].FRST_VMS_IFSC_ID  = "";
        AInfo->Unit[ii].SECD_VMS_IFSC_ID  = "";
        AInfo->Unit[ii].THIR_VMS_IFSC_ID  = "";
        AInfo->Unit[ii].FOUR_VMS_IFSC_ID  = "";
        AInfo->Unit[ii].FRST_IMG_IFSC_ID  = "";
        AInfo->Unit[ii].SECD_IMG_IFSC_ID  = "";
        AInfo->Unit[ii].THIR_IMG_IFSC_ID  = "";
        AInfo->Unit[ii].FOUR_IMG_IFSC_ID  = "";
        AInfo->Unit[ii].DSPL_HH           = 0;

        AInfo->Unit[ii].VMS_IFSC_ID       = "";

        AInfo->Unit[ii].DSPL_CNGS_YN      = true;

        AInfo->Unit[ii].EVENT             = NULL;
    }
}
//---------------------------------------------------------------------------
void TCDSCtlr::InitDownLoadInfo()
{
    VMS_DOWNLOAD_INFO *AInfo = DOWNLOAD;
    AInfo->Enable   = vms_download_disable;
    AInfo->SaveFlag = true;
    AInfo->dTimer   = Now();
    AInfo->Count    = 0;
}
//---------------------------------------------------------------------------
bool TCDSCtlr::ChangedState(INT_VMS_STATE *DSTATE, INT_VMS_STATE *RSTATE)
{
    if (DSTATE->OprMode != RSTATE->OprMode) return true;
	//if (DSTATE->Comm    != RSTATE->Comm) return true;
	if (DSTATE->Wcomm   != RSTATE->Wcomm) return true;

	if (DSTATE->DoorStatus        != RSTATE->DoorStatus) return true;
	if (DSTATE->ModulePowerStatus != RSTATE->ModulePowerStatus) return true;
	if (DSTATE->BodyTemp          != RSTATE->BodyTemp) return true;
	if (DSTATE->LuminanceStatus   != RSTATE->LuminanceStatus) return true;
	if (DSTATE->FanStatus         != RSTATE->FanStatus) return true;
	if (DSTATE->HeaterStatus      != RSTATE->HeaterStatus) return true;

    if (DSTATE->ExternalLightStatus != RSTATE->ExternalLightStatus) return true;
    if (DSTATE->AlarmLightStatus    != RSTATE->AlarmLightStatus) return true;
    if (DSTATE->SpeakerStatus       != RSTATE->SpeakerStatus) return true;

	//if (!memcmp(DSTATE->ControllerCurrentTime, RSTATE->ControllerCurrentTime, INT_VMS_MAX_DATETIME)) return true;

    if (DSTATE->Voltage != RSTATE->Voltage) return true;

	if (DSTATE->ModuleState      != RSTATE->ModuleState) return true;
	if (DSTATE->ModuleVertical   != RSTATE->ModuleVertical) return true;
	if (DSTATE->ModuleHorizontal != RSTATE->ModuleHorizontal) return true;
	if (memcmp(DSTATE->ModuleStatus, RSTATE->ModuleStatus, INT_VMS_MAX_MODULE_BIT)) return true;

	if (DSTATE->PowerCount != RSTATE->PowerCount) return true;
	if (memcmp(DSTATE->PowerStatus, RSTATE->PowerStatus, INT_VMS_MAX_POWER_BIT)) return true;

	if (DSTATE->ScheduledMessageOperatingTime   != RSTATE->ScheduledMessageOperatingTime) return true;
	if (DSTATE->ModuleOperatingTemperature      != RSTATE->ModuleOperatingTemperature) return true;
	if (DSTATE->FanOperatingTemperature         != RSTATE->FanOperatingTemperature) return true;
	if (DSTATE->HeaterOperatingTemperature      != RSTATE->HeaterOperatingTemperature) return true;
	if (DSTATE->ExternalLightOperatingLuminance != RSTATE->ExternalLightOperatingLuminance) return true;
	if (DSTATE->ModuleBasicFailureRate          != RSTATE->ModuleBasicFailureRate) return true;
	if (DSTATE->MaximumRetry                    != RSTATE->MaximumRetry) return true;
	if (DSTATE->ResponseTimeOut                 != RSTATE->ResponseTimeOut) return true;
	if (DSTATE->BlinkingCycleTime               != RSTATE->BlinkingCycleTime) return true;

    return false;
}
//---------------------------------------------------------------------------
void TCDSCtlr::InitDownloadFileInfo()
{
    memset((char*)&FormDownload, 0x00, sizeof(VMS_DOWNLOAD_DATA));
    FOR_STL(TDownloadForm*, pInfo, FDownloadLists)
    {
        pInfo->AlreadyDownload = false;    // 최초 접속시 모든 폼을 다운로드 할 수 있도록 플래그를 설정
    }
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
TCDSCtlrManager *CDSCtlrManager = NULL;
//---------------------------------------------------------------------------

TCDSCtlrManager::TCDSCtlrManager()
{
    Total  = 0;
    Error  = 0;
    Normal = 0;
    Module = 0;
    FCtlrStts5Min = -1;
}
//---------------------------------------------------------------------------
TCDSCtlrManager::~TCDSCtlrManager()
{
    FLists.RemoveAll();
}
//---------------------------------------------------------------------------
int TCDSCtlrManager::LoadCtlrInfo(TADOConnection *ADbConn)
{
    String     sQry;
    TADOQuery *pADO = NULL;

    DWORD dwTick = GetTickCount();
    SELSTART;

    sQry = "SELECT A.*,                               \r\n"
           "       B.VMS_WDTH,     B.VMS_HGHT,        \r\n"
           "       B.ROW_NUM,      B.COL_NUM,         \r\n"
           "       B.MODL_ROW_NUM, B.MODL_COL_NUM,    \r\n"
           "       B.POWR_ROW_NUM, B.POWR_COL_NUM     \r\n"
           "  FROM TB_VMS_CTLR A,                     \r\n"
           "       TB_VMS_TYPE B                      \r\n"
           " WHERE A.VMS_TYPE_CD = B.VMS_TYPE_CD      \r\n"
           "   AND A.DEL_YN      = 'N'                \r\n";

    BYTE OnOff;
    int nOnTime, nOffTime, nCurrTime;
    nCurrTime = Now().FormatString("hhnn").ToIntDef(0);
    try
    {
        CtlrItr it;
        for(it=FLists.FObjects.begin(); it != FLists.FObjects.end(); ++it)
        {
            TCDSCtlr *pObj = (TCDSCtlr*)it->second;

            pObj->Used = false;
        }

        FLists.Lock();
        try
        {
            pADO = new TADOQuery(NULL);
            pADO->Connection = ADbConn;

			SQLText(pADO, sQry, true);

			SQLOpen(pADO);
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString CTLR_NMBR = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;
                TCDSCtlr* pObj = FLists.Find(CTLR_NMBR);
                if (!pObj)
                {
                    pObj = new TCDSCtlr();
                    pObj->CTLR_NMBR = CTLR_NMBR;
                    pObj->CTLR_NMBR_ID.printf("%10.010d", pObj->CTLR_NMBR.ToIntDef(0));

                    FLists.Push(pObj->CTLR_NMBR, pObj);
                }
                pObj->Used = true;

                memset((char*)&pObj->DSTATE, 0x00, sizeof(pObj->DSTATE));
                memset((char*)&pObj->RSTATE, 0x00, sizeof(pObj->RSTATE));

                pObj->CTLR_ID       = pADO->FieldByName("VMS_CTLR_ID")->AsString.Trim();
                pObj->NM            = pADO->FieldByName("VMS_NM")->AsString.Trim();
                pObj->CTLR_IP       = pADO->FieldByName("VMS_CTLR_IP")->AsString.Trim();
                pObj->LOGIN_IPADDR  = pObj->CTLR_IP;
                pObj->CTLR_PORT     = pADO->FieldByName("VMS_CTLR_PORT")->AsInteger;
                pObj->GROUP_NO      = 0;
                pObj->CTLR_LOCAL_NO = pADO->FieldByName("VMS_CTLR_LOCAL_NO")->AsInteger;
                pObj->TYPE_CD       = pADO->FieldByName("VMS_TYPE_CD")->AsString.Trim();
                pObj->DEL_YN        = pADO->FieldByName("DEL_YN")->AsString.Trim();

                pObj->WIDTH         = pADO->FieldByName("VMS_WDTH")->AsString.Trim().ToIntDef(576);
                pObj->HEIGHT        = pADO->FieldByName("VMS_HGHT")->AsString.Trim().ToIntDef(320);
                pObj->ROW_NUM       = pADO->FieldByName("ROW_NUM")->AsInteger;
                pObj->COL_NUM       = pADO->FieldByName("COL_NUM")->AsInteger;
                pObj->MODL_ROW_NUM  = pADO->FieldByName("MODL_ROW_NUM")->AsInteger;
                pObj->MODL_COL_NUM  = pADO->FieldByName("MODL_COL_NUM")->AsInteger;
                pObj->POWR_ROW_NUM  = pADO->FieldByName("POWR_ROW_NUM")->AsInteger;
                pObj->POWR_COL_NUM  = pADO->FieldByName("POWR_COL_NUM")->AsInteger;

                pObj->OPER_MODE          = pADO->FieldByName("OPER_MODE")->AsString.Trim();         //	N	VARCHAR2(7)	Y	'A'		운영 모드
                if (pObj->OPER_MODE != "A" && pObj->OPER_MODE != "F" && pObj->OPER_MODE != "B")
                {
                    pObj->OPER_MODE = "A";
                }

                pObj->VMS_MAX_PHSE_NUM   = pADO->FieldByName("VMS_MAX_PHSE_NUM")->AsInteger;        //	N	NUMBER(2)	Y	14		VMS 최대 표출면 개수
                pObj->DEF_PHSE_CHNG_CYCL = pADO->FieldByName("DEF_PHSE_CHNG_CYCL")->AsInteger;      //	N	NUMBER(3)	Y	5		기본메시지주기

                pObj->PANL_ON_TIME       = pADO->FieldByName("PANL_ON_TIME")->AsString.Trim();      //	N	VARCHAR2(4)	Y	'0400'		전광판 ON TIME
                pObj->PANL_OFF_TIME      = pADO->FieldByName("PANL_OFF_TIME")->AsString.Trim();     //	N	VARCHAR2(4)	Y	'0200'		전광판 OFF TIME
                if (pObj->PANL_ON_TIME  == "9999" || pObj->PANL_ON_TIME.Length()  != 4) pObj->PANL_ON_TIME  = "0000";
                if (pObj->PANL_OFF_TIME == "9999" || pObj->PANL_OFF_TIME.Length() != 4) pObj->PANL_OFF_TIME = "0000";

                pObj->PANL_PWER_MODE     = pADO->FieldByName("PANL_PWER_MODE")->AsInteger;          //	N	NUMBER(3)	Y	2		전광판 전원 모드(0x00:꺼짐,0x01:켜짐,0x02:자동,0x09:알수없음)
                pObj->FAN_MODE           = pADO->FieldByName("FAN_MODE")->AsInteger;                //	N	NUMBER(3)	Y	2		FAN 동작모드(0x00:꺼짐,0x01:켜짐,0x02:자동,0x09:알수없음)
                pObj->FAN_RUN_TMPR       = pADO->FieldByName("FAN_RUN_TMPR")->AsInteger;            //	N	NUMBER(3)	Y	30		팬 동작 온도
                pObj->HETR_MODE          = pADO->FieldByName("HETR_MODE")->AsInteger;               //	N	NUMBER(3)	Y	2		히터 동작모드(0x00:꺼짐,0x01:켜짐,0x02:자동,0x09:알수없음)
                pObj->HETR_RUN_TMPR      = pADO->FieldByName("HETR_RUN_TMPR")->AsInteger;           //	N	NUMBER(3)	Y	0		히터 동작 온도
                pObj->BRGH_MODE          = pADO->FieldByName("BRGH_MODE")->AsInteger;               //	N	NUMBER(3)	Y	2		휘도 모드(0x00:주간,0x01:야간,0x00:자동,0x09:알수없음)
                pObj->BRGH_CURR_STEP     = pADO->FieldByName("BRGH_CURR_STEP")->AsInteger;          //	N	NUMBER(3)	Y	40		휘도 현재 단계(0~100)
                pObj->BRGH_WEEK_STEP     = pADO->FieldByName("BRGH_WEEK_STEP")->AsInteger;          //	N	NUMBER(3)	Y	64		휘도 주간 단계(0~100)
                pObj->BRGH_NGHT_STEP     = pADO->FieldByName("BRGH_NGHT_STEP")->AsInteger;          //	N	NUMBER(3)	Y	48		휘도 야간 단계(0~100)

                pObj->OLD_PANL_PWER_MODE = pObj->PANL_PWER_MODE;
                pObj->OLD_FAN_MODE       = pObj->FAN_MODE;
                pObj->OLD_FAN_RUN_TMPR   = pObj->FAN_RUN_TMPR;
                pObj->OLD_HETR_MODE      = pObj->HETR_MODE;
                pObj->OLD_HETR_RUN_TMPR  = pObj->HETR_RUN_TMPR;
                pObj->OLD_BRGH_MODE      = pObj->BRGH_MODE;
                pObj->OLD_BRGH_CURR_STEP = pObj->BRGH_CURR_STEP;
                pObj->OLD_BRGH_WEEK_STEP = pObj->BRGH_WEEK_STEP;
                pObj->OLD_BRGH_NGHT_STEP = pObj->BRGH_NGHT_STEP;

                pObj->MODL_ERR_RATE      = pADO->FieldByName("MODL_ERR_RATE")->AsInteger;           //	N	NUMBER(3)	Y	10		VMS 모듈 오류 율
                pObj->CMNC_FAIL_RATE     = pADO->FieldByName("CMNC_FAIL_RATE")->AsInteger;          //	N	NUMBER(3)	Y	60		VMS 통신 오류 기본 값

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

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

                OnOff    = vms_req_board_power_on;
                nOnTime  = pObj->PANL_ON_TIME.ToIntDef(0);
                nOffTime = pObj->PANL_OFF_TIME.ToIntDef(0);
                if (nOnTime != nOffTime)
                {
                    if (nOnTime > nOffTime)
                    {
                        // 0100(off), 0500(on)
                        if (nCurrTime >= nOffTime && nCurrTime < nOnTime)
                        {
                            OnOff = vms_req_board_power_off;
                        }
                    }
                    else
                    if (nOffTime > nOnTime)
                    {
                        // 2300(off), 0500(on)
                        if (nCurrTime >= nOffTime || nCurrTime < nOnTime)
                        {
                            OnOff = vms_req_board_power_off;
                        }
                    }
                }
                pObj->MODULE.OnOff = OnOff;
                pObj->MODULE.IsOnOff = true;


                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.ScheduledMessageOperatingTime   = (short)pObj->DEF_PHSE_CHNG_CYCL;     /* 필수 계획된 메시지의 동작시간(초) */
                pObj->DSTATE.ModuleOperatingTemperature      = (short)pObj->MODL_ERR_RATE;          /* 필수 모듈 전원이 꺼지는 온도값(℃) */
                pObj->DSTATE.FanOperatingTemperature         = (short)pObj->FAN_RUN_TMPR;           /* 필수 Fan 동작 기준 온도값(℃) */
                pObj->DSTATE.HeaterOperatingTemperature      = (short)pObj->HETR_RUN_TMPR;          /* 필수 Heater 동작 기준 온도값(℃) */
                pObj->DSTATE.ModuleBasicFailureRate          = (short)pObj->MODL_ERR_RATE;          /* 선택 모듈 장애율 (한 개의 모듈을 장애로 처리하기 위한 픽셀의 백분율값) */
                pObj->DSTATE.ExternalLightOperatingLuminance = 0;                                   /* 선택 외부전등 동작 기준 휘도값 */
                pObj->DSTATE.MaximumRetry                    = 3;                                   /* 선택 최대 재시도 횟수(회) */
                pObj->DSTATE.ResponseTimeOut                 = 30;                                  /* 선택 최대응답대기시간 (초) */
                pObj->DSTATE.BlinkingCycleTime               = 100;                                 /* 선택 점멸시간 주기 ( 1/10초단위) */

                pObj->DSTATE.VMS_CTLR_NMBR  = CTLR_NMBR.ToIntDef(0);
                memcpy(&pObj->RSTATE, &pObj->DSTATE, sizeof(pObj->RSTATE));
                pObj->RSTATE.Comm  = vms_comm_error;
                pObj->RSTATE.Wcomm = vms_wcomm_error;

#if 0
                pObj->LUMINANCE.SchTime = Now().FormatString("yyyymmdd");
                pObj->LUMINANCE.Value   = 0;
                pObj->LUMINANCE.Retry   = 0;
#endif
                pObj->FSLog = new TITSLog(g_sLogDir + "Comm\\"+pObj->CTLR_ID + "\\", pObj->CTLR_ID+"S", g_AppCfg.sLogDay);
                pObj->FCLog = new TITSLog(g_sLogDir + "Comm\\"+pObj->CTLR_ID + "\\", pObj->CTLR_ID+"C", g_AppCfg.sLogDay);
                pObj->FSLog->FLogCfg = g_LogCfg;
                pObj->FCLog->FLogCfg = g_LogCfg;

                if (COMM_CheckAddress(pObj->CTLR_IP.c_str()) &&
                    pObj->pPackQueue &&
                    pObj->FSLog      &&
                    pObj->FCLog      )
                {
                    pObj->Server.useFlag  = use_enable;
                    pObj->Server.thrState = thr_run;

                    pObj->Client.useFlag  = use_enable;
                    pObj->Client.thrState = thr_run;
                }

                pObj->SCHEDULE = new VMS_SCHEDULE_INFO;
                pObj->SCHEDULE->Count = 0;
                pObj->InitSchedule();   //스케줄정보

                pObj->EVEHICLE = new VMS_EVEHICLE_INFO;
                pObj->EVEHICLE->Count = 0;
                pObj->InitEVehicle();   // 긴급차량우선신호

                pObj->EVEHICLE->IsOcurr = false;
                pObj->EVEHICLE->IsEnd   = false;
                pObj->EVEHICLE->dtOcurr = Now()-1;
                pObj->EVEHICLE->IsDownload = false;
                pObj->EVEHICLE->dtDownload = Now()-1;
                pObj->EVEHICLE->IsEVechFirst = false;


                pObj->INCIDENT = new VMS_EVENT_INFO;
                pObj->INCIDENT->Count = 0;
                pObj->InitIncident();   //돌발정보

                pObj->EVENT = new VMS_EVENT_INFO;
                pObj->EVENT->Count = 0;
                pObj->InitEvent();      //이벤트(공사/행사)정보

                pObj->FMaxCngsForm = VMS_MAX_CNGS_FORM;

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

                pObj->CTRLMODE = new VMS_CONTROL_MODE;
                pObj->InitCtrlMode();

                //pObj->VMS_MAX_PHSE_NUM = INT_VMS_MAX_FORM;
#if 0
                if (pObj->VMS_MAX_PHSE_NUM > INT_VMS_MAX_FORM)
                    pObj->VMS_MAX_PHSE_NUM = INT_VMS_MAX_FORM;
#else
                //TODO: 도로공사 프로토콜(최대 10개)
                if (pObj->VMS_MAX_PHSE_NUM > MAX_VMS_SCENARIO_FORM)
                    pObj->VMS_MAX_PHSE_NUM = MAX_VMS_SCENARIO_FORM;
#endif

                pObj->CTRLMODE->MaxDisplayForm = pObj->VMS_MAX_PHSE_NUM;
                pObj->CTRLMODE->Control        = pObj->DSTATE.OprMode;

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

                pObj->FLocalFormDir = g_sFtpFormDir + pObj->CTLR_NMBR + "\\";
                ForceDirectories(pObj->FLocalFormDir.c_str());

                pObj->FFtpFormDir = AnsiString(FTP_FORM) + "\\" + pObj->CTLR_NMBR + "\\";    // 제어기에 내려보낼때 사용할 폼이저장되어 있는 경로
                pObj->FIsFtpDownload = true;
            }
        }
        catch(EDatabaseError &E)
        {
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
        }
    }
    __finally
    {
        FLists.UnLock();
        SQLFree(pADO);
    }

    SELEND(FLists.Size(), dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(FLists.Size(), dwTick);
    }

    if (LoadCtlrStts(ADbConn) < 0)
    {
        return -1;
    }

    return FLists.Size();
}
//---------------------------------------------------------------------------
int TCDSCtlrManager::LoadCtlrStts(TADOConnection *ADbConn)
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;

    DWORD dwTick = GetTickCount();
    SELSTART;

    sQry = "SELECT A.*                                \r\n"
           "  FROM TB_VMS_CTLR_STTS 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->Connection = ADbConn;

			SQLText(pADO, sQry, true);

			SQLOpen(pADO);
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString CTLR_NMBR = pADO->FieldByName("VMS_CTLR_NMBR")->AsAnsiString;
                TCDSCtlr *pObj = FLists.Find(CTLR_NMBR);
                if (!pObj) continue;

                nSelCnt++;

                AnsiString MODL_STTS_CD = pADO->FieldByName("MODL_STTS_CD")->AsString.Trim();
                AnsiString DOOR_STTS_CD = pADO->FieldByName("CBOX_DOOR_STTS_CD")->AsString.Trim();
                AnsiString FAN_STTS_CD  = pADO->FieldByName("FAN_STTS_CD")->AsString.Trim();
                AnsiString HETR_STTS_CD = pADO->FieldByName("HETR_STTS_CD")->AsString.Trim();
                int        CBOX_TMPR    = pADO->FieldByName("CBOX_TMPR")->AsInteger;
                int        BRGH_VAL     = pADO->FieldByName("BRGH_VAL")->AsInteger;
                AnsiString COMM_STTS_CD = pADO->FieldByName("COMM_STTS_CD")->AsString.Trim();

                pObj->DSTATE.ModulePowerStatus = MODL_STTS_CD == "MOS0" ? vms_module_power_on : vms_module_power_off;
                pObj->DSTATE.DoorStatus        = DOOR_STTS_CD == "CDS0" ? vms_door_close      : vms_door_open;
                pObj->DSTATE.FanStatus         = FAN_STTS_CD  == "PAS0" ? vms_fan_on          : vms_fan_off;
                pObj->DSTATE.HeaterStatus      = HETR_STTS_CD == "HTS0" ? vms_heater_on       : vms_heater_off;
                pObj->DSTATE.BodyTemp          = (short)CBOX_TMPR;
                pObj->DSTATE.LuminanceStatus   = (BYTE)BRGH_VAL;
                pObj->DSTATE.Wcomm             = COMM_STTS_CD == "CMS0" ? vms_wcomm_normal : vms_comm_error;

#if 0
                memcpy(&pObj->RSTATE, &pObj->DSTATE, sizeof(pObj->RSTATE));
#endif
            }
        }
        catch(EDatabaseError &E)
        {
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
        }
    }
    __finally
    {
        SQLFree(pADO);
    }

    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
    return nSelCnt;
}
//---------------------------------------------------------------------------
void TCDSCtlrManager::InitProvide(TCDSCtlr *AObj/*=NULL*/)
{
    try
    {
        //FLists.Lock();
        CtlrItr it;
        for(it=FLists.FObjects.begin(); it != FLists.FObjects.end(); ++it)
        {
            TCDSCtlr *pObj = (TCDSCtlr*)it->second;
            if (AObj == NULL || pObj == AObj)
            {
                pObj->FProvide = true;
            }
        }
    }
    __finally
    {
        //FLists.UnLock();
    }
}
//---------------------------------------------------------------------------
int TCDSCtlrManager::SaveCtlrStts(TADOConnection *ADbConn, void *AData)
{
	int        nSelCnt = 0;
	AnsiString sQry;
	TADOQuery *pADO = NULL;

    bool       bSaveIpAddr = false;
    bool       bSaveHist = false;

    CTLR_STTS *pStts = (CTLR_STTS*)AData;
    if (!pStts) return -1;

    TCDSCtlr *pObj = (TCDSCtlr*)pStts->ObjPtr;
    if (!pObj) return -2;

    //DWORD dwTick = GetTickCount();
    //JOBSTART;

    // 상태정보를 수집하면 실시간으로 업데이트 하고 운영단말로 전송하자
    if (pStts->Type == 0)   // 상태정보를 수신한 경우
    {
        // 제어기가 최초로 접속한 경우에는 상태정보를 바로 알수 없기 때문에 기존의 상태정보를 업데이트 하지 않기위해
        // 제거이가 상태정보를 수신한 경우에만 상태정보를 업데이트하도록 한다.
        memcpy(&pObj->DSTATE, &pObj->RSTATE, sizeof(pObj->DSTATE));
    }
    else
    {
        //통신 연결 또는 종료
        bSaveHist = true;
    }

    pObj->DSTATE.Comm = pObj->Server.commState == comm_open ? vms_comm_normal : vms_comm_error;

    TDateTime tmStts = Now();
    if (SecondOfTheDay(pObj->tmStts) >= SecondOfTheDay(tmStts))
    {
        //연결이 종료 되었다가 바로 접속되는 경우가 있어서 이력저장할때 Primary Key 중복에러가 발생한다.
        tmStts = IncSecond(pObj->tmStts, 1);
    }
    pObj->tmStts = tmStts;

    String UPDT_DT = pObj->tmStts.FormatString("yyyymmddhhnnss");

    if (pObj->DSTATE.Comm == vms_comm_normal)
    {
        if (pObj->CTLR_IP != pObj->LOGIN_IPADDR)
        {
            pObj->CTLR_IP = pObj->LOGIN_IPADDR;
            bSaveIpAddr = true;
        }
    }

#if 0
// 여기서는 데이터베이스에 저장하지 말고 그냥 클라이언트로 실시간 정보만 전달하도록 하자
// 1분마다 주기적으로 데이터베이스는 업데이트 한다.

    String sQry = (g_AppCfg.UpdateMode == 0) ? g_sUpdate : g_sMerge;

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

		try
		{
            SQLText(pADO, sQry, false);

            int    VMS_CTLR_NMBR     = pObj->CTLR_NMBR.ToIntDef(0);
            String CMNC_STTS_CD      = pObj->DSTATE.Comm              == vms_comm_normal     ? "CMS0" : "CMS1";
            String MODL_STTS_CD      = pObj->DSTATE.ModulePowerStatus == vms_module_power_on ? "MOS0" : "MOS1";
            String CBOX_DOOR_STTS_CD = pObj->DSTATE.DoorStatus        == vms_door_close      ? "CDS0" : "CDS1";
            String FAN_STTS_CD       = pObj->DSTATE.FanStatus         == vms_fan_on          ? "PAS0" : "PAS1";
            String HETR_STTS_CD      = pObj->DSTATE.HeaterStatus      == vms_heater_on       ? "HTS0" : "HTS1";
            String COMM_STTS_CD      = pObj->DSTATE.Wcomm             == vms_wcomm_normal    ? "CMS0" : "CMS1";
            int    CBOX_TMPR         = (int)(pObj->DSTATE.BodyTemp);
            int    BRGH_VAL          = (int)(pObj->DSTATE.LuminanceStatus);
            String PWER_STTS_CD      = pObj->DSTATE.PowerCtrlStatus == vms_module_power_on ? "MOS0" : "MOS1";
            String MODL_STTS         = "";
            String PWER_STTS         = "";

            if (pObj->DSTATE.ModulePowerStatus == 0x02) MODL_STTS_CD      = "MOS2";
            if (pObj->DSTATE.DoorStatus        == 0x02) CBOX_DOOR_STTS_CD = "CDS2";
            if (pObj->DSTATE.FanStatus         == 0x02) FAN_STTS_CD       = "PAS2";
            if (pObj->DSTATE.HeaterStatus      == 0x02) HETR_STTS_CD      = "HTS2";

            if (CMNC_STTS_CD != "CMS0" || COMM_STTS_CD != "CMS0") //통신이 종료된 경우 상태정보를 업데이트 하지 않는다.
            {
                MODL_STTS_CD      = "MOS2";
                PWER_STTS_CD      = "MOS2";
                CBOX_DOOR_STTS_CD = "CDS2";
                FAN_STTS_CD       = "PAS2";
                HETR_STTS_CD      = "HTS2";
                CBOX_TMPR         = 0;
                BRGH_VAL          = 0;
                COMM_STTS_CD      = "CMS2";
                MODL_STTS         = "";
                PWER_STTS         = "";
            }

            SQLBind(pADO, "p01", VMS_CTLR_NMBR);
            SQLBind(pADO, "p02", UPDT_DT);
            SQLBind(pADO, "p03", CMNC_STTS_CD);
            SQLBind(pADO, "p04", PWER_STTS_CD);
            SQLBind(pADO, "p05", MODL_STTS_CD);
            SQLBind(pADO, "p06", CBOX_DOOR_STTS_CD);
            SQLBind(pADO, "p07", FAN_STTS_CD);
            SQLBind(pADO, "p08", HETR_STTS_CD);
            SQLBind(pADO, "p09", CBOX_TMPR);
            SQLBind(pADO, "p10", BRGH_VAL);
            SQLBind(pADO, "p11", COMM_STTS_CD);
            SQLBind(pADO, "p12", MODL_STTS);
            SQLBind(pADO, "p13", PWER_STTS);

            nSelCnt = SQLExec(pADO);

            bSaveHist = false;
            if (bSaveHist)
            {
    sQry = "INSERT INTO TB_VMS_CTLR_STTS_HS (  \r\n"
           "            CRTN_DT,               \r\n"
           "            VMS_CTLR_NMBR,         \r\n"
           "            CMNC_STTS_CD,          \r\n"
           "            PWER_STTS_CD,          \r\n"
           "            MODL_STTS_CD,          \r\n"
           "            CBOX_DOOR_STTS_CD,     \r\n"
           "            FAN_STTS_CD,           \r\n"
           "            HETR_STTS_CD,          \r\n"
           "            CBOX_TMPR,             \r\n"
           "            BRGH_VAL,              \r\n"
           "            COMM_STTS_CD)          \r\n"
           "     SELECT UPDT_DT,               \r\n"
           "            VMS_CTLR_NMBR,         \r\n"
           "            CMNC_STTS_CD,          \r\n"
           "            PWER_STTS_CD,          \r\n"
           "            MODL_STTS_CD,          \r\n"
           "            CBOX_DOOR_STTS_CD,     \r\n"
           "            FAN_STTS_CD,           \r\n"
           "            HETR_STTS_CD,          \r\n"
           "            CBOX_TMPR,             \r\n"
           "            BRGH_VAL,              \r\n"
           "            COMM_STTS_CD           \r\n"
           "       FROM TB_VMS_CTLR_STTS       \r\n"
           "      WHERE VMS_CTLR_NMBR = :p01   \r\n";

                SQLText(pADO, sQry, false);

                SQLBind(pADO, "p01", VMS_CTLR_NMBR);

                SQLExec(pADO);
            }
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        SQLFree(pADO);
	}
#endif

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

    CComm_VmsStateNotify(&Res);

    //JOBEND(dwTick);
    //if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
    //    TIMEDELAY(nSelCnt, dwTick);
    //}

    if (bSaveIpAddr)
    {
        SaveCtlrIpAddr(ADbConn, AData);
    }

	return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSCtlrManager::SaveCtlrIpAddr(TADOConnection *ADbConn, void *AData)
{
	int        nSelCnt = 0;
	AnsiString sQry;
	TADOQuery *pADO = NULL;

    CTLR_STTS *pStts = (CTLR_STTS*)AData;
    if (!pStts) return -1;

    TCDSCtlr *pObj = (TCDSCtlr*)pStts->ObjPtr;
    if (!pObj) return -2;

    return 1;
    DWORD dwTick = GetTickCount();
    UPDSTART;

    sQry = "UPDATE TB_VMS_CTLR          \r\n"
           "   SET VMS_CTLR_IP = :p02   \r\n"
           " WHERE VMS_CTLR_NMBR = :p01 \r\n";

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

		try
		{
            SQLText(pADO, sQry, false);

            int    VMS_CTLR_NMBR = pObj->CTLR_NMBR.ToIntDef(0);
            String VMS_CTLR_IP   = pObj->CTLR_IP;

            SQLBind(pADO, "p01", VMS_CTLR_NMBR);
            SQLBind(pADO, "p02", VMS_CTLR_IP);

            nSelCnt = SQLExec(pADO);
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        SQLFree(pADO);
	}

    UPDEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
	return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSCtlrManager::SaveCtlrSttsAll(TADOConnection *ADbConn)
{
	int        nSelCnt = 0;
	AnsiString sQry;
	TADOQuery *pADO = NULL;

    DWORD dwTick = GetTickCount();
    UPDSTART;

    // 1분주기 상태정보 업데이트, 5분마다 이력정보를 입력한다.
    bool bSaveHist = false;
    int nCurrMin = StrToInt(Now().FormatString("nn"));
    if ((nCurrMin % 5) == 0) //매 5분마다 무조건 입력
    {
        if (FCtlrStts5Min != nCurrMin)
        {
            bSaveHist = true;
            FCtlrStts5Min = nCurrMin;
        }
    }

    sQry = (g_AppCfg.UpdateMode == 0) ? g_sUpdate : g_sMerge;
    String UPDT_DT = Now().FormatString("yyyymmddhhnnss");

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

		try
		{
            SQLText(pADO, sQry, false);

            CtlrItr it;
            for(it=FLists.FObjects.begin(); it != FLists.FObjects.end(); ++it)
            {
                TCDSCtlr *pObj = (TCDSCtlr*)it->second;

                if (pObj->Server.useFlag != use_enable) continue;

                pObj->DSTATE.Comm = pObj->Server.commState == comm_open ? vms_comm_normal : vms_comm_error;

                int    VMS_CTLR_NMBR     = pObj->CTLR_NMBR.ToIntDef(0);
                String CMNC_STTS_CD      = pObj->DSTATE.Comm              == vms_comm_normal     ? "CMS0" : "CMS1";
                String MODL_STTS_CD      = pObj->DSTATE.ModulePowerStatus == vms_module_power_on ? "MOS0" : "MOS1";
                String CBOX_DOOR_STTS_CD = pObj->DSTATE.DoorStatus        == vms_door_close      ? "CDS0" : "CDS1";
                String FAN_STTS_CD       = pObj->DSTATE.FanStatus         == vms_fan_on          ? "PAS0" : "PAS1";
                String HETR_STTS_CD      = pObj->DSTATE.HeaterStatus      == vms_heater_on       ? "HTS0" : "HTS1";
                String COMM_STTS_CD      = pObj->DSTATE.Wcomm             == vms_wcomm_normal    ? "CMS0" : "CMS1";
                int    CBOX_TMPR         = (int)(pObj->DSTATE.BodyTemp);
                int    BRGH_VAL          = (int)(pObj->DSTATE.LuminanceStatus);
                String PWER_STTS_CD      = pObj->DSTATE.PowerCtrlStatus == vms_module_power_on ? "MOS0" : "MOS1";
                String MODL_STTS         = "";
                String PWER_STTS         = "";

                if (pObj->DSTATE.ModulePowerStatus == 0x02) MODL_STTS_CD      = "MOS2";
                if (pObj->DSTATE.DoorStatus        == 0x02) CBOX_DOOR_STTS_CD = "CDS2";
                if (pObj->DSTATE.FanStatus         == 0x02) FAN_STTS_CD       = "PAS2";
                if (pObj->DSTATE.HeaterStatus      == 0x02) HETR_STTS_CD      = "HTS2";

                if (CMNC_STTS_CD != "CMS0" || COMM_STTS_CD != "CMS0") //통신이 종료된 경우 상태정보를 업데이트 하지 않는다.
                {
                    MODL_STTS_CD      = "MOS2";
                    PWER_STTS_CD      = "MOS2";
                    CBOX_DOOR_STTS_CD = "CDS2";
                    FAN_STTS_CD       = "PAS2";
                    HETR_STTS_CD      = "HTS2";
                    CBOX_TMPR         = 0;
                    BRGH_VAL          = 0;
                    COMM_STTS_CD      = "CMS2";
                    MODL_STTS         = "";
                    PWER_STTS         = "";
                }

        //PostMessage((HWND)g_AppCfg.lMainWinHandle, WM_PANEL_REFRESH, 2, (LPARAM)clAqua);

                SQLBind(pADO, "p01", VMS_CTLR_NMBR);
                SQLBind(pADO, "p02", UPDT_DT);
                SQLBind(pADO, "p03", CMNC_STTS_CD);
                SQLBind(pADO, "p04", PWER_STTS_CD);
                SQLBind(pADO, "p05", MODL_STTS_CD);
                SQLBind(pADO, "p06", CBOX_DOOR_STTS_CD);
                SQLBind(pADO, "p07", FAN_STTS_CD);
                SQLBind(pADO, "p08", HETR_STTS_CD);
                SQLBind(pADO, "p09", CBOX_TMPR);
                SQLBind(pADO, "p10", BRGH_VAL);
                SQLBind(pADO, "p11", COMM_STTS_CD);
                SQLBind(pADO, "p12", MODL_STTS);
                SQLBind(pADO, "p13", PWER_STTS);

                nSelCnt += SQLExec(pADO);

        //PostMessage((HWND)g_AppCfg.lMainWinHandle, WM_PANEL_REFRESH, 2, (LPARAM)clLime);
            }

            UPDEND(nSelCnt, dwTick);
            if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
                TIMEDELAY(nSelCnt, dwTick);
            }

            if (bSaveHist)
            {
                int nInsCnt = 0;
                dwTick = GetTickCount();
                INSSTART;
#if 0
    sQry = "INSERT INTO TB_VMS_CTLR_STTS_HS (  \r\n"
           "            CRTN_DT,               \r\n"
           "            VMS_CTLR_NMBR,         \r\n"
           "            CMNC_STTS_CD,          \r\n"
           "            PWER_STTS_CD,          \r\n"
           "            MODL_STTS_CD,          \r\n"
           "            CBOX_DOOR_STTS_CD,     \r\n"
           "            FAN_STTS_CD,           \r\n"
           "            HETR_STTS_CD,          \r\n"
           "            CBOX_TMPR,             \r\n"
           "            BRGH_VAL,              \r\n"
           "            COMM_STTS_CD,          \r\n"
           "            MODL_STTS,             \r\n"
           "            PWER_STTS )            \r\n"
           "     SELECT UPDT_DT,               \r\n"
           "            VMS_CTLR_NMBR,         \r\n"
           "            CMNC_STTS_CD,          \r\n"
           "            PWER_STTS_CD,          \r\n"
           "            MODL_STTS_CD,          \r\n"
           "            CBOX_DOOR_STTS_CD,     \r\n"
           "            FAN_STTS_CD,           \r\n"
           "            HETR_STTS_CD,          \r\n"
           "            CBOX_TMPR,             \r\n"
           "            BRGH_VAL,              \r\n"
           "            COMM_STTS_CD,          \r\n"
           "            MODL_STTS,             \r\n"
           "            PWER_STTS              \r\n"
           "       FROM TB_VMS_CTLR_STTS       \r\n"
           "      WHERE UPDT_DT = :p01         \r\n";
#else
    sQry = "INSERT INTO TB_VMS_CTLR_STTS_HS (  \r\n"
           "            CRTN_DT,               \r\n"
           "            VMS_CTLR_NMBR,         \r\n"
           "            CMNC_STTS_CD,          \r\n"
           "            PWER_STTS_CD,          \r\n"
           "            MODL_STTS_CD,          \r\n"
           "            CBOX_DOOR_STTS_CD,     \r\n"
           "            FAN_STTS_CD,           \r\n"
           "            HETR_STTS_CD,          \r\n"
           "            CBOX_TMPR,             \r\n"
           "            BRGH_VAL,              \r\n"
           "            COMM_STTS_CD)          \r\n"
           "     SELECT UPDT_DT,               \r\n"
           "            VMS_CTLR_NMBR,         \r\n"
           "            CMNC_STTS_CD,          \r\n"
           "            PWER_STTS_CD,          \r\n"
           "            MODL_STTS_CD,          \r\n"
           "            CBOX_DOOR_STTS_CD,     \r\n"
           "            FAN_STTS_CD,           \r\n"
           "            HETR_STTS_CD,          \r\n"
           "            CBOX_TMPR,             \r\n"
           "            BRGH_VAL,              \r\n"
           "            COMM_STTS_CD           \r\n"
           "       FROM TB_VMS_CTLR_STTS       \r\n"
           "      WHERE UPDT_DT = :p01         \r\n";
#endif

                SQLText(pADO, sQry, false);

                SQLBind(pADO, "p01", UPDT_DT);

                nInsCnt = SQLExec(pADO);

                INSEND(nInsCnt, dwTick);
                if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
                    TIMEDELAY(nInsCnt, dwTick);
                }
            }
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        SQLFree(pADO);
	}

	SendCtlrSttsAll();

    return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSCtlrManager::SendCtlrSttsAll()
{
	int               nSelCnt = 0;
    INT_VMS_STATE_RES Res;
    INT_VMS_STATE    *pVms;

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

    CtlrItr it;
    for(it=FLists.FObjects.begin(); it != FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;

        if (pObj->Server.useFlag != use_enable) continue;

        pVms = &Res.Unit[Res.Count++];

        memcpy((char*)pVms, (char*)&pObj->DSTATE, sizeof(INT_VMS_STATE));
        if (Res.Count >= (BYTE)INT_VMS_MAX_STATE)
        {
            CComm_VmsStateNotify(&Res);

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

    if (Res.Count > 0)
    {
        CComm_VmsStateNotify(&Res);
    }

	return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSCtlrManager::SaveCtlrParam(TADOConnection *ADbConn, void *AData)
{
	int        nSelCnt = 0;
	AnsiString sQry;
	TADOQuery *pADO = NULL;

    CTLR_STTS *pStts = (CTLR_STTS*)AData;
    if (!pStts) return -1;

    TCDSCtlr *pObj = (TCDSCtlr*)pStts->ObjPtr;
    if (!pObj) return -2;

    DWORD dwTick = GetTickCount();
    UPDSTART;

    sQry = "UPDATE TB_VMS_CTLR             "
           "   SET PANL_PWER_MODE = :p02,  "
           "       FAN_MODE       = :p03,  "
           "       FAN_RUN_TMPR   = :p04,  "
           "       HETR_MODE      = :p05,  "
           "       HETR_RUN_TMPR  = :p06,  "
           "       BRGH_MODE      = :p07,  "
           "       BRGH_CURR_STEP = :p08,  "
           "       BRGH_WEEK_STEP = :p09,  "
           "       BRGH_NGHT_STEP = :p10   "
           " WHERE VMS_CTLR_NMBR  = :p01   ";

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

		try
		{
            SQLText(pADO, sQry, false);

            int VMS_CTLR_NMBR = pObj->CTLR_NMBR.ToIntDef(0);

            SQLBind(pADO, "p01", VMS_CTLR_NMBR);
            SQLBind(pADO, "p02", pObj->PANL_PWER_MODE);
            SQLBind(pADO, "p03", pObj->FAN_MODE);
            SQLBind(pADO, "p04", pObj->FAN_RUN_TMPR);
            SQLBind(pADO, "p05", pObj->HETR_MODE);
            SQLBind(pADO, "p06", pObj->HETR_RUN_TMPR);
            SQLBind(pADO, "p07", pObj->BRGH_MODE);
            SQLBind(pADO, "p08", pObj->BRGH_CURR_STEP);
            SQLBind(pADO, "p09", pObj->BRGH_WEEK_STEP);
            SQLBind(pADO, "p10", pObj->BRGH_NGHT_STEP);

            nSelCnt = SQLExec(pADO);
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        SQLFree(pADO);
	}

    //파라미터정보를 클라이언트로 전송
    INT_VMS_PARAM_RES  Res;
    INT_VMS_PARAM     *pData;

    memset((char*)&Res, 0x00, sizeof(Res));
    Res.Total = CDSCtlrManager->Total;
    Res.Error = CDSCtlrManager->Error;
    Res.Normal= CDSCtlrManager->Normal;
    Res.Module= CDSCtlrManager->Module;
    Res.Count = 1;
    pData = &Res.Unit[0];

    pData->VMS_CTLR_NMBR = pObj->CTLR_NMBR.ToIntDef(0);
    pData->led           = (BYTE)pObj->PANL_PWER_MODE;                      // 0x00 : 꺼짐, 0x01 : 켜짐, 0x02 : 자동, 0x09 : 알수없음
    pData->fan           = (BYTE)pObj->FAN_MODE;                            // 0x00 : 꺼짐, 0x01 : 켜짐, 0x02 : 자동, 0x09 : 알수없음
    pData->fanTmpr       = (BYTE)pObj->FAN_RUN_TMPR;                        // Fan 동작온도(0x00~0x3f)
    pData->hetr          = (BYTE)pObj->HETR_MODE;                           // 0x00 : 꺼짐, 0x01 : 켜짐, 0x02 : 자동, 0x09 : 알수없음
    pData->hetrTmpr      = (BYTE)pObj->HETR_RUN_TMPR;                       // Heater 동작온도(0x00~0x3f)
    pData->brgh          = (BYTE)pObj->BRGH_MODE;                           // 0x00 : 주간, 0x01 : 야간, 0x02 : 자동, 0x09 : 수동
    pData->brghVal       = (BYTE)pObj->BRGH_CURR_STEP;                      // 현재휘도값 (0 ~ 100)
    pData->brghDay       = (BYTE)pObj->BRGH_WEEK_STEP;                      // 주간 휘도값(0 ~ 100)
    pData->brghNight     = (BYTE)pObj->BRGH_NGHT_STEP;                      // 야간 휘도값(0 ~ 100)
    memcpy(pData->time, pObj->ParamResTime.c_str(), INT_VMS_MAX_DATETIME);  // 현재 제어기 시간

    CComm_VmsParamNotify(&Res);

    UPDEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
	return nSelCnt;
}
//---------------------------------------------------------------------------

