Browse Source

内置数据

sat23 4 years ago
parent
commit
12dce92d7f

+ 17 - 5
Serail-Demo/Demo/Demo.cpp

@@ -30,13 +30,19 @@ int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 	else
 	{
 		// TODO: 在此处为应用程序的行为编写代码。
-#if 0
+#if 1
 		TCLCommand tcl(true);
+        std::string cmds;
+        std::vector<CommandParam> vtCommandParams;
+        utils::GetResourceData(BIN_CMD, "BIN", cmds);
+        if ( cmds.size() ) {
+            tcl.parse_cmds_from_string(cmds, vtCommandParams);
+        }
+
 		if (tcl.Open(21, _T("baud=115200 parity=N data=8 stop=1")) )
 		{
 			tcl.SetTimeouts();
-			std::vector<CommandParam> vtCommandParams;
-			tcl.parse_cmd_param_from_file("F:\\source\\scbc_repos\\Serail-Demo\\Demo\\command.data", vtCommandParams);
+			//tcl.parse_cmds_from_file("F:\\source\\scbc_repos\\Serail-Demo\\Demo\\command.data", vtCommandParams);
 			for ( std::vector<CommandParam>::iterator it = vtCommandParams.begin(); it != vtCommandParams.end(); it++ )
 			{
 				if ( !_tcsicmp(it->name.c_str(), _T("LeaveFactory")) )
@@ -60,11 +66,17 @@ int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 		}
 #else
 		TCLCommand tcl(false);
+		std::string cmds;
+        std::vector<CommandParam> vtCommandParams;
+		utils::GetResourceData(BIN_CMD, "BIN", cmds);
+        if ( cmds.size() ) {
+            tcl.parse_cmds_from_string(cmds, vtCommandParams);
+        }
+
 		if ( tcl.Open(21, _T("baud=115200 parity=N data=8 stop=1") ) )
 		{
 			tcl.SetTimeouts();
-			std::vector<CommandParam> vtCommandParams;
-			tcl.parse_cmd_param_from_file("F:\\source\\scbc_repos\\Serail-Demo\\Demo\\command.data", vtCommandParams);
+			//tcl.parse_cmds_from_file("F:\\source\\scbc_repos\\Serail-Demo\\Demo\\command.data", vtCommandParams);
 			for ( std::vector<CommandParam>::iterator it = vtCommandParams.begin(); it != vtCommandParams.end(); it++ )
 			{
 				if ( !_tcsicmp(it->name.c_str(), _T("LeaveFactory")) )

+ 28 - 16
Serail-Demo/Demo/Demo.rc

@@ -1,20 +1,25 @@
-//Microsoft Visual C++ 生成的资源脚本。
+// Microsoft Visual C++ generated resource script.
 //
 #include "resource.h"
 
 #define APSTUDIO_READONLY_SYMBOLS
 /////////////////////////////////////////////////////////////////////////////
 //
-// 从 TEXTINCLUDE 2 资源生成。
+// Generated from the TEXTINCLUDE 2 resource.
 //
 #include "afxres.h"
+
 /////////////////////////////////////////////////////////////////////////////
 #undef APSTUDIO_READONLY_SYMBOLS
 
+/////////////////////////////////////////////////////////////////////////////
+// 中文(中华人民共和国) resources
+
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
-LANGUAGE 4, 2
+#ifdef _WIN32
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
 #pragma code_page(936)
-
+#endif //_WIN32
 
 #ifdef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
@@ -22,18 +27,18 @@ LANGUAGE 4, 2
 // TEXTINCLUDE
 //
 
-1 TEXTINCLUDE
+1 TEXTINCLUDE 
 BEGIN
     "resource.h\0"
 END
 
-2 TEXTINCLUDE
+2 TEXTINCLUDE 
 BEGIN
     "#include ""afxres.h""\r\n"
     "\0"
 END
 
-3 TEXTINCLUDE
+3 TEXTINCLUDE 
 BEGIN
     "\r\n"
     "\0"
@@ -41,17 +46,25 @@ END
 
 #endif    // APSTUDIO_INVOKED
 
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// BIN
+//
+
+BIN_CMD                 BIN                     "command.data"
+
 /////////////////////////////////////////////////////////////////////////////
 //
-// 字符串表
+// String Table
 //
 
-STRINGTABLE
+STRINGTABLE 
 BEGIN
-   IDS_APP_TITLE       "Demo"
+    IDS_APP_TITLE           "Demo"
 END
 
-#endif
+#endif    // 中文(中华人民共和国) resources
 /////////////////////////////////////////////////////////////////////////////
 
 
@@ -59,11 +72,10 @@ END
 #ifndef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
 //
-// 从 TEXTINCLUDE 3 资源生成。
+// Generated from the TEXTINCLUDE 3 resource.
 //
-#ifndef _AFXDLL
-#include "l.CHS\\afxres.rc"
-#endif
+
 
 /////////////////////////////////////////////////////////////////////////////
-#endif    // 不是 APSTUDIO_INVOKED
+#endif    // not APSTUDIO_INVOKED
+

+ 4 - 0
Serail-Demo/Demo/Demo.vcproj

@@ -253,6 +253,10 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath=".\command.data"
+			>
+		</File>
 		<File
 			RelativePath=".\ReadMe.txt"
 			>

+ 9 - 8
Serail-Demo/Demo/Resource.h

@@ -2,16 +2,17 @@
 // Microsoft Visual C++ generated include file.
 // Used by Demo.rc
 //
+#define IDR_BIN1                        101
+#define BIN_CMD                         101
+#define IDS_APP_TITLE                   103
 
-#define IDS_APP_TITLE			103
-
-// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
-//
+// Next default values for new objects
+// 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE	101
-#define _APS_NEXT_COMMAND_VALUE		40001
-#define _APS_NEXT_CONTROL_VALUE		1000
-#define _APS_NEXT_SYMED_VALUE		101
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

+ 275 - 275
Serail-Demo/Demo/Serial.cpp

@@ -4,417 +4,417 @@
 
 DCB *CBaseSerial::GetState()
 {
-	return IsOpen() && ::GetCommState(_hCommHandle, &_DCB) == TRUE ? &_DCB : NULL;
+    return IsOpen() && ::GetCommState(_hCommHandle, &_DCB) == TRUE ? &_DCB : NULL;
 }
 
 bool CBaseSerial::SetState(DCB *pdcb /*= NULL*/)
 {
-	return IsOpen() ? ::SetCommState(_hCommHandle, pdcb == NULL ? &_DCB : pdcb) == TRUE : false;
+    return IsOpen() ? ::SetCommState(_hCommHandle, pdcb == NULL ? &_DCB : pdcb) == TRUE : false;
 }
 
 bool CBaseSerial::SetState(TCHAR *lpszSetStr /* = _T("baud=115200 parity=N data=8 stop=1") */)
 {
-	if (lpszSetStr && lpszSetStr[0] != '\0' && IsOpen())
-	{
-		if (::GetCommState(_hCommHandle, &_DCB) != TRUE)
-			return false;
-		// COMx[:][baud=b][parity=p][data=d][stop=s][to={on|off}][xon={on|off}][odsr={on|off}][octs={on|off}][dtr={on|off|hs}][rts={on|off|hs|tg}][idsr={on|off}]
-		if (::BuildCommDCB(lpszSetStr, &_DCB) != TRUE)
-			return false;
-		return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
-	}
-
-	return false;
+    if (lpszSetStr && lpszSetStr[0] != '\0' && IsOpen())
+    {
+        if (::GetCommState(_hCommHandle, &_DCB) != TRUE)
+            return false;
+        // COMx[:][baud=b][parity=p][data=d][stop=s][to={on|off}][xon={on|off}][odsr={on|off}][octs={on|off}][dtr={on|off|hs}][rts={on|off|hs|tg}][idsr={on|off}]
+        if (::BuildCommDCB(lpszSetStr, &_DCB) != TRUE)
+            return false;
+        return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
+    }
+
+    return false;
 }
 
 bool CBaseSerial::SetState(DWORD dwBaudRate, DWORD dwByteSize /* = 8 */, DWORD dwParity /* = NOPARITY */, DWORD dwStopBits /* = ONESTOPBIT */)
 {
-	if (!IsOpen()) return false;
+    if (!IsOpen()) return false;
 
-	if (::GetCommState(_hCommHandle, &_DCB) != TRUE)
-		return false;
+    if (::GetCommState(_hCommHandle, &_DCB) != TRUE)
+        return false;
 
-	_DCB.BaudRate = dwBaudRate;
-	_DCB.ByteSize = (BYTE)dwByteSize;
-	_DCB.Parity = (BYTE)dwParity;
-	_DCB.StopBits = (BYTE)dwStopBits;
-	return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
+    _DCB.BaudRate = dwBaudRate;
+    _DCB.ByteSize = (BYTE)dwByteSize;
+    _DCB.Parity = (BYTE)dwParity;
+    _DCB.StopBits = (BYTE)dwStopBits;
+    return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
 }
 
 LPCOMMTIMEOUTS CBaseSerial::GetTimeouts()
 {
-	return IsOpen() && ::GetCommTimeouts(_hCommHandle, &_CO) == TRUE ? &_CO : NULL;
+    return IsOpen() && ::GetCommTimeouts(_hCommHandle, &_CO) == TRUE ? &_CO : NULL;
 }
 
 bool CBaseSerial::SetTimeouts(DWORD ReadIntervalTimeout /* = 0 */, DWORD ReadTotalTimeoutMultiplier /* = 10 */, DWORD ReadTotalTimeoutConstant /* = 1500 */, DWORD WriteTotalTimeoutMultiplier /* = 10 */, DWORD WriteTotalTimeoutConstant /* = 1500 */)
 {
-	COMMTIMEOUTS CO = {
-		ReadIntervalTimeout, 
-		ReadTotalTimeoutMultiplier, 
-		ReadTotalTimeoutConstant, 
-		WriteTotalTimeoutMultiplier, 
-		WriteTotalTimeoutConstant
-	};
-	return IsOpen() ? ::SetCommTimeouts(_hCommHandle, &CO) == TRUE : false;
+    COMMTIMEOUTS CO = {
+        ReadIntervalTimeout, 
+        ReadTotalTimeoutMultiplier, 
+        ReadTotalTimeoutConstant, 
+        WriteTotalTimeoutMultiplier, 
+        WriteTotalTimeoutConstant
+    };
+    return IsOpen() ? ::SetCommTimeouts(_hCommHandle, &CO) == TRUE : false;
 }
 
 bool CBaseSerial::SetTimeouts(LPCOMMTIMEOUTS lpCO)
 {
-	return IsOpen() ? ::SetCommTimeouts(_hCommHandle, lpCO) == TRUE : false;
+    return IsOpen() ? ::SetCommTimeouts(_hCommHandle, lpCO) == TRUE : false;
 }
 
 bool CBaseSerial::SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)
 {
-	// SetupComm设置输入输出缓冲区大小;
-	return IsOpen() ? ::SetupComm(_hCommHandle, dwInputSize, dwOutputSize) == TRUE : false;
+    // SetupComm设置输入输出缓冲区大小;
+    return IsOpen() ? ::SetupComm(_hCommHandle, dwInputSize, dwOutputSize) == TRUE : false;
 }
 
 void CBaseSerial::SetMaskEvent(DWORD dwEvent /* = DEFAULT_COM_MASK_EVENT */)
 {
-	_dwMaskEvent = dwEvent;
+    _dwMaskEvent = dwEvent;
 }
 
 int CBaseSerial::GetInputSize()
 {
-	COMSTAT Stat;
-	DWORD dwError;
-	return ::ClearCommError(_hCommHandle, &dwError, &Stat) == TRUE ? Stat.cbInQue : (DWORD)-1L;
+    COMSTAT Stat;
+    DWORD dwError;
+    return ::ClearCommError(_hCommHandle, &dwError, &Stat) == TRUE ? Stat.cbInQue : (DWORD)-1L;
 }
 
 bool CBaseSerial::Open(DWORD dwPort)
 {
-	return Open(dwPort, 19200);
+    return Open(dwPort, 19200);
 }
 
 bool CBaseSerial::Open(DWORD dwPort, DWORD dwBaudRate)
 {
-	if (dwPort < 1 || dwPort > 1024)
-		return false;
+    if (dwPort < 1 || dwPort > 1024)
+        return false;
 
-	BindCommPort(dwPort);
-	if (!OpenCommPort())
-		return false;
-	if (!SetupPort())
-		return false;
+    BindCommPort(dwPort);
+    if (!OpenCommPort())
+        return false;
+    if (!SetupPort())
+        return false;
 
-	return SetState(dwBaudRate);
+    return SetState(dwBaudRate);
 }
 
 bool CBaseSerial::Open(DWORD dwPort, TCHAR *lpszSetStr /* = _T("baud/* =115200 parity/* =N data/* =8 stop/* =1") */ )
 {
-	if (dwPort < 1 || dwPort > 1024)
-		return false;
+    if (dwPort < 1 || dwPort > 1024)
+        return false;
 
-	BindCommPort(dwPort);
-	if (!OpenCommPort())
-		return false;
-	if (!SetupPort())
-		return false;
+    BindCommPort(dwPort);
+    if (!OpenCommPort())
+        return false;
+    if (!SetupPort())
+        return false;
 
-	return SetState(lpszSetStr);
+    return SetState(lpszSetStr);
 }
 
 DWORD CBaseSerial::Read(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime /* = 100 */)
 {
-	if (!IsOpen())
-		return 0;
+    if (!IsOpen())
+        return 0;
 
-	COMSTAT Stat;
-	DWORD dwError;
-	if (::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0) {
-		::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);	// 清空输入缓冲区(PURGE_RXCLEAR)
-		return 0;
-	}
+    COMSTAT Stat;
+    DWORD dwError;
+    if (::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0) {
+        ::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);    // 清空输入缓冲区(PURGE_RXCLEAR)
+        return 0;
+    }
 
 #if 0 
-	// 暂时保留:要视机器情况而定,有些响应慢缓冲区会暂时性无数据;
-	if (!Stat.cbInQue)
-		return 0; // 缓冲区无数据
+    // 暂时保留:要视机器情况而定,有些响应慢缓冲区会暂时性无数据;
+    if (!Stat.cbInQue)
+        return 0; // 缓冲区无数据
 #endif
-	utils::_dprintf("缓冲区数据量:%ld", Stat.cbInQue);
-
-	unsigned long uReadLength = 0;
-	// dwBufferLength = dwBufferLength > Stat.cbInQue ? Stat.cbInQue : dwBufferLength;//会越界;
-	if (!::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, &_ReadOverlapped))  { // 可能Buffer不够大,装不完;
-		WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime); // 等待异步操作完成;
-		if (::GetLastError() == ERROR_IO_PENDING) {
-			while (!::GetOverlappedResult(_hCommHandle, &_ReadOverlapped, &uReadLength, false)) {
-				dwError = ::GetLastError();
-				if ( dwError == ERROR_IO_PENDING ) {
-					Sleep(50);
-					utils::_dprintf("读等待:%ld", dwError);
-				} else if ( dwError == ERROR_SUCCESS || dwError == ERROR_IO_INCOMPLETE ) {
-					utils::_dprintf("读完成:%ld,%ld,%ld", dwError, uReadLength,_ReadOverlapped.InternalHigh);
-					// 奇葩:_ReadOverlapped并不能马上出长度,在超时后才会刷新出来(不知是否与Win平台有关);
-					if ( _ReadOverlapped.InternalHigh )
-						uReadLength = _ReadOverlapped.InternalHigh;
-					else
-						uReadLength = Stat.cbInQue;
-					break;
-				} else {
-					utils::_dprintf("读错误:%ld", dwError);
-					uReadLength = 0;
-					break;
-				}
-			}
-		}
-	}
-
-	return uReadLength;
+    utils::_dprintf("缓冲区数据量:%ld", Stat.cbInQue);
+
+    unsigned long uReadLength = 0;
+    // dwBufferLength = dwBufferLength > Stat.cbInQue ? Stat.cbInQue : dwBufferLength;//会越界;
+    if (!::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, &_ReadOverlapped))  { // 可能Buffer不够大,装不完;
+        WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime); // 等待异步操作完成;
+        if (::GetLastError() == ERROR_IO_PENDING) {
+            while (!::GetOverlappedResult(_hCommHandle, &_ReadOverlapped, &uReadLength, false)) {
+                dwError = ::GetLastError();
+                if ( dwError == ERROR_IO_PENDING ) {
+                    Sleep(50);
+                    utils::_dprintf("读等待:%ld", dwError);
+                } else if ( dwError == ERROR_SUCCESS || dwError == ERROR_IO_INCOMPLETE ) {
+                    utils::_dprintf("读完成:%ld,%ld,%ld", dwError, uReadLength,_ReadOverlapped.InternalHigh);
+                    // 奇葩:_ReadOverlapped并不能马上出长度,在超时后才会刷新出来(不知是否与Win平台有关);
+                    if ( _ReadOverlapped.InternalHigh )
+                        uReadLength = _ReadOverlapped.InternalHigh;
+                    else
+                        uReadLength = Stat.cbInQue;
+                    break;
+                } else {
+                    utils::_dprintf("读错误:%ld", dwError);
+                    uReadLength = 0;
+                    break;
+                }
+            }
+        }
+    }
+
+    return uReadLength;
 }
 
 char* CBaseSerial::ReadString(char *szBuffer, DWORD dwBufferLength, DWORD dwWaitTime /* = 20 */)
 {
-	unsigned long uReadLength = Read(szBuffer, dwBufferLength - 1, dwWaitTime);
-	szBuffer[uReadLength] = '\0';
-	return szBuffer;
+    unsigned long uReadLength = Read(szBuffer, dwBufferLength - 1, dwWaitTime);
+    szBuffer[uReadLength] = '\0';
+    return szBuffer;
 }
 
 DWORD CBaseSerial::Write(LPVOID Buffer, DWORD dwBufferLength)
 {
-	if (!IsOpen())
-		return 0;
-
-	DWORD dwError;
-	if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
-		::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);	// 清空输出缓冲区(PURGE_TXCLEAR)
-	
-	unsigned long uWriteLength = 0;
-	if (!::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, &_WriteOverlapped)) {
-		if (ERROR_IO_PENDING == GetLastError()) {
-			while (!GetOverlappedResult(_hCommHandle, &_WriteOverlapped, &uWriteLength, FALSE)) {
-				dwError = GetLastError();
-				if (ERROR_IO_PENDING == dwError) {
-					utils::_dprintf("写等待");
-					continue;
-				} else if (dwError == ERROR_SUCCESS || dwError == ERROR_IO_INCOMPLETE){
-					uWriteLength = _WriteOverlapped.InternalHigh;
-					utils::_dprintf("写完成:%ld", dwError);
-					break;
-				} else {
-					utils::_dprintf("写出错:%ld",dwError);
-					uWriteLength = 0;
-					ClearCommError(_hCommHandle, &dwError, NULL);
-					break;
-				}
-			}
-		}
-	}
-
-	return uWriteLength;
+    if (!IsOpen())
+        return 0;
+
+    DWORD dwError;
+    if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
+        ::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);    // 清空输出缓冲区(PURGE_TXCLEAR)
+    
+    unsigned long uWriteLength = 0;
+    if (!::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, &_WriteOverlapped)) {
+        if (ERROR_IO_PENDING == GetLastError()) {
+            while (!GetOverlappedResult(_hCommHandle, &_WriteOverlapped, &uWriteLength, FALSE)) {
+                dwError = GetLastError();
+                if (ERROR_IO_PENDING == dwError) {
+                    utils::_dprintf("写等待");
+                    continue;
+                } else if (dwError == ERROR_SUCCESS || dwError == ERROR_IO_INCOMPLETE){
+                    uWriteLength = _WriteOverlapped.InternalHigh;
+                    utils::_dprintf("写完成:%ld", dwError);
+                    break;
+                } else {
+                    utils::_dprintf("写出错:%ld",dwError);
+                    uWriteLength = 0;
+                    ClearCommError(_hCommHandle, &dwError, NULL);
+                    break;
+                }
+            }
+        }
+    }
+
+    return uWriteLength;
 }
 
 DWORD CBaseSerial::Write(const TCHAR *szBuffer)
 {
-	assert(szBuffer);
-	return Write((void *)szBuffer, _tclen(szBuffer));
+    assert(szBuffer);
+    return Write((void *)szBuffer, _tclen(szBuffer));
 }
 
 DWORD CBaseSerial::ReadSync(LPVOID Buffer, DWORD dwBufferLength)
 {
-	if (!IsOpen())
-		return 0;
-	
-	COMSTAT Stat;
-	DWORD dwError;
-
-	DWORD dwLastLen = 0;
-	ULONGLONG ulTick = GetTickCount();	
-	// 直到有数据为止,超时3秒;
-	while (true) {// cbInQue表示输入缓冲区的字节数; 
-		if (GetTickCount() - ulTick > 3000) {
-			utils::_dprintf("读出错: 超过3秒仍未读完");
-			break;
-		}
-
-		if ( ::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0 ) {
-			::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);	// 清空输入缓冲区(PURGE_RXCLEAR)
-			utils::_dprintf("读出错: ClearCommError出错");
-			break;
-		}
-
-		// 防止读一次没读完,再读一次;二次长度一样表示读完;
-		if (Stat.cbInQue != 0 && dwLastLen == Stat.cbInQue)
-			break;
-		dwLastLen = Stat.cbInQue;
-		Sleep(100);
-	}
-
-	if (Stat.cbInQue == 0) {
-		// 串口超时,无数据返回;
-		return 0;
-	}
-
-	if (dwBufferLength < Stat.cbInQue) {
-		utils::_dprintf("读出错: 缓冲数据过大 %ld > %ld", dwBufferLength, Stat.cbInQue);
-	}
-
-	DWORD uReadLength = 0;
-	if ( !::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL) )
-	{
-		DWORD dwError = GetLastError();
-		utils::_dprintf("读出错:%ld", dwError);
-	}
-
-	return uReadLength;
+    if (!IsOpen())
+        return 0;
+    
+    COMSTAT Stat;
+    DWORD dwError;
+
+    DWORD dwLastLen = 0;
+    ULONGLONG ulTick = GetTickCount();    
+    // 直到有数据为止,超时3秒;
+    while (true) {// cbInQue表示输入缓冲区的字节数; 
+        if (GetTickCount() - ulTick > 3000) {
+            utils::_dprintf("读出错: 超过3秒仍未读完");
+            break;
+        }
+
+        if ( ::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0 ) {
+            ::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);    // 清空输入缓冲区(PURGE_RXCLEAR)
+            utils::_dprintf("读出错: ClearCommError出错");
+            break;
+        }
+
+        // 防止读一次没读完,再读一次;二次长度一样表示读完;
+        if (Stat.cbInQue != 0 && dwLastLen == Stat.cbInQue)
+            break;
+        dwLastLen = Stat.cbInQue;
+        Sleep(100);
+    }
+
+    if (Stat.cbInQue == 0) {
+        // 串口超时,无数据返回;
+        return 0;
+    }
+
+    if (dwBufferLength < Stat.cbInQue) {
+        utils::_dprintf("读出错: 缓冲数据过大 %ld > %ld", dwBufferLength, Stat.cbInQue);
+    }
+
+    DWORD uReadLength = 0;
+    if ( !::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL) )
+    {
+        DWORD dwError = GetLastError();
+        utils::_dprintf("读出错:%ld", dwError);
+    }
+
+    return uReadLength;
 }
 
 DWORD CBaseSerial::WriteSync(LPVOID Buffer, DWORD dwBufferLength)
 {
-	if (!IsOpen())
-		return 0;
-	
-	DWORD dwError;
-	if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
-		::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);	// 清空输出缓冲区(PURGE_TXCLEAR)
-	
-	unsigned long uWriteLength = 0;
-	if ( !::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL) )
-	{
-		DWORD dwError = GetLastError();
-		utils::_dprintf("写出错:%ld", dwError);
-	}
-
-	return uWriteLength;
+    if (!IsOpen())
+        return 0;
+    
+    DWORD dwError;
+    if (::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
+        ::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);    // 清空输出缓冲区(PURGE_TXCLEAR)
+    
+    unsigned long uWriteLength = 0;
+    if ( !::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL) )
+    {
+        DWORD dwError = GetLastError();
+        utils::_dprintf("写出错:%ld", dwError);
+    }
+
+    return uWriteLength;
 }
 
 DWORD CBaseSerial::Write(TCHAR *szBuffer, DWORD dwBufferLength, TCHAR *szFormat, ...)
 {
-	if (!IsOpen())
-		return 0;
-	
-	va_list va;
-	va_start(va, szFormat);
+    if (!IsOpen())
+        return 0;
+    
+    va_list va;
+    va_start(va, szFormat);
 #if _MSC_VER < 1500
-	_vsnprintf(szBuffer, dwBufferLength, szFormat, va);
+    _vsnprintf(szBuffer, dwBufferLength, szFormat, va);
 #elif _MSC_VER >=1500 // VC9.0以上版本;
-	//_vsntprintf(szBuffer, dwBufferLength, szFormat, va);
-	_vsntprintf_s(szBuffer, dwBufferLength, _TRUNCATE, szFormat, va);
+    //_vsntprintf(szBuffer, dwBufferLength, szFormat, va);
+    _vsntprintf_s(szBuffer, dwBufferLength, _TRUNCATE, szFormat, va);
 #endif
-	va_end(va);
+    va_end(va);
 
-	return Write(szBuffer);
+    return Write(szBuffer);
 }
 
 DWORD CBaseSerial::Write(TCHAR *szBuffer, TCHAR *szFormat, ...)
 {
-	if (!IsOpen()) 
-		return 0;
-	
-	va_list va;
-	va_start(va, szFormat);
+    if (!IsOpen()) 
+        return 0;
+    
+    va_list va;
+    va_start(va, szFormat);
 #if _MSC_VER < 1500       
-	vsprintf(szBuffer, szFormat, va);
+    vsprintf(szBuffer, szFormat, va);
 #elif _MSC_VER >=1500 // VC9.0以上版本;    
-	_vstprintf(szBuffer, szFormat, va);
+    _vstprintf(szBuffer, szFormat, va);
 #endif
-	va_end(va);
+    va_end(va);
 
-	return Write(szBuffer);
+    return Write(szBuffer);
 }
 
 void CBaseSerial::Close()
 {
-	if (!IsOpen()) return;
+    if (!IsOpen()) return;
 
-	PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);	// 清空输出缓冲区(PURGE_TXCLEAR)
-	::CloseHandle(_hCommHandle);
-	_hCommHandle = INVALID_HANDLE_VALUE;
+    PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);    // 清空输出缓冲区(PURGE_TXCLEAR)
+    ::CloseHandle(_hCommHandle);
+    _hCommHandle = INVALID_HANDLE_VALUE;
 }
 
 bool CBaseSerial::SetDTR(bool OnOrOff)
 {
-	return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR : CLRDTR) : false;
+    return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR : CLRDTR) : false;
 }
 
 bool CBaseSerial::SetRTS(bool OnOrOff)
 {
-	return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS : CLRRTS) : false;
+    return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS : CLRRTS) : false;
 }
 
 bool CBaseSerial::SetBreak(bool OnOrOff)
 {
-	return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) : false;
+    return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) : false;
 }
 
 void CBaseSerial::Init()
 {
-	memset(_szCommStr, 0, 20*sizeof(TCHAR));
-	memset(&_DCB, 0, sizeof(_DCB));
-	_DCB.DCBlength = sizeof(_DCB);
-	_hCommHandle = INVALID_HANDLE_VALUE;
-
-	memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped));
-	memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped));
-	_ReadOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
-	assert(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE);
-	_WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
-	assert(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);
-
-	_hNotifyWnd = NULL;
-	_dwNotifyNum = 0;
-	_dwMaskEvent = DEFAULT_COM_MASK_EVENT;
-
-	memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
-	_WaitOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
-	assert(_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE);
+    memset(_szCommStr, 0, 20*sizeof(TCHAR));
+    memset(&_DCB, 0, sizeof(_DCB));
+    _DCB.DCBlength = sizeof(_DCB);
+    _hCommHandle = INVALID_HANDLE_VALUE;
+
+    memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped));
+    memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped));
+    _ReadOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
+    assert(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE);
+    _WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
+    assert(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);
+
+    _hNotifyWnd = NULL;
+    _dwNotifyNum = 0;
+    _dwMaskEvent = DEFAULT_COM_MASK_EVENT;
+
+    memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
+    _WaitOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
+    assert(_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE);
 }
 
 void CBaseSerial::UnInit()
 {
-	if (_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
-		CloseHandle(_ReadOverlapped.hEvent);
-	if (_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
-		CloseHandle(_WriteOverlapped.hEvent);
-	if (_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)
-		CloseHandle(_WaitOverlapped.hEvent);
+    if (_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
+        CloseHandle(_ReadOverlapped.hEvent);
+    if (_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
+        CloseHandle(_WriteOverlapped.hEvent);
+    if (_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)
+        CloseHandle(_WaitOverlapped.hEvent);
 }
 
 void CBaseSerial::BindCommPort(DWORD dwPort)
 {
-	assert(dwPort >= 1 && dwPort <= 1024);
-	TCHAR p[5] = {0};
-	_dwPort = dwPort;
+    assert(dwPort >= 1 && dwPort <= 1024);
+    TCHAR p[5] = {0};
+    _dwPort = dwPort;
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-	strcpy(_szCommStr, _T("\\\\.\\COM"));
-	ltoa(_dwPort, p, 10);
-	strcat(_szCommStr, p);
+    strcpy(_szCommStr, _T("\\\\.\\COM"));
+    ltoa(_dwPort, p, 10);
+    strcat(_szCommStr, p);
 #elif _MSC_VER >= 1500
-	_tcscpy_s(_szCommStr, _T("\\\\.\\COM"));
-	_ltot_s(_dwPort, p, 10);
-	_tcscat_s(_szCommStr, p);
+    _tcscpy_s(_szCommStr, _T("\\\\.\\COM"));
+    _ltot_s(_dwPort, p, 10);
+    _tcscat_s(_szCommStr, p);
 #endif
 }
 
 bool CBaseSerial::OpenCommPort()
 {
-	if (IsOpen())
-		Close();
-	_hCommHandle = ::CreateFile(_szCommStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | _dwIOMode, NULL);
-	return IsOpen();
+    if (IsOpen())
+        Close();
+    _hCommHandle = ::CreateFile(_szCommStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | _dwIOMode, NULL);
+    return IsOpen();
 }
 
 bool CBaseSerial::SetupPort()
 {
-	if (!IsOpen())
-		return false;
-	// SetupComm设置输入输出缓冲区大小;
-	if (!::SetupComm(_hCommHandle, 8192, 8192))
-		return false;
-	if (!::GetCommTimeouts(_hCommHandle, &_CO))
-		return false;
-
-	_CO.ReadIntervalTimeout = 0;
-	_CO.ReadTotalTimeoutMultiplier = 10;
-	_CO.ReadTotalTimeoutConstant = 1500;
-	_CO.WriteTotalTimeoutMultiplier = 10;
-	_CO.WriteTotalTimeoutConstant = 1500;
-	if (!::SetCommTimeouts(_hCommHandle, &_CO))
-		return false;
-
-	// 清空输入输出缓冲区;
-	if (!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
-		return false;
-
-	return true;
+    if (!IsOpen())
+        return false;
+    // SetupComm设置输入输出缓冲区大小;
+    if (!::SetupComm(_hCommHandle, 8192, 8192))
+        return false;
+    if (!::GetCommTimeouts(_hCommHandle, &_CO))
+        return false;
+
+    _CO.ReadIntervalTimeout = 0;
+    _CO.ReadTotalTimeoutMultiplier = 10;
+    _CO.ReadTotalTimeoutConstant = 1500;
+    _CO.WriteTotalTimeoutMultiplier = 10;
+    _CO.WriteTotalTimeoutConstant = 1500;
+    if (!::SetCommTimeouts(_hCommHandle, &_CO))
+        return false;
+
+    // 清空输入输出缓冲区;
+    if (!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
+        return false;
+
+    return true;
 }

+ 12 - 12
Serail-Demo/Demo/Serial.h

@@ -57,12 +57,12 @@ public:
     // 获得超时结构
     LPCOMMTIMEOUTS GetTimeouts(void);    
     // 设置超时
-	bool SetTimeouts(
-		DWORD ReadIntervalTimeout = 5, 
-		DWORD ReadTotalTimeoutMultiplier = 10, 
-		DWORD ReadTotalTimeoutConstant = 1500, 
-		DWORD WriteTotalTimeoutMultiplier = 10, 
-		DWORD WriteTotalTimeoutConstant = 1500);
+    bool SetTimeouts(
+        DWORD ReadIntervalTimeout = 5, 
+        DWORD ReadTotalTimeoutMultiplier = 10, 
+        DWORD ReadTotalTimeoutConstant = 1500, 
+        DWORD WriteTotalTimeoutMultiplier = 10, 
+        DWORD WriteTotalTimeoutConstant = 1500);
     bool SetTimeouts(LPCOMMTIMEOUTS lpCO);
     // 设置串口的I/O缓冲区大小
     bool SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize);
@@ -87,7 +87,7 @@ public:
     // 打开串口 缺省 baud_rate, 8, n, 1
     bool Open(DWORD dwPort, DWORD dwBaudRate);    
     // 打开串口, 使用类似"9600, 8, n, 1"的设置字符串设置串口
-	bool Open(DWORD dwPort, TCHAR *lpszSetStr = _T("baud=115200 parity=N data=8 stop=1") );
+    bool Open(DWORD dwPort, TCHAR *lpszSetStr = _T("baud=115200 parity=N data=8 stop=1") );
     
     // 读取串口 dwBufferLength个字符到 Buffer 返回实际读到的字符数 可读任意数据
     DWORD Read(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime = 100);    
@@ -113,11 +113,11 @@ public:
     bool SetRTS(bool OnOrOff);
     // 设置信号状态为中断;
     bool SetBreak(bool OnOrOff);
-	// 清除缓存;
-	void ClearCommBuffer() { 
-		ClearCommError(_hCommHandle, NULL, NULL);
-		::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); 
-	}
+    // 清除缓存;
+    void ClearCommBuffer() { 
+        ClearCommError(_hCommHandle, NULL, NULL);
+        ::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); 
+    }
 
 protected:
     volatile DWORD _dwPort;                             // 串口号

+ 392 - 297
Serail-Demo/Demo/TCLCommand.cpp

@@ -10,353 +10,448 @@ TCLCommand::TCLCommand(bool bSync):CBaseSerial(bSync ? 0 : FILE_FLAG_OVERLAPPED)
 
 TCLCommand::~TCLCommand(void)
 {
-
+    m_vtExternalCMDParams.clear();
+    m_vtInternalCMDParams.clear();
 }
 
 int TCLCommand::pares_time_value(std::string strTime)
 {
-	int nTimes = 0;
+    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());
-	}
+    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());
-	}
+    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;
+    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 };
-	// 去除空格;
+    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
+    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);
-	}
+    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))
+    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))
+    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;
+    {
+        if (_tcsstr(szText, lpszText)) {
+            RetValue = szValue;
+            return true;
+        }
+    }
+
+    return false;
 }
 
