#include "StdAfx.h"
#include "TCLCommand.h"

#define NoneOptLen 5
#define MINSIZE 128
#define MIDSIZE 4096
#define MAXSIZE 10240

byte* TCLCommand::m_pData = NULL;
TCLCommand::TCLCommand(bool bSync):CBaseSerial(bSync ? 0 : FILE_FLAG_OVERLAPPED)
{
    m_pData = new byte[MAXSIZE];
}

TCLCommand::~TCLCommand(void)
{
    if (m_pData)
        delete []m_pData;
    m_pData = NULL;
    m_vtExternalCMDParams.clear();
    m_vtInternalCMDParams.clear();
}

int TCLCommand::pares_time_value(std::string strTime)
{
    int nTimes = 0;
#if _MSC_VER >= 1200 && _MSC_VER < 1500
    if (strstr(strTime.c_str(), _T("ms")) || strstr(strTime.c_str(), _T("MS")))
    {
        nTimes = atol(strTime.c_str());
    }
    else if (strstr(strTime.c_str(), _T("s")) || strstr(strTime.c_str(), _T("S")))
    {
        nTimes = atol(strTime.c_str()) * 1000;
    }
    else if (strstr(strTime.c_str(), _T("m")) || strstr(strTime.c_str(), _T("M")))
    {
        nTimes = atol(strTime.c_str()) * 6000;
    }
    else
    {
        // ������λ��������,Ĭ��ms;
        nTimes = atol(strTime.c_str());
    }
#elif _MSC_VER >= 1500
    if (_tcsstr(strTime.c_str(), _T("ms")) || _tcsstr(strTime.c_str(), _T("MS")))
    {
        nTimes = _tstol(strTime.c_str());
    }
    else if (_tcsstr(strTime.c_str(), _T("s")) || _tcsstr(strTime.c_str(), _T("S")))
    {
        nTimes = _tstol(strTime.c_str()) * 1000;
    }
    else if (_tcsstr(strTime.c_str(), _T("m")) || _tcsstr(strTime.c_str(), _T("M")))
    {
        nTimes = _tstol(strTime.c_str()) * 6000;
    }
    else
    {
        // ������λ��������,Ĭ��ms;
        nTimes = _tstol(strTime.c_str());
    }
#endif

    return nTimes;
}

bool TCLCommand::parse_pair_key(std::string& RetValue, std::string strLine, TCHAR* lpszText)
{
    TCHAR szText[MAX_PATH] = { 0 };
    TCHAR szValue[MAX_PATH] = { 0 };
    // ȥ���ո�;
#if _MSC_VER > 1900
    strLine.erase(std::remove_if(strLine.begin(), strLine.end(), [](unsigned char x) {return std::isspace(x); }), strLine.end()); //C++17
#else
    for (std::string::iterator it = strLine.begin(); it != strLine.end();) {
        !isspace(*it) ? it++ : it = it = strLine.erase(it);
    }
#endif

#if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0
    if (2 == sscanf(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH))
#else
    if (2 == _stscanf_s(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH))
#endif
    {
        if (_tcsstr(szText, lpszText)) {
            RetValue = szValue;
            return true;
        }
    }

    return false;
}

