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


#pragma hdrstop

#include "VMSCThread.h"
#include "VMSCThreadRecvF.h"

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

#pragma package(smart_init)

/*
 * 패킷 수신
 *  arguments
 *   void
 *  return
 *   void
 */
int __fastcall TVMSCThread::RecvPacket(BYTE *ABuffer, int ALen)
{
FErrLine = 3;
    int       result = SYS_ERR_NONE;
    BYTE      data;
    PKT_HEAD *pHd = (PKT_HEAD*)m_RxBuff;

    if (ALen > 0)
    {
        LogData("RECV", (char*)ABuffer, ALen);
    }

    m_rcvPacketTimer = Now();

    for (int ii = 0; ii < ALen; ii++)
    {
        data = ABuffer[ii];
        switch(m_RxState)
        {
        case RX_STX:
            if (data == VMS_STX)
            {
                m_RxBuff[m_RxLen++] = data;
                m_RxState = RX_HEAD;
            }
            else
            {
                LERROR("Receive packet format sequence error[STX]: %02X, %d", data, m_RxLen);
                InitRx();
            }
            break;

        case RX_HEAD:
             m_RxBuff[m_RxLen++] = data;
             if (m_RxLen == (int)sizeof(PKT_HEAD))
             {
                m_RxDataLen = htonl(pHd->Size);

                if (m_RxDataLen > (CLIENT_RCV_BUF_SIZE-10) || m_RxDataLen == 0)
                {
                    LERROR("Receive packet length error: %d", m_RxDataLen);
                    InitRx();
                }
                else
                {
                    m_RxPktLen = 1 + 1 + m_RxDataLen; // stx+etx+data(id~crc)
                    m_RxState = RX_DATA;
                }
             }
             break;

        case RX_DATA:
             // 나머지 데이터에 대한 유효성 처리는 하지 않는다.(ETX 체크안함)
             m_RxBuff[m_RxLen++] = data;
             if (m_RxLen == m_RxPktLen)
             {
                //패킷완성
                result = ProcessRecvPacket(m_RxBuff, m_RxPktLen);
                InitRx();
                m_WatchDogTimer = Now();
             }
             break;
        }
    }

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

/*
 * 수신 패킷 처리
 *  arguments
 *   void
 *  return
 *   void
 */
int __fastcall TVMSCThread::ProcessRecvPacket(BYTE *ABuffer, int ARcvLen)
{
FErrLine = 4;
    VMS_PACKET *Pkt    = (VMS_PACKET*)ABuffer;
	int         result = SYS_ERR_NONE;

    InfoPacket(ABuffer, ARcvLen, false);

    switch(Pkt->hd.OpCode)
    {
    case RES_VMS_STATUS://                   0x50        // Status 응답,  VMS->센터
        result = ResVmsStatus(ABuffer, ARcvLen);
        break;
    case RES_VMS_MSG_DOWNLOAD://             0x51        // 문안 전송 응답, VMS->센터
        result = ResVmsMsgDownload(ABuffer, ARcvLen);
        break;
    case RES_VMS_LIB_DOWNLOAD://             0x52        // Library download 응답, VMS->센터
        result = ResVmsLibDownload(ABuffer, ARcvLen);
        break;
    case RES_VMS_PARAM_DOWNLOAD://           0x53        // Parameter download 응답, VMS->센터
        break;
    case RES_VMS_BLANK_DISP://               0x54        // Blank 응답, VMS->센터
        break;
    case RES_VMS_DEF_MSG_DISP://             0x55        // Default message display 응답, VMS->센터
        break;
    case RES_VMS_MODULE_STATUS://            0x56        // Module status upload 응답, VMS->센터
        result = ResVmsModuleStatus(ABuffer, ARcvLen);
        break;
    case RES_VMS_INITIALIZE://               0x57        // Initialize 응답, VMS->센터
        result = ResVmsInitialize(ABuffer, ARcvLen);
        break;
    case RES_VMS_LUMINANCE_LEVEL_SET://      0x58        // Luminance level set 응답, VMS->센터
        break;
    case RES_SIGNBOARD_POWER_CONTROL://      0x59        // Signboard power control 응답, VMS->센터
        result = ResVmsSignboardPowerControl(ABuffer, ARcvLen);
        break;
    default:
        LERROR("<<< Unknown ProcessRecvPacket: 0x%02X", Pkt->hd.OpCode);
        return SYS_ERR_UNKNOWN_COMMAND;
    }

	if (result == SYS_ERR_NONE)
    {
		FClient.sendRetry = VMS_MAX_RETRY_COUNT;
	}

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

// Initialize 요청 응답
int __fastcall TVMSCThread::ResVmsInitialize(BYTE *ABuffer, int ARcvLen)
{
    VMS_PACKET *Pkt    = (VMS_PACKET*)ABuffer;
	int         result = SYS_ERR_NONE;

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

// Signboard powwer control 요청 응답
int __fastcall TVMSCThread::ResVmsSignboardPowerControl(BYTE *ABuffer, int ARcvLen)
{
    VMS_PACKET *Pkt    = (VMS_PACKET*)ABuffer;
	int         result = SYS_ERR_NONE;

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

// VMS 상태정보 요청 응답
int __fastcall TVMSCThread::ResVmsStatus(BYTE *ABuffer, int ARcvLen)
{
    VMS_PACKET *Pkt    = (VMS_PACKET*)ABuffer;
	int         result = SYS_ERR_NONE;
    ACK_NAK     res;

    if (FClient.State == CT_CLIENT_WAIT)
    {
        //TODO: 클라이언트로 결과전송
    }

    if (FLocalCmd.obj == OBJ_GeneralStatus)
    {
        FLocalCmd.GeneralStatus = true;
    }

    if (FClient.State == CT_CLIENT_WAIT)
        FClient.State = CT_CLIENT_COMMAND;
    else
    if (FClient.State == CT_LOCAL_WAIT)
        FClient.State = CT_LOCAL_COMMAND;

    SaveStatusData(ABuffer);

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

/*
 *
 *  arguments
 *   void
 *  return
 *   void
 */
int __fastcall TVMSCThread::SaveStatusData(BYTE *pGS)
{
	int         result = SYS_ERR_OTHER;
    VMS_STATUS1 status1;
    VMS_STATUS2 status2;
    short        temp;

	if (m_pState == NULL) return result;

#if 0
typedef struct tagVmsStatus1
{
    BYTE localModeActive  : 1;
    BYTE defaultParameter : 1;
    BYTE resetOccured     : 1;
    BYTE longPowerFail    : 1;
    BYTE shortPowerFail   : 1;
    BYTE doorOpen         : 1;
    BYTE moduleErrRateOver: 1;
    BYTE ramRomError      : 1;
} VMS_STATUS1;

typedef struct tagVmsStatus2
{
    BYTE libChecksumErr: 1;
    BYTE fan           : 1;
    BYTE heater        : 1;
    BYTE boardPower    : 1;
    BYTE boardPowerFail: 1;
    BYTE blankDisp     : 1;
    BYTE sirenFail     : 1;
    BYTE reserved      : 1;
} VMS_STATUS2;
#endif
    memcpy((char*)&status2, (char*)&pGS[11], sizeof(BYTE));
    memcpy((char*)&status1, (char*)&pGS[12], sizeof(BYTE));
    temp = (short)pGS[13];

    m_pState->DoorStatus        = status1.doorOpen   == 0x01 ? vms_open : vms_close;
    m_pState->ModulePowerStatus = status2.boardPower == 0x01 ? vms_on   : vms_off;
    m_pState->FanStatus         = status2.fan        == 0x01 ? vms_on   : vms_off;
    m_pState->HeaterStatus      = status2.heater     == 0x01 ? vms_on   : vms_off;
	m_pState->BodyTemp          = temp;
	m_pState->LuminanceStatus   = 0;  //PASIG 없음
    m_pState->ModuleState       = status1.moduleErrRateOver == 0x01 ? vms_error : vms_normal;

LDEBUG("     module_StatusCode: %2d, %s", status1.moduleErrRateOver, m_pState->ModuleState       == vms_normal ? "Normal" : "Error");
LDEBUG("modulePower_StatusCode: %2d, %s", status2.boardPower,        m_pState->ModulePowerStatus == vms_on     ? "On"     : "Off");
LDEBUG("       door_StatusCode: %2d, %s", status1.doorOpen,          m_pState->DoorStatus        == vms_open   ? "Open"   : "Close");
LDEBUG("        fan_StatusCode: %2d, %s", status2.fan,               m_pState->FanStatus         == vms_on     ? "On"     : "Off");
LDEBUG("     heater_StatusCode: %2d, %s", status2.heater,            m_pState->HeaterStatus      == vms_on     ? "On"     : "Off");
LDEBUG("   body_TemperatureQty: %2d, %d", temp,                      m_pState->BodyTemp         );
//LDEBUG("   luminance_StatusQty: %2d, %d", m_pState->LuminanceStatus, m_pState->LuminanceStatus  );

	result = SYS_ERR_NONE;

    //if (FGenState && FModState && FPowState)
    {
        //FGenState = FModState = FPowState = false;
        POST_MSG(MAINHANDLE, WM_VMS_THREAD, WM_VMS_STATE_STTS, (int)FVmsObj);
    }
	return result;
}
//---------------------------------------------------------------------------

// VMS 상태정보 요청 응답
int __fastcall TVMSCThread::ResVmsModuleStatus(BYTE *ABuffer, int ARcvLen)
{
    VMS_PACKET *Pkt    = (VMS_PACKET*)ABuffer;
	int         result = SYS_ERR_NONE;

    if (FClient.State == CT_CLIENT_WAIT)
    {
        //TODO: 클라이언트로 결과전송
    }

    if (FLocalCmd.obj == OBJ_ModuleStatus)
    {
        FLocalCmd.ModuleStatus = true;
    }

    if (FClient.State == CT_CLIENT_WAIT)
        FClient.State = CT_CLIENT_COMMAND;
    else
    if (FClient.State == CT_LOCAL_WAIT)
        FClient.State = CT_LOCAL_COMMAND;

    BYTE ModuleState;
    memset((char*)m_pState->ModuleStatus, 0x00, sizeof(m_pState->ModuleStatus));
    //INT_VMS_MAX_MODULE_BIT
    int nBytes = (int)CommUtil_swapl(Pkt->hd.Size);
    nBytes -= 12;
    if (FLogFile->FLogCfg.Debug)
    {
    LDEBUG("ModuleInfo Bytes: %d, %d", nBytes, nBytes*8);
        for (int ii = 0; ii < nBytes; ii++)
        {
    LDEBUG("                : %d, %02X", ii, Pkt->data[ii]);
        }
    }

    memcpy((char*)m_pState->ModuleStatus, (char*)Pkt->data, nBytes);
	return result;
}
//---------------------------------------------------------------------------

// VMS MSG Download 요청 응답
int __fastcall TVMSCThread::ResVmsMsgDownload(BYTE *ABuffer, int ARcvLen)
{
    VMS_PACKET *Pkt    = (VMS_PACKET*)ABuffer;
	int         result = SYS_ERR_NONE;

    try
    {
        m_pVmsFormList->Lock();

        int nFormCnt = m_pVmsFormList->Count();
        for (int ii = 0; ii < nFormCnt; ii++)
        {
            TVmsForm *pVmsForm = m_pVmsFormList->GetItem(ii);
            if (!pVmsForm) continue;

            pVmsForm->SvcRes = true;
        }
    }
    __finally
    {
        m_pVmsFormList->UnLock();
    }

    if (FLocalCmd.obj == OBJ_RealTimeDisplay)
    {
        SAVE_STRUCT ProvideSave;

        memset(&ProvideSave, 0x00, sizeof(ProvideSave));

        ProvideSave.Type    = save_provide;
        ProvideSave.Count   = 1;
        ProvideSave.pObj[0] = (void*)FVmsObj;

        FVmsObj->CTLMODE->Enable   = object_disable;
        FVmsObj->CTLMODE->SvcDate  = Now().FormatString("yyyymmddhhnnss");
        FVmsObj->CTLMODE->SaveFlag = true;
        FVmsObj->CTLMODE->Result   = true;


        if ((result = SendDbThreadDataMessage(WM_PROVIDE_SAVE, &ProvideSave, sizeof(ProvideSave))) != VERR_NONE)
        {
            SERROR("SendDbThreadDataMessage Error %d", result);
        }
    }

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

// VMS LIB Download 요청 응답
int __fastcall TVMSCThread::ResVmsLibDownload(BYTE *ABuffer, int ARcvLen)
{
    VMS_PACKET *Pkt    = (VMS_PACKET*)ABuffer;
	int         result = SYS_ERR_NONE;

    try
    {
        m_pVmsFormList->Lock();

        int nFormCnt = m_pVmsFormList->Count();
        for (int ii = 0; ii < nFormCnt; ii++)
        {
            TVmsForm *pVmsForm = m_pVmsFormList->GetItem(ii);
            if (!pVmsForm) continue;

            pVmsForm->SvcRes = true;
        }
    }
    __finally
    {
        m_pVmsFormList->UnLock();
    }

    if (FLocalCmd.obj == OBJ_RealTimeDisplay)
    {
        SAVE_STRUCT ProvideSave;

        memset(&ProvideSave, 0x00, sizeof(ProvideSave));

        ProvideSave.Type    = save_provide;
        ProvideSave.Count   = 1;
        ProvideSave.pObj[0] = (void*)FVmsObj;

        FVmsObj->CTLMODE->Enable   = object_disable;
        FVmsObj->CTLMODE->SvcDate  = Now().FormatString("yyyymmddhhnnss");
        FVmsObj->CTLMODE->SaveFlag = true;
        FVmsObj->CTLMODE->Result   = true;


        if ((result = SendDbThreadDataMessage(WM_PROVIDE_SAVE, &ProvideSave, sizeof(ProvideSave))) != VERR_NONE)
        {
            SERROR("SendDbThreadDataMessage Error %d", result);
        }
    }

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