-int TCLCommand::parse_cmd_param_from_file(TCHAR* file_name, std::vector<CommandParam>& vtCommandParams)
+int TCLCommand::parse_cmds_from_file(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;
-		unsigned short keycode = 0;
-		unsigned int protocol = 0;
-		unsigned int scancode = 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;
-			}
-		}
+    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)
+        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)
+        //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;
+        {
+            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;
+    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;
+            _stprintf_s(buf, _T("%s"), str.substr(0, nPos - 1).c_str());
+            str = str.substr(nPos+1);
+        } 
+        else if ( std::string::npos != nPos1 ) {
+            _stprintf_s(buf, _T("%s"), str.substr(0, nPos1 - 1).c_str());
+            str = str.substr(nPos + 1);
+        }
+        else if ( std::string::npos != nPos2 ) {
+            _stprintf_s(buf, _T("%s"), str.substr(0, nPos2 - 1).c_str());
+            str = str.substr(nPos + 1);
+        }
+        else {
+            _stprintf_s(buf, _T("%s"), str.c_str());
+            str.clear();
+        }
+
+#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());
 }
 
-int TCLCommand::parse_cmd_from_string(std::string str, std::vector<CommandParam>& vtCommandParams)
+bool TCLCommand::GetCommandParams(std::string name, CommandParam& cmdPara)
 {
-	return 0;
+    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;
+            }
+        }
+    }
+
+    // 清除状态;
+    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) {
-				cmdPara._rtnError = utils::_dprintf("[%s] 返回数据长度错误:%ld", __FUNCTION__, (byte)data[1]);
-				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]) {
-				cmdPara._rtnError = utils::_dprintf("[%s] CRC校验错误:计算[%02% %02X] != 接收[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
-				return false;
-			}
-		}
-		else {
-			cmdPara._rtnError = utils::_dprintf("[%s] 返回码错误:%02X", __FUNCTION__, (byte)data[0]);
-			return false;
-		}
-	}
-	else {
-		cmdPara._rtnError = utils::_dprintf("[%s] 返回数据长度错误", __FUNCTION__);
-		return false;
-	}
-
-	return true;
+    if (data.size() == NoneOptLen) {
+        if ((byte)data[0] == cmdPara._rtnCode) {
+            // 长度;
+            int nPacketLen = (byte)data[1];
+            if (nPacketLen != NoneOptLen) {
+                cmdPara._rtnError = utils::_dprintf("[%s] 返回数据长度错误:%ld", __FUNCTION__, (byte)data[1]);
+                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]) {
+                cmdPara._rtnError = utils::_dprintf("[%s] CRC校验错误:计算[%02% %02X] != 接收[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
+                return false;
+            }
+        }
+        else {
+            cmdPara._rtnError = utils::_dprintf("[%s] 返回码错误:%02X", __FUNCTION__, (byte)data[0]);
+            return false;
+        }
+    }
+    else {
+        cmdPara._rtnError = utils::_dprintf("[%s] 返回数据长度错误", __FUNCTION__);
+        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) {
-				cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回数据长度异常"), __FUNCTION__);
-				return false;
-			}
-		}
-		else
-		{
-			nDataPos = 2;
-			nPacketLen = (byte)data[1];
+    // 数据起始位;
+    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) {
+                cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回数据长度异常"), __FUNCTION__);
+                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;
-			}
+            if (data.size() > 255) {
+                //nPackageLen = data[1] << 8 | data[2];
+                cmdPara._rtnError = _dprintf(_T("长度异常"));
+                return false;
+            }
 #endif