int TCLCommand::parse_cmds_from_file(const TCHAR* file_name, std::vector<CommandParam>& vtCommandParams)
{
    TCHAR buf[MAX_PATH] = { 0 };
    TCHAR name[MAX_PATH] = { 0 };
    TCHAR option[MAX_PATH] = { 0 };
    TCHAR head[MAX_PATH] = { 0 };
    TCHAR code[MAX_PATH] = { 0 };
    TCHAR param[MAX_PATH] = { 0 };
    TCHAR multicode[MAX_PATH] = { 0 };
    TCHAR cmd_wait_time[MAX_PATH] = { 0 };
    TCHAR read_wait_time[MAX_PATH] = { 0 };

    int ret = -1;
    FILE* fp = NULL;

    if (!file_name || file_name[0] == '\0')
        return ret;

    fp = fopen(file_name, "r");
    if (!fp)
        goto EXIT;

    while ((fgets((char*)buf, MAX_PATH, fp) != NULL)) {
        int tmp_len = 0;
        tmp_len = _tcslen(buf);
        if (tmp_len >= 1) {
            if (buf[tmp_len - 1] == '\r' || buf[tmp_len - 1] == '\n')
                buf[tmp_len - 1] = 0;
            if (tmp_len >= 2) {
                if (buf[tmp_len - 2] == '\r' || buf[tmp_len - 2] == '\n')
                    buf[tmp_len - 2] = 0;
            }
        }

#if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0 
        if (sscanf(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, option, head, code, param, multicode, read_wait_time, cmd_wait_time) == 8)
#elif _MSC_VER >= 1500 
        //if ( _stscanf_s(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, MAX_PATH, option, MAX_PATH, head, MAX_PATH, code, MAX_PATH, param, MAX_PATH, multicode, MAX_PATH, read_wait_time, MAX_PATH, cmd_wait_time, MAX_PATH) == 8) // �ȼ�����;
        if (_stscanf_s(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%s", name, MAX_PATH, option, MAX_PATH, head, MAX_PATH, code, MAX_PATH, param, MAX_PATH, multicode, MAX_PATH, read_wait_time, MAX_PATH, cmd_wait_time, MAX_PATH) == 8)
#endif
        {
            CommandParam cp;
            parse_pair_key(cp.name, name, _T("Name"));
            parse_pair_key(cp.head, head, _T("HeadCode"));
            parse_pair_key(cp.code, code, _T("Command"));
            parse_pair_key(cp.param, param, _T("CMDParam"));

            std::string value;
            parse_pair_key(value, option, _T("Option"));
            if (!_tcsicmp(value.c_str(), _T("None")))
                cp.nOption = CMDOPT_None;
            else if (!_tcsicmp(value.c_str(), _T("Get")))
                cp.nOption = CMDOPT_Get;
            else if (!_tcsicmp(value.c_str(), _T("Set")))
                cp.nOption = CMDOPT_Set;

            parse_pair_key(value, multicode, _T("MultiParams"));
            cp.bMulticode = !_tcsicmp(value.c_str(), _T("true")) ? true : false;

            parse_pair_key(value, read_wait_time, _T("ReadWaitTime"));
            cp.read_wait_time = pares_time_value(value.c_str());

            parse_pair_key(value, cmd_wait_time, _T("CMDWaitTime"));
            cp.cmd_wait_time = pares_time_value(value.c_str());
            cp.UpdateRtnCode();

            vtCommandParams.push_back(cp);
        }
    }

    ret = 0;
EXIT:
    if (fp)
        fclose(fp);
    return ret;
}

void TCLCommand::parse_cmds_from_string(std::string str, std::vector<CommandParam>& vtCommandParams)
{
    int nPos(0);
    TCHAR buf[MAX_PATH] = { 0 };
    TCHAR name[MAX_PATH] = { 0 };
    TCHAR option[MAX_PATH] = { 0 };
    TCHAR head[MAX_PATH] = { 0 };
    TCHAR code[MAX_PATH] = { 0 };
    TCHAR param[MAX_PATH] = { 0 };
    TCHAR multicode[MAX_PATH] = { 0 };
    TCHAR cmd_wait_time[MAX_PATH] = { 0 };
    TCHAR read_wait_time[MAX_PATH] = { 0 };

    do 
    {
        memset(buf, 0, MAX_PATH);
        int nPos1 = str.find_first_of('\r');
        int nPos2 = str.find_first_of('\n');
        if ( std::string::npos != nPos1 && std::string::npos != nPos2 ) {
            nPos = nPos1 > nPos2 ? nPos1 : nPos2;
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			sprintf(buf, _T("%s"), str.substr(0, nPos - 1).c_str());
#elif _MSC_VER >= 1500
            _stprintf_s(buf, _T("%s"), str.substr(0, nPos - 1).c_str());
#endif
            str = str.substr(nPos+1);
        } 
        else if ( std::string::npos != nPos1 ) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			sprintf(buf, _T("%s"), str.substr(0, nPos1 - 1).c_str());
#elif _MSC_VER >= 1500
            _stprintf_s(buf, _T("%s"), str.substr(0, nPos1 - 1).c_str());
#endif
            str = str.substr(nPos + 1);
        }
        else if ( std::string::npos != nPos2 ) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			sprintf(buf, _T("%s"), str.substr(0, nPos2 - 1).c_str());
#elif _MSC_VER >= 1500
            _stprintf_s(buf, _T("%s"), str.substr(0, nPos2 - 1).c_str());
#endif
            str = str.substr(nPos + 1);
        }
        else {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			sprintf(buf, _T("%s"), str.c_str());
#elif _MSC_VER >= 1500
            _stprintf_s(buf, _T("%s"), str.c_str());
#endif
            str = "";
        }

#if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0 
        if (sscanf(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, option, head, code, param, multicode, read_wait_time, cmd_wait_time) == 8)
#elif _MSC_VER >= 1500 
        //if ( _stscanf_s(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, MAX_PATH, option, MAX_PATH, head, MAX_PATH, code, MAX_PATH, param, MAX_PATH, multicode, MAX_PATH, read_wait_time, MAX_PATH, cmd_wait_time, MAX_PATH) == 8) // �ȼ�����;
        if (_stscanf_s(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%s", name, MAX_PATH, option, MAX_PATH, head, MAX_PATH, code, MAX_PATH, param, MAX_PATH, multicode, MAX_PATH, read_wait_time, MAX_PATH, cmd_wait_time, MAX_PATH) == 8)
#endif
        {
            CommandParam cp;
            parse_pair_key(cp.name, name, _T("Name"));
            parse_pair_key(cp.head, head, _T("HeadCode"));
            parse_pair_key(cp.code, code, _T("Command"));
            parse_pair_key(cp.param, param, _T("CMDParam"));

            std::string value;
            parse_pair_key(value, option, _T("Option"));
            if (!_tcsicmp(value.c_str(), _T("None")))
                cp.nOption = CMDOPT_None;
            else if (!_tcsicmp(value.c_str(), _T("Get")))
                cp.nOption = CMDOPT_Get;
            else if (!_tcsicmp(value.c_str(), _T("Set")))
                cp.nOption = CMDOPT_Set;

            parse_pair_key(value, multicode, _T("MultiParams"));
            cp.bMulticode = !_tcsicmp(value.c_str(), _T("true")) ? true : false;

            parse_pair_key(value, read_wait_time, _T("ReadWaitTime"));
            cp.read_wait_time = pares_time_value(value.c_str());

            parse_pair_key(value, cmd_wait_time, _T("CMDWaitTime"));
            cp.cmd_wait_time = pares_time_value(value.c_str());
            cp.UpdateRtnCode();

            vtCommandParams.push_back(cp);
        }
    } while (str.size());
}

bool TCLCommand::GetCommandParams(std::string name, CommandParam& cmdPara)
{
    bool bget = false;
    // �ⲿ����;
    for (std::vector<CommandParam>::iterator it = m_vtExternalCMDParams.begin(); it != m_vtExternalCMDParams.end(); it++ )
    {
        if ( !_tcsicmp(name.c_str(), it->name.c_str()) ) {
            bget = true;
            cmdPara = *it;
            break;
        }
    }
    
    if ( !bget )
    {
        for (std::vector<CommandParam>::iterator it = m_vtInternalCMDParams.begin(); it != m_vtInternalCMDParams.end(); it++ )
        {
            if ( !_tcsicmp(name.c_str(), it->name.c_str()) ) {
                bget = true;
                cmdPara = *it;
                break;
            }
        }
    }

    // ���״̬;
    cmdPara.Clean();

    return bget;
}

bool TCLCommand::TheFirstPart(CommandParam& cmdPara, std::string data)
{
    if (data.size() == NoneOptLen) {
        if ((byte)data[0] == cmdPara._rtnCode) {
            // ����;
            int nPacketLen = (byte)data[1];
            if (nPacketLen != NoneOptLen) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
				cmdPara._rtnError = utils::_dprintf("[%s] �������ݳ��ȴ���%ld", (byte)data[1]);
#elif _MSC_VER >= 1500
                cmdPara._rtnError = utils::_dprintf("[%s] �������ݳ��ȴ���%ld", __FUNCTION__, (byte)data[1]);
#endif
                return false;
            }

            // ִ��״̬;
            cmdPara._rtnStatus = (byte)data[2];
            //utils::_dprintf(_T("[%s] rtnStatus=%02X"), __FUNCTION__, cmdPara._rtnStatus);

            // ��crc;
            unsigned short usCRCValue = utils::CRC16Calculate((byte*)data.data(), nPacketLen - 2);
            if (((usCRCValue >> 8) & 0xFF) != (byte)data[nPacketLen - 2] || (usCRCValue & 0xFF) != (byte)data[nPacketLen - 1]) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
				cmdPara._rtnError = utils::_dprintf("CRCУ����󣺼���[%02% %02X] != ����[%02X %02X]", (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
#elif _MSC_VER >= 1500
                cmdPara._rtnError = utils::_dprintf("[%s] CRCУ����󣺼���[%02% %02X] != ����[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
#endif
				return false;
            }
        }
        else {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			cmdPara._rtnError = utils::_dprintf("���������%02X", (byte)data[0]);
#elif _MSC_VER >= 1500
            cmdPara._rtnError = utils::_dprintf("[%s] ���������%02X", __FUNCTION__, (byte)data[0]);
#endif
            return false;
        }
    }
    else {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
		cmdPara._rtnError = utils::_dprintf("�������ݳ��ȴ���", (byte)data[0]);
#elif _MSC_VER >= 1500
        cmdPara._rtnError = utils::_dprintf("[%s] �������ݳ��ȴ���", __FUNCTION__);
#endif
        return false;
    }

    return true;
}

bool TCLCommand::TheSecondPart(CommandParam& cmdPara, std::string data)
{
    // ������ʼλ;
    int nDataPos = 0;
    // ���ݰ�����;
    int nPacketLen = 0;
    if ((byte)data[0] == cmdPara._rtnCode) {
        // ��ȡ����;
        if ((byte)data[1] == 0xFE) {
            nDataPos = 4;
            nPacketLen = (byte)data[2] << 8 | (byte)data[3];
            if (data.size() < 255 && data[2] != 0) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
				cmdPara._rtnError = utils::_dprintf(_T("�������ݳ����쳣"));
#elif _MSC_VER >= 1500
                cmdPara._rtnError = utils::_dprintf(_T("[%s] �������ݳ����쳣"), __FUNCTION__);
#endif
                return false;
            }
        }
        else
        {
            nDataPos = 2;
            nPacketLen = (byte)data[1];
#if 0 // ������ݰ����з�Э����ڵ�����,���ж��쳣;
            if (data.size() > 255) {
                //nPackageLen = data[1] << 8 | data[2];
                cmdPara._rtnError = _dprintf(_T("�����쳣"));
                return false;
            }
#endif
        }

#if 0
        // ������ij���,�ص��ڰ���;// ��������������ǰ�����,���ж��쳣;
        if (nPackageLen != data.size())
            return false;
#endif

        if (_tcsicmp(cmdPara.code.c_str(), utils::ByteToChars((byte)data[nDataPos] - 1).c_str()) != 0) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			cmdPara._rtnError = utils::_dprintf(_T("���ص�ָ�����, %s, %02X"), cmdPara.head.c_str(), (byte)data[nDataPos]);
#elif _MSC_VER >= 1500
            cmdPara._rtnError = utils::_dprintf(_T("[%s] ���ص�ָ�����, %s, %02X"), __FUNCTION__, cmdPara.head.c_str(), (byte)data[nDataPos]);
#endif
            return false;
        }

        // ���ص�����;
        ++nDataPos;// ������ռһ�ֽ�;
        if (cmdPara.bMulticode) {
            if (_tcsicmp(cmdPara.param.c_str(), utils::ByteToChars((byte)data[nDataPos]).c_str()) != 0) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
				cmdPara._rtnError = utils::_dprintf(_T("���ص�ָ���������, %s, %02X"), cmdPara.param.c_str(), (byte)data[nDataPos]);
#elif _MSC_VER >= 1500
                cmdPara._rtnError = utils::_dprintf(_T("[%s] ���ص�ָ���������, %s, %02X"), __FUNCTION__, cmdPara.param.c_str(), (byte)data[nDataPos]);
#endif
				return false;
            }

            ++nDataPos;// ָ�������ռһ�ֽ�;
        }

        cmdPara._rtnData = data.substr(nDataPos, nPacketLen - nDataPos - 2); //2 = crc;
        utils::_dprintf(_T("rtnData=%s"), utils::BytesToHexString((byte*)cmdPara._rtnData.c_str(), cmdPara._rtnData.size(), ' ').c_str());

        // ��crc;
        unsigned short usCRCValue = utils::CRC16Calculate((byte*)data.data(), nPacketLen - 2);
        if (((usCRCValue >> 8) & 0xFF) != (byte)data[nPacketLen - 2] || (usCRCValue & 0xFF) != (byte)data[nPacketLen - 1])
        {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			cmdPara._rtnError = utils::_dprintf("CRCУ����󣺼���[%02X %02X] != ����[%02X %02X]", (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
#elif _MSC_VER >= 1500
            cmdPara._rtnError = utils::_dprintf("[%s] CRCУ����󣺼���[%02X %02X] != ����[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
#endif
			return false;
        }

        if (data.size() > nPacketLen)
#if _MSC_VER >= 1200 && _MSC_VER < 1500
			utils::_dprintf(_T("���������ݣ�%s"), data.substr(nPacketLen));
#elif _MSC_VER >= 1500
            utils::_dprintf("[%s] ���������ݣ�%s", __FUNCTION__, data.substr(nPacketLen));
#endif
    }
    else {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
        cmdPara._rtnError = utils::_dprintf("���������%02X", (byte)data[0]);
#elif _MSC_VER >= 1500
		cmdPara._rtnError = utils::_dprintf("[%s] ���������%02X", __FUNCTION__, (byte)data[0]);
#endif
        return false;
    }

    return true;
}

void TCLCommand::PackingCommand(CommandParam& cmdPara, std::string data, const int& dataLen)
{
    // Tag:[����ͷ][ȫ�����][������]<���������><��������>[crc1][crc2]
    std::string command;
    // ����ͷ��ʶλ;
    command.append(utils::HexStringToBytes(cmdPara.head, 2).c_str(), cmdPara.head.size() / 2);
    // ������;
    command.append(utils::HexStringToBytes(cmdPara.code, 2).c_str(), cmdPara.code.size() / 2);
    // ���������;
    command.append(utils::HexStringToBytes(cmdPara.param, 2).c_str(), cmdPara.param.size() / 2);
    // ���ӵ�����;
    if (dataLen > 0)
        command.append(data.c_str(), dataLen);

    int len(0);
    // ���ȣ�����1�ֽڱ�ʾ������255��2�ֽڱ�ʾ;
    byte szlen[2] = { 0 };
    //if ((byte)command[1] == 0xFE)
    //if ( cmdPara.head.size() >= 4 && cmdPara.head.find("FE", 2, 2) != std::string::npos )
    if (_tcsicmp(_T("AAFE"), cmdPara.head.c_str()) == 0)
    {// ���ȳ���255,��Ҫ2�ֽڱ�ʾ;
        len = command.size() + 4;    // 2λcrc + 2λ����;
        szlen[0] = (len >> 8) & 0xFF;
        szlen[1] = len & 0xFF;
        command.insert(2, (char*)szlen, 2);
    }
    else {
        // 2λcrc + 1λ����;
        len = command.size() + 3;
        //if ( _tcsicmp(cmdPara.code.c_str(), "99 00") == 0 )
        //    len -= 2;

        if (len > 255) {// ���ȳ���255����һ��ռλ��;
            ++len;
            szlen[0] = (len >> 8) & 0xFF;
            szlen[1] = len & 0xFF;
            command.insert(1, (char*)szlen, 2);
        }
        else {
            szlen[0] = len & 0xFF;
            command.insert(1, (char*)szlen, 1);
        }
    }

    // crc��;
    byte szcrc[2] = { 0 };
    WORD usCRCValue = utils::CRC16Calculate((byte*)command.c_str(), command.size()); // �����0�Ͽ���Σ��;
    //WORD usCRCValue = CRC16Calculate((byte *)command.c_str(), len - 2);
    szcrc[0] = (usCRCValue >> 8) & 0xFF;
    szcrc[1] = usCRCValue & 0xFF;
    command.append((char*)szcrc, 2);

    cmdPara._cmdContext = command;
    utils::_dprintf(_T("ָ�%s = %s"), cmdPara.name.c_str(), utils::BytesToHexString((byte*)command.c_str(), command.size(), ' ').c_str());
}

bool TCLCommand::ParseResultString(CommandParam& cmdPara, std::string data, const int& dataLen)
{
    // Tag:[����ͷ][ȫ���ݳ���][������]<����������><��������>[crc16]
    if (!TheFirstPart(cmdPara, data.substr(0, 5)))
        return false;

    if (cmdPara._rtnStatus != 0x0A) {
#if _MSC_VER >= 1200 && _MSC_VER < 1500
        utils::_dprintf("ִ�н������%02X", cmdPara._rtnStatus);
#elif _MSC_VER >= 1500
        utils::_dprintf("[%s] ִ�н������%02X", __FUNCTION__, cmdPara._rtnStatus);
#endif
        return false;
    }

    switch (cmdPara.nOption)
    {
    case CMDOPT_None:
        break;
    case CMDOPT_Get:
    case CMDOPT_Set:
        return TheSecondPart(cmdPara, data.substr(5));
        break;
    default:
        break;
    }

    return false;
}

bool TCLCommand::SendCommand(CommandParam& cmdPara)
{
    memset(m_pData, 0, MAXSIZE);
    if (_dwIOMode == FILE_FLAG_OVERLAPPED)
    {
        if (!Write((void*)cmdPara._cmdContext.c_str(), cmdPara._cmdContext.size()))
            return false;

        Sleep(cmdPara.read_wait_time);     
		int nReadCount = Read(m_pData, MAXSIZE);
		cmdPara._rtnContext.append((char*)m_pData, nReadCount);
    }
    else 
    {
        if (!WriteSync((void*)cmdPara._cmdContext.c_str(), cmdPara._cmdContext.size()))
            return false;

        Sleep(cmdPara.read_wait_time);
        int nReadCount = ReadSync(m_pData, MAXSIZE);
		cmdPara._rtnContext.append((char*)m_pData, nReadCount);
    }

	utils::_dprintf("�����%s = %s", cmdPara.name.c_str(), utils::BytesToHexString((byte*)cmdPara._rtnContext.c_str(), cmdPara._rtnContext.size(), ' ').c_str());
	ParseResultString(cmdPara, cmdPara._rtnContext, cmdPara._rtnContext.size());
    Sleep(cmdPara.cmd_wait_time);

    return cmdPara._rtnStatus == 0x0A ? true : false;
}

void TCLCommand::SetInternalCMDParams(DWORD dwResouceID)
{
    std::string data;
    if ( utils::GetResourceData(dwResouceID, _T("BIN"), data) )
    {
        parse_cmds_from_string(data, m_vtInternalCMDParams);
    }
}

void TCLCommand::SetExternalCMDParams(LPCTSTR lpFileName)
{
    parse_cmds_from_file(lpFileName, m_vtExternalCMDParams);
}

bool TCLCommand::EnterFactory()
{
	CommandParam cmdpara;
	GetCommandParams("EnterFactory", cmdpara);
	PackingCommand(cmdpara);
    return SendCommand(cmdpara);
}

bool TCLCommand::LeaveFactory()
{
	CommandParam cmdpara;
	GetCommandParams("LeaveFactory", cmdpara);
	PackingCommand(cmdpara);
    return SendCommand(cmdpara);
}

bool TCLCommand::GetProjectId(int& pid)
{
	CommandParam cmdpara;
	GetCommandParams("GetProjectId", cmdpara);
	PackingCommand(cmdpara);
    if (SendCommand(cmdpara))
    {
        if (cmdpara._rtnData.size() == 2)
            pid = (byte)cmdpara._rtnData[0] << 8 | (byte)cmdpara._rtnData[1];
        else
            pid = (byte)cmdpara._rtnData[0];

        return true;
    }

    return false;
}

bool TCLCommand::GetSoftVersion(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetSoftVersion", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
        strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetDeviceId(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetDeviceId", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetClientType(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetClientType", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetMAC(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetMAC", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetHDCPKey(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetHDCPKey", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetHDCPKey22(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetHDCPKey22", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetWidi(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetWidi", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetNetflixESN(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetNetflixESN", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetWidevine(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetWidevine", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetCiKey(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetCiKey", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetOSDLanguage(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetOSDLanguage", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetShopLanguage(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetShopLanguage", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}

bool TCLCommand::GetChannel(std::string& strValue)
{
	CommandParam cmdpara;
	GetCommandParams("GetChannel", cmdpara);
	PackingCommand(cmdpara);
	if (SendCommand(cmdpara))
	{
		strValue = cmdpara._rtnData;
		return true;
	}

	return false;
}


bool TCLCommand::SetProjectId(const byte* pBuffer, const int& nLen)
{
	return false;
}

bool TCLCommand::SetDeviceId(LPCTSTR lpDeviceId)
{
    return false;
}

bool TCLCommand::SetDeviceId(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetMAC(LPCTSTR lpMac)
{
    return false;
}

bool TCLCommand::SetMAC(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetHDCPKey(LPCTSTR lpHDCP, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetHDCPKey(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetHDCPKey22(LPCTSTR lpHDCP22, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetHDCPKey22(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetNetflixESN(LPCTSTR lpESN, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetNetflixESN(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetWidi(LPCTSTR lpWidi, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetWidi(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetWidevine(LPCTSTR lpWidevine, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetWidevine(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetCiKey(LPCTSTR lpCiKey, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetCiKey(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetOSDLanguage(LPCTSTR lan, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetOSDLanguage(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetShopLanguage(LPCTSTR lan, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetShopLanguage(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetChannel(LPCTSTR channel, bool bHasSpace)
{
    return false;
}

bool TCLCommand::SetChannel(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetWBNormal(LPCTSTR data)
{
    return false;
}

bool TCLCommand::SetWBNormal(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetWBCool(LPCTSTR data)
{
    return false;
}

bool TCLCommand::SetWBCool(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::SetWBWarm(LPCTSTR data)
{
    return false;
}

bool TCLCommand::SetWBWarm(const byte* pBuffer, const int& nLen)
{
    return false;
}

bool TCLCommand::CheckDeviceId()
{
    return false;
}

bool TCLCommand::CheckMAC()
{
    return false;
}

bool TCLCommand::CheckHDCP()
{
    return false;
}

bool TCLCommand::CheckHDCP22()
{
    return false;
}

bool TCLCommand::CheckNetflixESN()
{
    return false;
}

bool TCLCommand::CheckWidi()
{
    return false;
}

bool TCLCommand::CheckWidevine()
{
    return false;
}

bool TCLCommand::CheckCikey()
{
    return false;
}

bool TCLCommand::StarWarmUpMode()
{
    return false;
}

bool TCLCommand::StopWarmUpMode()
{
    return false;
}

bool TCLCommand::SetProjectId(int pid)
{
    return false;
}

bool TCLCommand::SetProjectId(LPCTSTR lpPid)
{
    return false;
}