-		}
+        }
 
 #if 0
-		// 计算出的长度,必等于包长;// 如果包含有其他非包数据,会判断异常;
-		if (nPackageLen != data.size())
-			return false;
+        // 计算出的长度,必等于包长;// 如果包含有其他非包数据,会判断异常;
+        if (nPackageLen != data.size())
+            return false;
 #endif
 
-		if (_tcsicmp(cmdPara.code.c_str(), utils::ByteToChars((byte)data[nDataPos] - 1).c_str()) != 0) {
-			cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回的指令错误, %s, %02X"), __FUNCTION__, cmdPara.head.c_str(), (byte)data[nDataPos]);
-			return false;
-		}
-
-		// 返回的数据;
-		++nDataPos;// 返回码占一字节;
-		if (cmdPara.bMulticode) {
-			if (_tcsicmp(cmdPara.param.c_str(), utils::ByteToChars((byte)data[nDataPos]).c_str()) != 0) {
-				cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回的指令参数错误, %s, %02X"), __FUNCTION__, cmdPara.param.c_str(), (byte)data[nDataPos]);
-				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])
-		{
-			cmdPara._rtnError = utils::_dprintf("[%s] CRC校验错误:计算[%02X %02X] != 接收[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
-			return false;
-		}
-
-		if (data.size() > nPacketLen)
-			utils::_dprintf("[%s] 带有脏数据:%s", __FUNCTION__, data.substr(nPacketLen));
-	}
-	else {
-		cmdPara._rtnError = utils::_dprintf("[%s] 返回码错误:%02X", __FUNCTION__, (byte)data[0]);
-		return false;
-	}
-
-	return true;
+        if (_tcsicmp(cmdPara.code.c_str(), utils::ByteToChars((byte)data[nDataPos] - 1).c_str()) != 0) {
+            cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回的指令错误, %s, %02X"), __FUNCTION__, cmdPara.head.c_str(), (byte)data[nDataPos]);
+            return false;
+        }
+
+        // 返回的数据;
+        ++nDataPos;// 返回码占一字节;
+        if (cmdPara.bMulticode) {
+            if (_tcsicmp(cmdPara.param.c_str(), utils::ByteToChars((byte)data[nDataPos]).c_str()) != 0) {
+                cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回的指令参数错误, %s, %02X"), __FUNCTION__, cmdPara.param.c_str(), (byte)data[nDataPos]);
+                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])
+        {
+            cmdPara._rtnError = utils::_dprintf("[%s] CRC校验错误:计算[%02X %02X] != 接收[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
+            return false;
+        }
+
+        if (data.size() > nPacketLen)
+            utils::_dprintf("[%s] 带有脏数据:%s", __FUNCTION__, data.substr(nPacketLen));
+    }
+    else {
+        cmdPara._rtnError = utils::_dprintf("[%s] 返回码错误:%02X", __FUNCTION__, (byte)data[0]);
+        return false;
+    }
+
+    return true;
 }
 
 std::string 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 = utils::BytesToHexString((byte*)command.c_str(), command.size(), ' ');
-	utils::_dprintf(_T("指令:%s"), cmdPara._cmdContext.c_str());
-
-	return command;
+    // 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 = utils::BytesToHexString((byte*)command.c_str(), command.size(), ' ');
+    utils::_dprintf(_T("指令:%s = %s"), cmdPara.name.c_str(), cmdPara._cmdContext.c_str());
+
+    return command;
 }
 
 void TCLCommand::ParseResultString(CommandParam& cmdPara, std::string data, const int& dataLen)
 {
-	// Tag:[返回头][全数据长度][返回码]<返回码子项><附加数据>[crc16]
-	if (!TheFirstPart(cmdPara, data.substr(0, 5)))
-		return;
-
-	if (cmdPara._rtnStatus != 0x0A) {
-		utils::_dprintf("[%s] 执行结果错误:%02X", __FUNCTION__, cmdPara._rtnStatus);
-		return;
-	}
-
-	switch (cmdPara.nOption)
-	{
-	case CMDOPT_None:
-		break;
-	case CMDOPT_Get:
-	case CMDOPT_Set:
-		TheSecondPart(cmdPara, data.substr(5));
-		break;
-	default:
-		break;
-	}
+    // Tag:[返回头][全数据长度][返回码]<返回码子项><附加数据>[crc16]
+    if (!TheFirstPart(cmdPara, data.substr(0, 5)))
+        return;
+
+    if (cmdPara._rtnStatus != 0x0A) {
+        utils::_dprintf("[%s] 执行结果错误:%02X", __FUNCTION__, cmdPara._rtnStatus);
+        return;
+    }
+
+    switch (cmdPara.nOption)
+    {
+    case CMDOPT_None:
+        break;
+    case CMDOPT_Get:
+    case CMDOPT_Set:
+        TheSecondPart(cmdPara, data.substr(5));
+        break;
+    default:
+        break;
+    }
 }

+ 92 - 64
Serail-Demo/Demo/TCLCommand.h

@@ -4,87 +4,115 @@
 
 enum CMDOPT
 {
-	CMDOPT_None = 0,
-	CMDOPT_Get = 1,
-	CMDOPT_Set = 2
+    CMDOPT_None = 0,
+    CMDOPT_Get = 1,
+    CMDOPT_Set = 2
 };
 
 typedef struct __CMDPARAM__ {
-	std::string name;		// 命令描述;
-	std::string head;		// 命令头;
-	std::string code;		// 命令码;
-	std::string param;		// 命令码参数;
-	// 命令属性类型:
-	// 0=None,只返回一段数据包;
-	// 1=Get,返回一段或两段数据包(成功时返回2段,失败时返回1段);
-	// 2=Set,返回一段或两段数据包(成功时返回1段,失败时返回1段);
-	int nOption;
-	bool bMulticode;		// 命令码是否多参数;
-	int cmd_wait_time;		// 两条串口指令间隔时间;
-	int read_wait_time;		// 写完串口后,等待多久读;
-	byte _rtnCode;
-	byte _rtnStatus;
-	std::string _rtnData;
-	std::string _rtnError;
-	std::string _rtnContext;
-	std::string _cmdContext;
-	void UpdateRtnCode()
-	{
-		if (!_tcsicmp(_T("AA"), head.c_str())) { // 调试用命令代码引导码;
-			_rtnCode = 0xAB;
-		}
-		else if (!_tcsicmp(_T("AC"), head.c_str())) { // 软件配屏参数调整命令代码引导码;
-			_rtnCode = 0xAD;
-		}
-		else if (!_tcsicmp(_T("AE"), head.c_str())) { // 保留命令发送类型引导码;
-			_rtnCode = 0xAF;
-		}
-	}
+    std::string name;        // 命令描述;
+    std::string head;        // 命令头;
+    std::string code;        // 命令码;
+    std::string param;        // 命令码参数;
+    // 命令属性类型:
+    // 0=None,只返回一段数据包;
+    // 1=Get,返回一段或两段数据包(成功时返回2段,失败时返回1段);
+    // 2=Set,返回一段或两段数据包(成功时返回1段,失败时返回1段);
+    int nOption;
+    bool bMulticode;        // 命令码是否多参数;
+    int cmd_wait_time;        // 两条串口指令间隔时间;
+    int read_wait_time;        // 写完串口后,等待多久读;
+    byte _rtnCode;
+    byte _rtnStatus;
+    std::string _rtnData;
+    std::string _rtnError;
+    std::string _rtnContext;
+    std::string _cmdContext;
+    void UpdateRtnCode()
+    {
+        if (!_tcsicmp(_T("AA"), head.c_str())) { // 调试用命令代码引导码;
+            _rtnCode = 0xAB;
+        }
+        else if (!_tcsicmp(_T("AC"), head.c_str())) { // 软件配屏参数调整命令代码引导码;
+            _rtnCode = 0xAD;
+        }
+        else if (!_tcsicmp(_T("AE"), head.c_str())) { // 保留命令发送类型引导码;
+            _rtnCode = 0xAF;
+        }
+    }
 
-	void Clean()
-	{
-		//_rtnCode = 0;
-		_rtnStatus = 0;
+    __CMDPARAM__& operator=(const __CMDPARAM__& cls)
+    {
+        if (this != &cls)
+        {
+           name = cls.name;
+           head = cls.head;
+           code = cls.code;
+           param = cls.param;
+           nOption = cls.nOption;
+           bMulticode = cls.bMulticode;
+           cmd_wait_time = cls.cmd_wait_time;
+           read_wait_time = cls.read_wait_time;
+           _rtnCode = cls._rtnCode;
+           _rtnStatus = cls._rtnStatus;
+           _rtnData = cls._rtnData;
+           _rtnError = cls._rtnError;
+           _rtnContext = cls._rtnContext;
+           _cmdContext = cls._cmdContext;
+        }
+        
+        return *this;
+    }
+
+    void Clean()
+    {
+        //_rtnCode = 0;
+        _rtnStatus = 0;
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-		_rtnData = "";
-		_rtnError = "";
+        _rtnData = "";
+        _rtnError = "";
+        _rtnContext = "";
+        _cmdContext = "";
 #elif _MSC_VER >= 1500
-		_rtnData.clear();
-		_rtnError.clear();
+        _rtnData.clear();
+        _rtnError.clear();
+        _rtnContext.clear();
+        _cmdContext.clear();
 #endif
-	}
+    }
 
-	__CMDPARAM__() {
-		_rtnCode = 0;
-		_rtnStatus = 0;
-		nOption = 0;
-		bMulticode = false;
-		cmd_wait_time = 100;
-		read_wait_time = 100;
-	}
+    __CMDPARAM__() {
+        _rtnCode = 0;
+        _rtnStatus = 0;
+        nOption = 0;
+        bMulticode = false;
+        cmd_wait_time = 100;
+        read_wait_time = 100;
+    }
 } CommandParam, * pCommandParam;
 
 
 class TCLCommand :public CBaseSerial
 {
-	// 内部-低优先查找;
-	std::vector<CommandParam> m_vtInternalCMDParams;
-	// 外部-高优先查找;
-	std::vector<CommandParam> m_vtExternalCMDParams;
+    // 内部-低优先查找;
+    std::vector<CommandParam> m_vtInternalCMDParams;
+    // 外部-高优先查找;
+    std::vector<CommandParam> m_vtExternalCMDParams;
 public:
-	TCLCommand(bool bSync = true);
-	~TCLCommand(void);
+    TCLCommand(bool bSync = true);
+    ~TCLCommand(void);
 
 public:
-	int pares_time_value(std::string strTime);
-	bool parse_pair_key(std::string& RetValue, std::string strLine, TCHAR* lpszText);
-	int parse_cmd_param_from_file(TCHAR* file_name, std::vector<CommandParam>& vtCommandParams);
-	int parse_cmd_from_string(std::string str, std::vector<CommandParam>& vtCommandParams);
+    int pares_time_value(std::string strTime);
+    bool parse_pair_key(std::string& RetValue, std::string strLine, TCHAR* lpszText);
+    int parse_cmds_from_file(TCHAR* file_name, std::vector<CommandParam>& vtCommandParams);
+    void parse_cmds_from_string(std::string str, std::vector<CommandParam>& vtCommandParams);
+    bool GetCommandParams(std::string name, CommandParam& cmdPara);
 
-	bool TheFirstPart(CommandParam& cmdPara, std::string data);
-	bool TheSecondPart(CommandParam& cmdPara, std::string data);
-	std::string PackingCommand(CommandParam& cmdPara, std::string data, const int& dataLen);
-	void ParseResultString(CommandParam& cmdPara, std::string data, const int& dataLen);
+    bool TheFirstPart(CommandParam& cmdPara, std::string data);
+    bool TheSecondPart(CommandParam& cmdPara, std::string data);
+    std::string PackingCommand(CommandParam& cmdPara, std::string data, const int& dataLen);
+    void ParseResultString(CommandParam& cmdPara, std::string data, const int& dataLen);
 
 public:
 

+ 1 - 8
Serail-Demo/Demo/command.data

@@ -42,11 +42,4 @@ Name=SetWBNormal; Option=Set; HeadCode=AA; Command=4D 04 01 01; CMDParam=/; Mult
 Name=SetWBCool; Option=Set; HeadCode=AA; Command=4D 04 02 01; CMDParam=/; MultiParams=false; ReadWaitTime=100ms; CMDWaitTime=100ms
 Name=SetWBWarm; Option=Set; HeadCode=AA; Command=4D 04 03 01; CMDParam=/; MultiParams=false; ReadWaitTime=100ms; CMDWaitTime=100ms
 Name=StarWarmUpMode; Option=None; HeadCode=AA; Command=13; CMDParam=01; MultiParams=false; ReadWaitTime=100ms; CMDWaitTime=100ms
-Name=StopWarmUpMode; Option=None; HeadCode=AA; Command=13; CMDParam=00; MultiParams=false; ReadWaitTime=100ms; CMDWaitTime=100ms
-
-
-
-
-
-
-
+Name=StopWarmUpMode; Option=None; HeadCode=AA; Command=13; CMDParam=00; MultiParams=false; ReadWaitTime=100ms; CMDWaitTime=100ms

+ 174 - 129
Serail-Demo/Demo/utils.cpp

@@ -3,165 +3,210 @@
 
 namespace utils
 {
-	const unsigned short CRC16_TABLE[16] = {
-	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
-	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
-	};
+    const unsigned short CRC16_TABLE[16] = {
+    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+    0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
+    };
 
-	std::string& trim(std::string& str)
-	{
+    std::string& trim(std::string& str)
+    {
 #if _MSC_VER >= 1200 && _MSC_VER < 1600
-		for (std::string::iterator it = str.begin(); it != str.end();) {
-			!isspace(*it) ? it++ : it = it = str.erase(it);
-		}
+        for (std::string::iterator it = str.begin(); it != str.end();) {
+            !isspace(*it) ? it++ : it = it = str.erase(it);
+        }
 #elif _MSC_VER >= 1600
-		str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char x) {return std::isspace(x); }), str.end()); //C++17
+        str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char x) {return std::isspace(x); }), str.end()); //C++17
 #endif
-		return str;
-	}
+        return str;
+    }
 
-	std::string _dprintf(CHAR* pszStr, ...)
-	{
-		const int LOGLEN = 8912;
-		char szData[LOGLEN] = { 0 };
+    std::string _dprintf(CHAR* pszStr, ...)
+    {
+        const int LOGLEN = 8912;
+        char szData[LOGLEN] = { 0 };
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-		sprintf(szData, _T("[%s %s]\n\t"), _T("Db"), CTime::GetCurrentTime().Format(_T("%H:%M:%S")));
+        sprintf(szData, _T("[%s %s]\n\t"), _T("Db"), CTime::GetCurrentTime().Format(_T("%H:%M:%S")));
 #elif _MSC_VER >= 1500
-		_stprintf_s(szData, _T("[%s %s]\n\t"), _T("Db"), CTime::GetCurrentTime().Format(_T("%H:%M:%S")).GetString());
+        _stprintf_s(szData, _T("[%s %s]\n\t"), _T("Db"), CTime::GetCurrentTime().Format(_T("%H:%M:%S")).GetString());
 #endif
-		int len = strlen(szData);
-		va_list args;
-		va_start(args, pszStr);
+        int len = strlen(szData);
+        va_list args;
+        va_start(args, pszStr);
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-		_vsnprintf(szData + len, LOGLEN - len, pszStr, args);
+        _vsnprintf(szData + len, LOGLEN - len, pszStr, args);
 #elif _MSC_VER >= 1500
-		_vsntprintf_s(szData + len, LOGLEN - len, _TRUNCATE, pszStr, args);
+        _vsntprintf_s(szData + len, LOGLEN - len, _TRUNCATE, pszStr, args);
 #endif
-		va_end(args);
-		if (szData[strlen(szData) - 1] != '\n')
+        va_end(args);
+        if (szData[strlen(szData) - 1] != '\n')
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-			strcat(szData, "\n");
+            strcat(szData, "\n");
 #elif _MSC_VER >= 1500
-			strcat_s(szData, "\n");
+            strcat_s(szData, "\n");
 #endif
-		OutputDebugStringA(szData);
+        OutputDebugStringA(szData);
 
-		return std::string(szData);
-	}
+        return std::string(szData);
+    }
 
-	std::string ByteToChars(byte b)
-	{
-		char szhex[3] = { 0 };
+    std::string ByteToChars(byte b)
+    {
+        char szhex[3] = { 0 };
 
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-		sprintf(szhex, "%02X", b);
+        sprintf(szhex, "%02X", b);
 #elif _MSC_VER >= 1500
-		_stprintf_s(szhex, "%02X", b);
+        _stprintf_s(szhex, "%02X", b);
 #endif
 
-		return std::string(szhex);
-	}
-
-	BOOL IsValidString(LPCTSTR lpszString)
-	{
-		if (lpszString == NULL)
-			return FALSE;
-
-		do {
-			// ASCII可显示的字符;
-			if (*lpszString < 32 || *lpszString > 126) {
-				return FALSE;
-			}
-		} while (*++lpszString);
-
-		return TRUE;
-	}
-
-	unsigned char TwoHexCharToInteger(char high, char low)
-	{
-		std::string str = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
-		if (str.find_first_of(high) == std::string::npos || str.find_first_of(low) == std::string::npos)
-		{
-			return 0;
-		}
-
-		char Numb1 = high >= 'A' ? (toupper(high) - '0' - 7) * 16 : (high - '0') * 16;
-		char Numb2 = low >= 'A' ? (toupper(low) - '0' - 7) : (low - '0');
-
-		return (Numb1 + Numb2);
-	}
-
-	std::string BytesToHexString(const unsigned char* pbuffer, int nLen)
-	{
-		std::string hex;
-		char szhex[5] = { 0 };
-		for (int i = 0; i < nLen; i++)
-		{
-			memset(szhex, 0, 5);
+        return std::string(szhex);
+    }
+
+    BOOL IsValidString(LPCTSTR lpszString)
+    {
+        if (lpszString == NULL)
+            return FALSE;
+
+        do {
+            // ASCII可显示的字符;
+            if (*lpszString < 32 || *lpszString > 126) {
+                return FALSE;
+            }
+        } while (*++lpszString);
+
+        return TRUE;
+    }
+
+    unsigned char TwoHexCharToInteger(char high, char low)
+    {
+        std::string str = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+        if (str.find_first_of(high) == std::string::npos || str.find_first_of(low) == std::string::npos)
+        {
+            return 0;
+        }
+
+        char Numb1 = high >= 'A' ? (toupper(high) - '0' - 7) * 16 : (high - '0') * 16;
+        char Numb2 = low >= 'A' ? (toupper(low) - '0' - 7) : (low - '0');
+
+        return (Numb1 + Numb2);
+    }
+
+    std::string BytesToHexString(const unsigned char* pbuffer, int nLen)
+    {
+        std::string hex;
+        char szhex[5] = { 0 };
+        for (int i = 0; i < nLen; i++)
+        {
+            memset(szhex, 0, 5);
 
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-			sprintf(szhex, "%02X", pbuffer[i]);
+            sprintf(szhex, "%02X", pbuffer[i]);
 #elif _MSC_VER >= 1500
-			_stprintf_s(szhex, "%02X", pbuffer[i]);
+            _stprintf_s(szhex, "%02X", pbuffer[i]);
 #endif
-			hex.append(szhex);
-		}
-
-		return hex;
-	}
-
-	std::string BytesToHexString(const unsigned char* pbuffer, int nLen, char chSpace)
-	{
-		std::string hex;
-		char szhex[5] = { 0 };
-		for (int i = 0; i < nLen; i++)
-		{
-			memset(szhex, 0, 5);
+            hex.append(szhex);
+        }
+
+        return hex;
+    }
+
+    std::string BytesToHexString(const unsigned char* pbuffer, int nLen, char chSpace)
+    {
+        std::string hex;
+        char szhex[5] = { 0 };
+        for (int i = 0; i < nLen; i++)
+        {
+            memset(szhex, 0, 5);
 #if _MSC_VER >= 1200 && _MSC_VER < 1500
-			sprintf(szhex, "%02X%c", pbuffer[i], chSpace);
+            sprintf(szhex, "%02X%c", pbuffer[i], chSpace);
 #elif _MSC_VER >= 1500
-			_stprintf_s(szhex, "%02X%c", pbuffer[i], chSpace);
+            _stprintf_s(szhex, "%02X%c", pbuffer[i], chSpace);
 #endif
-			hex.append(szhex);
-		}
-
-		return hex.substr(0, hex.size() - 1);
-	}
-
-	std::string HexStringToBytes(std::string strHex, const int& len)
-	{
-		byte value = 0;
-		std::string strBytes;
-		int nSize = strHex.size();
-		for (int i = 0; i < nSize; i += len)
-		{
+            hex.append(szhex);
+        }
+
+        return hex.substr(0, hex.size() - 1);
+    }
+
+    std::string HexStringToBytes(std::string strHex, const int& len)
+    {
+        byte value = 0;
+        std::string strBytes;
+        int nSize = strHex.size();
+        for (int i = 0; i < nSize; i += len)
+        {
 #if _MSC_VER >=1200 && _MSC_VER < 1500
-			strBytes.append((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]), 1);
+            strBytes.append((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]), 1);
 #elif _MSC_VER >=1500
-			strBytes.push_back((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]));
+            strBytes.push_back((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]));
 #endif
-		}
-
-		return strBytes;
-	}
-
-	unsigned short CRC16Calculate(byte* pBuffer, unsigned int wordLength)
-	{
-		byte byteTemp(0);
-		unsigned short wordCRC(0);
-
-		wordCRC = 0xFFFF;
-		while (wordLength--) {
-			byteTemp = (byte)(wordCRC >> 0x0C);
-			wordCRC <<= 4;
-			wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) >> 0x04)];
-			byteTemp = (byte)(wordCRC >> 0x0C);
-			wordCRC <<= 4;
-			wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) & 0x0F)];
-			pBuffer++;
-		}
-
-		return wordCRC;
-	}
+        }
+
+        return strBytes;
+    }
+
+    unsigned short CRC16Calculate(byte* pBuffer, unsigned int wordLength)
+    {
+        byte byteTemp(0);
+        unsigned short wordCRC(0);
+
+        wordCRC = 0xFFFF;
+        while (wordLength--) {
+            byteTemp = (byte)(wordCRC >> 0x0C);
+            wordCRC <<= 4;
+            wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) >> 0x04)];
+            byteTemp = (byte)(wordCRC >> 0x0C);
+            wordCRC <<= 4;
+            wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) & 0x0F)];
+            pBuffer++;
+        }
+
+        return wordCRC;
+    }
+
+    bool GetResourceData(DWORD dwResourceID, LPCTSTR lpExt, std::string &rtnData)
+    {
+        HGLOBAL hGlobal = NULL;
+        HRSRC   hSource = NULL;
+        LPVOID  lpBuffer = NULL;
+        DWORD   dwSize = 0;
+        BOOL    bResult = FALSE;
+
+        // 1.查找资源,如果没找到返回Null
+        hSource = FindResource(NULL, MAKEINTRESOURCE(dwResourceID), lpExt);
+        if (hSource == NULL) {
+            _dprintf(_T("查找资源失败:%s,ID=%d"), lpExt, dwResourceID);
+            return false;
+        }
+
+        // 2.获取资源大小;
+        dwSize = (UINT)SizeofResource(NULL, hSource);
+
+        // 3.加载资源;
+        hGlobal = LoadResource(NULL, hSource);
+        if (hGlobal == NULL) {
+            _dprintf(_T("加载资源失败:%s,ID=%d"), lpExt, dwResourceID);
+            return false;
+        }
+
+        // 4.提取到buffer中;
+        lpBuffer = LockResource(hGlobal);
+        if (lpBuffer == NULL) {
+            _dprintf(_T("锁定资源失败:%s,ID=%d"), lpExt, dwResourceID);
+            return false;
+        }
 
+#if _MSC_VER >=1200 && _MSC_VER < 1500
+		rtnData = "";
+#elif _MSC_VER >= 1500
+        rtnData.clear();
+#endif
+        rtnData.append((char*)lpBuffer, dwSize);
+
+        // 释放资源;
+        UnlockResource(hGlobal);
+        FreeResource(hGlobal);
+
+        return true;
+    }
 }

+ 11 - 9
Serail-Demo/Demo/utils.h

@@ -1,15 +1,17 @@
 #pragma once
 namespace utils
 {
-	std::string& trim(std::string& str);
-	std::string _dprintf(CHAR* pszStr, ...);
-	std::string ByteToChars(byte b);
-	BOOL IsValidString(LPCTSTR lpszString);
-	unsigned char TwoHexCharToInteger(char high, char low);
-	std::string BytesToHexString(const unsigned char* pbuffer, int nLen);
-	std::string BytesToHexString(const unsigned char* pbuffer, int nLen, char chSpace);
+    std::string& trim(std::string& str);
+    std::string _dprintf(CHAR* pszStr, ...);
+    std::string ByteToChars(byte b);
+    BOOL IsValidString(LPCTSTR lpszString);
+    unsigned char TwoHexCharToInteger(char high, char low);
+    std::string BytesToHexString(const unsigned char* pbuffer, int nLen);
+    std::string BytesToHexString(const unsigned char* pbuffer, int nLen, char chSpace);
 
-	std::string HexStringToBytes(std::string strHex, const int& len /* = 3 */);
-	unsigned short CRC16Calculate(byte* pBuffer, unsigned int wordLength);
+    std::string HexStringToBytes(std::string strHex, const int& len /* = 3 */);
+    unsigned short CRC16Calculate(byte* pBuffer, unsigned int wordLength);
+
+	bool GetResourceData(DWORD dwResourceID, LPCTSTR lpExt, std::string &rtnData);
 };