Преглед на файлове

VS2008版本的IRControl:因为有些电脑上,无法加载VS2019生成的Pyd文件,故使用VS2008重新编译;

scbc.sat2 преди 5 години
родител
ревизия
ccc729a336

+ 26 - 0
IRControl_08/IRControl.sln

@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IRControl", "IRControl\IRControl.vcproj", "{59FE3448-7812-4B17-9817-A7F525D0A3A4}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		DebugPYD|Win32 = DebugPYD|Win32
+		Release|Win32 = Release|Win32
+		ReleasePYD|Win32 = ReleasePYD|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.Debug|Win32.ActiveCfg = Debug|Win32
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.Debug|Win32.Build.0 = Debug|Win32
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.DebugPYD|Win32.ActiveCfg = DebugPYD|Win32
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.DebugPYD|Win32.Build.0 = DebugPYD|Win32
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.Release|Win32.ActiveCfg = Release|Win32
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.Release|Win32.Build.0 = Release|Win32
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.ReleasePYD|Win32.ActiveCfg = ReleasePYD|Win32
+		{59FE3448-7812-4B17-9817-A7F525D0A3A4}.ReleasePYD|Win32.Build.0 = ReleasePYD|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 84 - 0
IRControl_08/IRControl/CritSection.h

@@ -0,0 +1,84 @@
+#ifndef __CRITSECTION_20160221__
+#define __CRITSECTION_20160221__
+
+// ÁÙ½çÖµ;
+class ThreadSection
+{
+public:
+	ThreadSection(){
+		HRESULT hr = Init();
+		(hr);
+	}
+
+	~ThreadSection(){
+		DeleteCriticalSection(&_CriticalSection);
+	}
+
+	bool Lock()
+	{
+		bool result = false;
+		__try
+		{
+			EnterCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+	bool Unlock()
+	{
+		bool result = false;
+		__try
+		{
+			LeaveCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+private:
+	HRESULT Init() throw()
+	{
+		HRESULT hRes = E_FAIL;
+		__try
+		{
+			InitializeCriticalSection(&_CriticalSection);
+			hRes = S_OK;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+			hRes = E_OUTOFMEMORY;
+		}
+		return hRes;
+	}
+
+	ThreadSection(const ThreadSection & tSection);
+	ThreadSection &operator=(const ThreadSection & tSection);
+	CRITICAL_SECTION _CriticalSection;
+};
+
+
+class AutoThreadSection
+{
+public:
+	AutoThreadSection(IN ThreadSection* pSection){
+		_pSection = pSection;
+		_pSection->Lock();
+	}
+
+	~AutoThreadSection(){
+		_pSection->Unlock();
+	}
+private:
+	AutoThreadSection(const AutoThreadSection & tSection);
+	AutoThreadSection &operator=(const AutoThreadSection & tSection);
+	ThreadSection * _pSection;
+};
+
+#endif //__CRITSECTION_20160221__

+ 537 - 0
IRControl_08/IRControl/Global.cpp

@@ -0,0 +1,537 @@
+#include "stdafx.h"
+#include "Global.h"
+#include <SetupAPI.h>
+#include <InitGuid.h>
+#include <WinIoCtl.h>
+#include <direct.h>
+#pragma comment(lib, "SetupAPI.lib")
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	TCHAR g_szCurModuleDir[MAX_PATH] = { 0 };
+	TCHAR g_szCurModulePath[MAX_PATH] = { 0 };
+	TCHAR g_szFna[MAX_PATH] = { 0 };
+	TCHAR g_szConfig[MAX_PATH] = { 0 };
+	TCHAR g_szLogPath[MAX_PATH] = { 0 };
+	bool g_bEnableLog = false;
+	time_t g_time = time(NULL);
+	
+	//////////////////////////////////////////////////////////////////////////
+	void MKDIR(LPCTSTR dir) 
+	{
+		//////////////////////////////////////////////////////////////////////////
+		// 创建目录;
+		int nleft = 0;
+		int nIndex = -1;
+		string strdir = dir;
+		strdir = strdir.substr(0, strdir.find_last_of(_T("\\")));
+
+		if (strdir.at(strdir.size() - 1) != _T('\\'))
+			strdir.append(_T("\\"));
+
+		// 共享路径和硬盘盘符;
+		if (_tcscmp(strdir.substr(0, 2).c_str(), _T("\\\\")) == 0)
+			nleft = strdir.find_first_of(_T("\\"), 2) + 1;	// 去除共享主机名;
+		else if (strdir.at(2) == _T('\\'))
+			nleft = 3;
+
+		do
+		{
+			nIndex = strdir.substr(nleft, -1).find_first_of(_T("\\"));
+
+			if (nIndex != string::npos)
+			{
+				if (_mkdir(strdir.substr(0, nIndex + nleft).c_str()) == -1 && (errno != EEXIST))
+				{
+					//WriteTextLog(_T("创建目录失败:%s,错误码:%d"), strdir.substr(0, nIndex + nleft).c_str(), errno);
+					break;
+				}
+
+				nleft += nIndex + 1;
+			}
+		} while (nIndex != -1);
+	};
+
+	// 全局函数;
+	/************************************************************************/
+	/*  函数:WriteTextLog[7/28/2009 Jeff];
+	/*  描述:写文本日志;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void WriteTextLog(const TCHAR* format, ...)
+	{
+		// 将日志内容输入到文件中;
+		// 获取今年年份;
+		__time64_t gmt = time(NULL); // 获取当前日历时间(1900-01-01开始的Unix时间戳);
+		struct tm gmtm = { 0 };
+		localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+
+		// 解析出日志路径;
+		TCHAR szlogpath[MAX_PATH] = { 0 };
+		_stprintf_s(szlogpath, _T("%slog %02d%02d.txt"), g_szCurModuleDir, gmtm.tm_mon + 1, gmtm.tm_mday);
+		// 打开或创建文件;
+		FILE* fp = NULL;
+		MKDIR(szlogpath);
+		//if (_taccess(szlogpath, 0) != -1)
+#ifndef UNICODE
+		if (_access(szlogpath, 0) != -1)
+#else
+		if (_taccess(szlogpath, 0) != -1)
+#endif
+		{ // 存在;
+			if (0 == _tfopen_s(&fp, szlogpath, _T("a+")))
+				// 移动到末尾;
+				fseek(fp, 0, SEEK_END);
+		}
+		else
+		{ // 不存在;
+			_tfopen_s(&fp, szlogpath, _T("w+"));
+		}
+
+		if (fp == NULL)
+			return;
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs")); //设定中文;
+
+		// 格式化日志内容;
+		va_list args = NULL;
+		int len = 0;
+		TCHAR* buffer = NULL;
+		va_start(args, format);
+		// _vscprintf doesn't count. terminating '\0'
+		len = _vsctprintf(format, args) + 1;
+		buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
+		_vstprintf_s(buffer, len, format, args);
+		_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);
+
+		// 关闭文件,释放资源并设置回原语言区域;
+		free(buffer);
+		fclose(fp);
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale); //还原区域设定;
+	}
+
+	void WritePythonLog(const TCHAR* format, ...)
+	{
+		// 将日志内容输入到文件中;
+		// 获取今年年份;
+		__time64_t gmt = time(NULL); // 获取当前日历时间(1900-01-01开始的Unix时间戳);
+		struct tm gmtm = { 0 };
+		localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+
+		// 解析出日志路径;
+		//TCHAR szlogpath[MAX_PATH] = { 0 };
+		//_stprintf_s(szlogpath, _T("%slog\\Serial Port Log %02d%02d.txt"), g_szCurModuleDir, gmtm.tm_mon + 1, gmtm.tm_mday);
+		// 打开或创建文件;
+		FILE* fp = NULL;
+		MKDIR(g_szLogPath);
+		//if (_taccess(szlogpath, 0) != -1)
+#ifndef UNICODE
+		if (_access(g_szLogPath, 0) != -1)
+#else
+		if (_taccess(g_szLogPath, 0) != -1)
+#endif
+		{ // 存在;
+			if (0 == _tfopen_s(&fp, g_szLogPath, _T("a+")))
+				// 移动到末尾;
+				fseek(fp, 0, SEEK_END);
+		}
+		else
+		{ // 不存在;
+			_tfopen_s(&fp, g_szLogPath, _T("w+"));
+		}
+
+		if (fp == NULL)
+			return;
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs")); //设定中文;
+
+		// 格式化日志内容;
+		va_list args = NULL;
+		int len = 0;
+		TCHAR* buffer = NULL;
+		va_start(args, format);
+		// _vscprintf doesn't count. terminating '\0'
+		len = _vsctprintf(format, args) + 1;
+		buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
+		_vstprintf_s(buffer, len, format, args);
+		_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);
+
+		// 关闭文件,释放资源并设置回原语言区域;
+		free(buffer);
+		fclose(fp);
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale); //还原区域设定;
+	}
+
+	// 去除空格;
+	std::string& trim(std::string& str)
+	{
+		int nIndex = 0;
+		while ((nIndex = str.find_first_of(' ')) != std::string::npos)
+			str.erase(nIndex, 1);
+
+		return str;
+	}
+
+	void Init()
+	{
+		TCHAR szDrive[_MAX_DRIVE] = { 0 };
+		TCHAR szDir[_MAX_DIR] = { 0 };
+		TCHAR szExt[_MAX_DIR] = { 0 };
+		::GetModuleFileName(NULL, g_szCurModulePath, sizeof(g_szCurModulePath) / sizeof(TCHAR));
+		_tsplitpath_s(g_szCurModulePath, szDrive, szDir, g_szFna, szExt);
+		_tcscpy_s(g_szCurModuleDir, szDrive);
+		_tcscat_s(g_szCurModuleDir, szDir);
+		SetCurrentDirectory(g_szCurModulePath);
+	}
+
+	// hModule 模块句柄 NULL表示当前模块;
+	bool GetVersion(IN const TCHAR* fname, OUT WORD* pdwFileVersion, OUT WORD* pdwProductVerion)
+	{
+		VS_FIXEDFILEINFO* pVi = NULL;
+		DWORD dwHandle = 0;
+		int size = GetFileVersionInfoSize(fname, &dwHandle);
+		if (size > 0)
+		{
+			BYTE* buffer = new BYTE[size];
+			memset(buffer, 0, size);
+
+			if (GetFileVersionInfo(fname, 0, size, buffer))
+			{
+				if (VerQueryValue(buffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& size))
+				{
+					pdwFileVersion[0] = HIWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[1] = LOWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[2] = HIWORD(pVi->dwFileVersionLS);
+					pdwFileVersion[3] = LOWORD(pVi->dwFileVersionLS);
+
+					pdwProductVerion[0] = HIWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[1] = LOWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[2] = HIWORD(pVi->dwProductVersionLS);
+					pdwProductVerion[3] = LOWORD(pVi->dwProductVersionLS);
+
+					delete[] buffer;
+					return true;
+				}
+			}
+
+			delete[] buffer;
+		}
+
+		return false;
+	}
+
+	BOOL GetVersion(IN HMODULE hModule, OUT DWORD(&dwFVArray)[4], OUT DWORD(&dwPVArray)[4])
+	{
+		TCHAR fname[MAX_PATH];
+		VS_FIXEDFILEINFO* pVi;
+		DWORD dwHandle;
+
+		if (GetModuleFileName(hModule, fname, MAX_PATH))
+		{
+			INT nSize = GetFileVersionInfoSize(fname, &dwHandle);
+
+			if (nSize > 0)
+			{
+				BYTE* pBuffer = new BYTE[nSize];
+				memset(pBuffer, 0, nSize);
+
+				if (GetFileVersionInfo(fname, 0, nSize, pBuffer))
+				{
+					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& nSize))
+					{
+						dwFVArray[0] = HIWORD(pVi->dwFileVersionMS);
+						dwFVArray[1] = LOWORD(pVi->dwFileVersionMS);
+						dwFVArray[2] = HIWORD(pVi->dwFileVersionLS);
+						dwFVArray[3] = LOWORD(pVi->dwFileVersionLS);
+
+						dwPVArray[0] = HIWORD(pVi->dwProductVersionMS);
+						dwPVArray[1] = LOWORD(pVi->dwProductVersionMS);
+						dwPVArray[2] = HIWORD(pVi->dwProductVersionLS);
+						dwPVArray[3] = LOWORD(pVi->dwProductVersionLS);
+
+						delete[]pBuffer;
+						return TRUE;
+					}
+				}
+
+				if (pBuffer)
+					delete[]pBuffer;
+			}
+		}
+
+		return FALSE;
+	}
+
+	WCHAR* ASCII2UNICODE(IN LPCCH lpASCIIStr)
+	{
+		if (lpASCIIStr == NULL)
+			return NULL;
+
+		// 获取宽字符字节数;
+		int cchWideChar = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+		if (cchWideChar == 0)
+			return NULL;
+
+		// 转换成宽字符串;
+		WCHAR* pWideChar = new WCHAR[cchWideChar + 1];
+		memset(pWideChar, 0, sizeof(WCHAR) * (cchWideChar + 1));
+		int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pWideChar, cchWideChar);
+		if (nWriteNum != cchWideChar)
+		{
+			if (pWideChar)
+				delete[] pWideChar;
+			return NULL;
+		}
+
+		return pWideChar;
+	}
+
+	BOOL UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT string& strResult)
+	{
+		if (lpUNICODEStr == NULL)
+			return FALSE;
+
+		// 获取多字节字符字节数;
+		int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+		if (cbMultiByte == 0)
+			return FALSE;
+
+		// 转换成多字节字符;
+		CHAR* pResult = new CHAR[cbMultiByte];
+		memset(pResult, 0, cbMultiByte);
+		int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pResult, cbMultiByte, NULL, NULL);
+		if (nWriteNum != cbMultiByte)
+			return FALSE;
+
+		strResult = pResult;
+		if (pResult)
+			delete[] pResult;
+
+		return TRUE;
+	}
+
+	BOOL ASCII2UTF8(IN LPCCH lpASCIIStr, OUT string& strResult)
+	{
+		// 将ASCII字符串转成UNICODE字符串;
+		WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+		if (pWideChar == NULL)
+			return FALSE;
+
+		// 再将UICODE转成UTF8;
+		BOOL bResult = UNICODE2UTF8(pWideChar, strResult);
+
+		if (pWideChar)
+			delete[] pWideChar;
+
+		return bResult;
+	}
+
+	string EnCode_UTF8URL(IN const CHAR* pText)
+	{
+		string tt = "";
+		string dd = "";
+		ASCII2UTF8(pText, tt);
+
+		size_t len = tt.length();
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)tt.at(i)))
+			{
+				char tempbuff[2] = { 0 };
+				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+				dd.append(tempbuff);
+			}
+			else if (isspace((BYTE)tt.at(i)))
+			{
+				dd.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				dd.append(tempbuff);
+			}
+		}
+		return dd;
+	}
+
+	void EnCode_UTF8URL(IN const CHAR* pText, OUT string& strResult)
+	{
+		string tt = "";
+		ASCII2UTF8(pText, tt);
+
+		size_t len = tt.length();
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)tt.at(i)))
+			{
+				char tempbuff[2] = { 0 };
+				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+				strResult.append(tempbuff);
+			}
+			else if (isspace((BYTE)tt.at(i)))
+			{
+				strResult.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				strResult.append(tempbuff);
+			}
+		}
+	}
+
+	//做为解Url使用
+	char CharToInt(char ch)
+	{
+		if (ch >= '0' && ch <= '9')return (char)(ch - '0');
+		if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
+		if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
+		return -1;
+	}
+
+	char StrToBin(IN char(&str)[2])
+	{
+		char tempWord[2];
+		char chn;
+
+		tempWord[0] = CharToInt(str[0]);                         //make the B to 11 -- 00001011
+		tempWord[1] = CharToInt(str[1]);                         //make the 0 to 0  -- 00000000
+
+		chn = (tempWord[0] << 4) | tempWord[1];                //to change the BO to 10110000
+
+		return chn;
+	}
+
+	CHAR* UNICODE2ASCII(IN LPWCH lpUNICODEStr)
+	{
+		if (lpUNICODEStr == NULL)
+			return NULL;
+
+		// 获取多字节字符字节数;
+		int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+		if (cbMultiByte == 0)
+			return NULL;
+
+		// 转换成多字节字符;
+		CHAR *pMultiByteStr = new CHAR[cbMultiByte + 1];
+		memset(pMultiByteStr, 0, cbMultiByte + 1);
+		int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pMultiByteStr, cbMultiByte, NULL, NULL);
+		if (nWriteNum != cbMultiByte)
+		{
+			if (pMultiByteStr)
+				delete[]pMultiByteStr;
+			return NULL;
+		}
+
+		pMultiByteStr[cbMultiByte] = '\0';
+
+		return pMultiByteStr;
+	}
+
+	BOOL UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen)
+	{
+		if (lpUNICODEStr == NULL)
+			return FALSE;
+
+		// 获取多字节字符字节数;
+		int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+		if (cbMultiByte == 0 || cbMultiByte >= nASCIIStrLen)
+			return FALSE;
+
+		// 转换成多字节字符;
+		memset((void*)pASCIIStr, 0, nASCIIStrLen);
+		int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pASCIIStr, cbMultiByte, NULL, NULL);
+		if (nWriteNum != cbMultiByte)
+		{
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	/************************************************************************/
+	/*  函数:[7/26/2016 IT];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	string DeCode_URLUNICODE(IN const CHAR* pURLText)
+	{
+		string str = pURLText;
+		string strResult = "";
+
+		INT nIndex = 0;
+		string strTemp = "";
+
+		while (str.find("\\u", 0, 2) != string::npos)
+		{
+			nIndex = str.find("\\u", 0, 2);
+			strResult.append(str.substr(0, nIndex));
+			strTemp = str.substr(nIndex + 2, 4);
+			str = str.substr(nIndex + 2 + 4);
+			CHAR szReturn[10] = { 0 };
+
+			union  __UNION_VAR_INT {
+				BYTE   ch[2];
+				int	   value;
+			}unionVarInt;
+
+			unionVarInt.ch[0] = (CharToInt(strTemp.at(2)) << 4) | (CharToInt(strTemp.at(3)) & 0x00FF);
+			unionVarInt.ch[1] = (CharToInt(strTemp.at(0)) << 4) | (CharToInt(strTemp.at(1)) & 0x00FF);
+
+			WCHAR szWide[2] = { 0 };
+			szWide[0] = unionVarInt.value;
+			UNICODE2ASCII(szWide, szReturn, 10);
+			strResult.append(szReturn);
+		}
+		strResult.append(str);
+
+		return strResult;
+	}
+
+	// 通过注册表查找系统当前串口信息;
+	
+	BOOL IsValidString(LPCTSTR lpszString)
+	{
+		if (lpszString == NULL)
+			return FALSE;
+
+		do
+		{
+			// ASCII可显示的字符;
+			if (*lpszString < 32 || *lpszString > 126)
+			{
+				return FALSE;
+			}
+		} while (*++lpszString);
+
+		return TRUE;
+	}
+} // namespace Global

+ 43 - 0
IRControl_08/IRControl/Global.h

@@ -0,0 +1,43 @@
+
+#pragma once
+#include <stdio.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h> //或者 #include <ctime>
+#include <io.h>
+#pragma comment(lib,"version.lib")
+#include <tchar.h>
+#include <vector>
+#include <string>
+using namespace std;
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	extern TCHAR g_szCurModuleDir[MAX_PATH];
+	extern TCHAR g_szCurModulePath[MAX_PATH];
+	extern TCHAR g_szFna[MAX_PATH];
+	extern TCHAR g_szConfig[MAX_PATH];
+
+	extern bool g_bEnableLog;
+	extern TCHAR g_szLogPath[MAX_PATH];
+	extern time_t g_time;
+
+	typedef struct _TLOG_{
+		string report_type;
+		string report_data;
+	}TLog, *pTLog;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	void Init();
+	bool GetVersion(IN const TCHAR *fname, OUT WORD *pdwFileVersion, OUT WORD *pdwProductVerion);
+	BOOL GetVersion(IN HMODULE hModule, OUT DWORD(&dwFVArray)[4], OUT DWORD(&dwPVArray)[4]);
+	void WriteTextLog(const TCHAR *format, ...);
+	void WritePythonLog(const TCHAR *format, ...);
+	std::string EnCode_UTF8URL(IN const CHAR* pText);
+	std::string &trim(std::string &str);
+	// 字符串是否由数字、字母、符号组成;
+	BOOL IsValidString(LPCTSTR lpszString);
+	string DeCode_URLUNICODE(IN const CHAR* pURLText);
+};

+ 365 - 0
IRControl_08/IRControl/IRControl.cpp

@@ -0,0 +1,365 @@
+// IRControl.cpp : 定义 DLL 应用程序的导出函数。
+//
+
+#include "stdafx.h"
+#include "IRControl.h"
+#include "RedRatProcess.h"
+#ifdef __MAKE_PYD__
+#include "Python.h"
+#endif
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+#ifdef __DEFUALT__
+// 唯一的应用程序对象
+
+CWinApp theApp;
+
+using namespace std;
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+	int nRetCode = 0;
+
+	// 初始化 MFC 并在失败时显示错误
+	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+	{
+		// TODO: 更改错误代码以符合您的需要
+		_tprintf(_T("错误: MFC 初始化失败\n"));
+		nRetCode = 1;
+	}
+	else
+	{
+		// TODO: 在此处为应用程序的行为编写代码。
+	}
+
+	return nRetCode;
+}
+
+#endif
+
+static CRedRatProcess g_IRControl;
+#ifndef __MAKE_PYD__
+// 定义 DLL 的导出函数和变量。
+int nIRControl = 100;
+
+IRCONTROL_API DWORD IsAppRunning(LPCTSTR lpszAppDir)
+{
+	return CRedRatProcess::IsAppRunning(lpszAppDir);
+}
+
+IRCONTROL_API bool StartIRApp(LPCTSTR lpszAppDir, LPCTSTR lpSignalXml, DWORD dwPort)
+{
+	if (!CRedRatProcess::StartApp(lpszAppDir, lpSignalXml, dwPort))
+		return false;
+
+	return true;
+}
+
+IRCONTROL_API bool CloseApp()
+{
+	return CRedRatProcess::CloseApp();
+}
+
+IRCONTROL_API bool Connect(LPCTSTR lpServer, int port)
+{
+	// 创建连接;
+	if (!g_IRControl.InitSocket())
+	{
+		Global::WriteTextLog(_T("创建TCP连接失败"));
+		//g_IRControl.CloseApp();
+		return false;
+	}
+
+	if (!lpServer || lpServer[0] == '\0' || port < 0)
+		return false;
+
+	//if (!g_IRControl.SelectConnect(lpServer, port, 5000))
+	if (!g_IRControl.Connect(lpServer, port))
+	{
+		Global::WriteTextLog(_T("连接服务器失败"));
+		//g_IRControl.CloseApp();
+		return false;
+	}
+
+	return true;
+}
+
+IRCONTROL_API void DisConnect()
+{
+	g_IRControl.DisConnect();
+}
+
+IRCONTROL_API LPCTSTR getDeviceNames()
+{
+	static std::string devices;
+	std::vector<std::string> vtDevices;
+	if ( g_IRControl.getDeviceNameList(vtDevices) )
+	{
+		devices.clear();
+		for ( std::vector<std::string>::iterator dv = vtDevices.begin(); dv != vtDevices.end(); dv++)
+		{
+			devices.append(*dv + _T(";"));
+		}
+
+		return devices.c_str();
+	}
+
+	return _T("");
+}
+
+IRCONTROL_API LPCTSTR getSignalsName()
+{
+	static std::string signals;
+	signals = g_IRControl.getSignalsName();
+
+	return signals.c_str();
+}
+
+IRCONTROL_API bool loadSignalDataSet(LPCTSTR lpDatasetXml)
+{
+	if (!lpDatasetXml || lpDatasetXml[0] == '\0')
+		return false;
+
+	return g_IRControl.loadSignalDataSet(lpDatasetXml);
+}
+
+IRCONTROL_API bool sendSignal(LPCTSTR lpSignal, int send_times, int sleep_time)
+{
+	if (!lpSignal || lpSignal[0] == '\0')
+		return false;
+
+	return g_IRControl.sendSignal(lpSignal, send_times, sleep_time);
+}
+
+IRCONTROL_API bool sendSignals(LPCTSTR lpSignals, int sleep_time)
+{
+	if (!lpSignals || lpSignals[0] == '\0')
+		return false;
+
+	std::string signals = lpSignals;
+	std::vector<std::string> vtSignals;
+	int npos = -1;
+	while (true)
+	{
+		npos = signals.find_first_of(';');
+		if (npos == std::string::npos)
+			break;
+
+		vtSignals.push_back(signals.substr(0, npos));
+		signals = signals.substr(npos + 1);
+	}
+	vtSignals.push_back(signals);
+
+	return g_IRControl.sendSignals(vtSignals, sleep_time);
+}
+
+IRCONTROL_API bool sendRepeatsSignal(LPCTSTR lpSignal, int repeat_time)
+{
+	if (!lpSignal || lpSignal[0] == '\0')
+		return false;
+
+	return g_IRControl.sendRepeatsSignal(lpSignal, repeat_time);
+}
+#else
+
+static PyObject* IsAppRunning(PyObject* self, PyObject* args)
+{
+	// 应用程序路径;
+	const char* pszExePath = NULL;
+	if (!PyArg_ParseTuple(args, "s", &pszExePath))
+		return NULL;
+
+	// 返回进程Id;
+	return Py_BuildValue("i", CRedRatProcess::IsAppRunning(pszExePath));
+}
+
+static PyObject* StartApp(PyObject* self, PyObject* args)
+{
+	// 应用程序路径;
+	const char* pszExePath = NULL;
+	const char* pszDataset = NULL;
+	unsigned int port = 0;
+	if (!PyArg_ParseTuple(args, "ssI", &pszExePath, &pszDataset, &port))
+		return NULL;
+
+	return Py_BuildValue("b", CRedRatProcess::StartApp(pszExePath, pszDataset, port));
+}
+
+static PyObject* StopApp(PyObject* self, PyObject* args)
+{
+	return Py_BuildValue("b", CRedRatProcess::CloseApp());	// 返回None;
+}
+
+//描述:连接设备,默认连接索引为0的设备;
+static PyObject* ConnectDevice(PyObject* self, PyObject* args)
+{
+	unsigned int port = 0;
+	const char* pszServer = NULL;
+	if (!PyArg_ParseTuple(args, "sI", &pszServer, &port))
+		return NULL;
+
+	// 创建连接;
+	if (!g_IRControl.InitSocket())
+	{
+		Global::WriteTextLog(_T("创建TCP连接失败"));
+		g_IRControl.CloseApp();
+		return Py_BuildValue("b", false);
+	}
+
+	if (!pszServer || pszServer[0] == '\0' || port < 0)
+		return Py_BuildValue("b", false);
+
+	if (!g_IRControl.SelectConnect(pszServer, port, 5000))
+	{
+		Global::WriteTextLog(_T("连接服务器失败"));
+		g_IRControl.CloseApp();
+		return Py_BuildValue("b", false);
+	}
+
+	return Py_BuildValue("b", true);
+}
+
+static PyObject* DisconnectDevice(PyObject* self, PyObject* args)
+{
+	g_IRControl.DisConnect();
+	return Py_BuildValue("");
+}
+
+static PyObject* getDeviceNames(PyObject* self, PyObject* args)
+{
+	std::string devices;
+	std::vector<std::string> vtDevices;
+	if (g_IRControl.getDeviceNameList(vtDevices))
+	{
+		for (std::vector<std::string>::iterator dv = vtDevices.begin(); dv != vtDevices.end(); dv++ )
+		{
+			devices.append(*dv + _T(";"));
+		}
+
+		return Py_BuildValue("s", devices.c_str());
+	}
+
+	return Py_BuildValue("s", "");
+}
+
+static PyObject* loadSignalDataSet(PyObject* self, PyObject* args)
+{
+	const char* pszDatasetXml = NULL;
+	if (!PyArg_ParseTuple(args, "s", &pszDatasetXml))
+		return NULL;
+
+	if ( !pszDatasetXml || pszDatasetXml[0] == '\0')
+		return Py_BuildValue("b", false);
+
+	if (!g_IRControl.loadSignalDataSet(std::string(pszDatasetXml)) )
+	{
+		Global::WriteTextLog(_T("加载信号数据集失败"));
+		g_IRControl.CloseApp();
+		return Py_BuildValue("b", false);
+	}
+
+	return Py_BuildValue("b", true);
+}
+
+static PyObject* getSignalsName(PyObject* self, PyObject* args)
+{
+	std::string data = g_IRControl.getSignalsName();
+	return Py_BuildValue("s", data.c_str());
+}
+
+static PyObject* sendSignal(PyObject* self, PyObject* args)
+{
+	const char* pszSignal = NULL;
+	int send_times = 1, sleep_time = 1000;
+	if (!PyArg_ParseTuple(args, "sii", &pszSignal, &send_times, &sleep_time))
+		return NULL;
+
+	if (!pszSignal || pszSignal[0] == '\0')
+		return Py_BuildValue("b", false);
+
+	return Py_BuildValue("b", g_IRControl.sendSignal(pszSignal, send_times, sleep_time));
+}
+
+static PyObject* sendSignals(PyObject* self, PyObject* args)
+{
+	const char* pszSignal = NULL;
+	int sleep_time = 1000;
+	if (!PyArg_ParseTuple(args, "si", &pszSignal, &sleep_time))
+		return NULL;
+
+	if (!pszSignal || pszSignal[0] == '\0')
+		return Py_BuildValue("b", false);
+
+	std::string signals = pszSignal;
+	std::vector<std::string> vtSignals;
+	int npos = -1;
+	while (true)
+	{
+		npos = signals.find_first_of(';');
+		if (npos == std::string::npos)
+			break;
+
+		vtSignals.push_back(signals.substr(0, npos));
+		signals = signals.substr(npos + 1);
+	}
+	vtSignals.push_back(signals);
+
+	return Py_BuildValue("b", g_IRControl.sendSignals(vtSignals, sleep_time));
+}
+
+static PyObject* sendRepeatsSignal(PyObject* self, PyObject* args)
+{
+	const char* pszSignal = NULL;
+	int repeat_time = 2;
+	if (!PyArg_ParseTuple(args, "si", &pszSignal, &repeat_time))
+		return NULL;
+
+	if (!pszSignal || pszSignal[0] == '\0')
+		return Py_BuildValue("b", false);
+
+	return Py_BuildValue("b", g_IRControl.sendRepeatsSignal(pszSignal, repeat_time));
+}
+
+static PyObject* sendDurationSignal(PyObject* self, PyObject* args)
+{
+	const char* pszSignal = NULL;
+	int duration_time = 2;
+	if (!PyArg_ParseTuple(args, "si", &pszSignal, &duration_time))
+		return NULL;
+
+	if (!pszSignal || pszSignal[0] == '\0')
+		return Py_BuildValue("b", false);
+
+	return Py_BuildValue("b", g_IRControl.sendDurationSignal(pszSignal, duration_time));
+}
+
+// 描述方法,暴露给python的函数;
+static PyMethodDef IRControl_Methods[] = {
+	{"IsAppRunning",IsAppRunning,METH_VARARGS,"程序是否在运行"},
+	{"StartApp", StartApp, METH_VARARGS, "启动进程"},
+	{"StopApp", StopApp, METH_VARARGS, "关闭进程"},
+	{"ConnectDevice", ConnectDevice, METH_VARARGS, "连接设备"},
+	{"DisconnectDevice", DisconnectDevice, METH_VARARGS, "断开设备"},
+	{"getDeviceNames", getDeviceNames, METH_VARARGS, "获取设备列表,逗号分隔"},
+	{"loadSignalDataSet", loadSignalDataSet, METH_VARARGS, "加载指定目录的信号数据集XML文件"},
+	{"getSignalsName", getSignalsName, METH_VARARGS, "获取默认信号数据集信号列表"},
+	{"sendSignal", sendSignal, METH_VARARGS, "发送单个信号"},
+	{"sendSignals", sendSignals, METH_VARARGS, "发送多个信号,以分号为分隔符"},
+	{"sendRepeatsSignal", sendRepeatsSignal, METH_VARARGS, "发送重复信号"},
+	{"sendDurationSignal", sendDurationSignal, METH_VARARGS, "发送时叠信号"},
+
+	{NULL,NULL}
+};
+
+// 初始模块;//格式:init<模块名称>
+PyMODINIT_FUNC initIRControl()
+{
+	// 初始化pyd函数列表;
+	PyObject* m, * d;
+	m = Py_InitModule("IRControl", IRControl_Methods);
+	d = PyModule_GetDict(m);
+}
+#endif

+ 42 - 0
IRControl_08/IRControl/IRControl.h

@@ -0,0 +1,42 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 IRCONTROL_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// IRCONTROL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+#ifdef IRCONTROL_EXPORTS
+#define IRCONTROL_API __declspec(dllexport)
+#else
+#define IRCONTROL_API __declspec(dllimport)
+#endif
+
+
+#ifndef __MAKE_PYD__ // 是否使用PYD;
+
+extern "C" IRCONTROL_API int nIRControl;
+
+//////////////////////////////////////////////////////////////////////////
+// 程序是否在运行;
+extern "C" IRCONTROL_API DWORD IsAppRunning(LPCTSTR lpszAppDir);
+// 启动红老鼠服务进程;
+extern "C" IRCONTROL_API bool StartIRApp(LPCTSTR lpszAppDir, LPCTSTR lpSignalXml, DWORD dwPort);
+// 关闭红老鼠;
+extern "C" IRCONTROL_API bool CloseApp();
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" IRCONTROL_API bool Connect(LPCTSTR lpServer, int port);
+extern "C" IRCONTROL_API void DisConnect();
+// 返回设备列表,以逗号隔开;
+extern "C" IRCONTROL_API LPCTSTR getDeviceNames();
+// 获取信号数据集信号,以\n分隔;
+extern "C" IRCONTROL_API LPCTSTR getSignalsName();
+// 加载xml文件;
+extern "C" IRCONTROL_API bool loadSignalDataSet(LPCTSTR lpDatasetXml);
+// 发送单个信号;
+extern "C" IRCONTROL_API bool sendSignal(LPCTSTR lpSignal, int send_times, int sleep_time);
+// 发送多个信号,以逗号分隔;
+extern "C" IRCONTROL_API bool sendSignals(LPCTSTR lpSignals, int sleep_time);
+// 发送重复信号;
+extern "C" IRCONTROL_API bool sendRepeatsSignal(LPCTSTR lpSignal, int repeat_time);
+
+#endif

+ 69 - 0
IRControl_08/IRControl/IRControl.rc

@@ -0,0 +1,69 @@
+//Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#include "afxres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+   IDS_APP_TITLE       "IRControl"
+END
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#ifndef _AFXDLL
+#include "l.CHS\\afxres.rc"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED

+ 438 - 0
IRControl_08/IRControl/IRControl.vcproj

@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="IRControl"
+	ProjectGUID="{59FE3448-7812-4B17-9817-A7F525D0A3A4}"
+	RootNamespace="IRControl"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)\"
+			IntermediateDirectory="$(OutDir)$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\cJSON"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IRCONTROL_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)\"
+			IntermediateDirectory="$(OutDir)$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="..\cJSON"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IRCONTROL_EXPORTS"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugPYD|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)\"
+			IntermediateDirectory="$(OutDir)$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\cJSON;C:\Python27\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IRCONTROL_EXPORTS;__MAKE_PYD__"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="C:\Python27\libs"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleasePYD|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)\"
+			IntermediateDirectory="$(OutDir)$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="..\cJSON;C:\Python27\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IRCONTROL_EXPORTS;__MAKE_PYD__"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="C:\Python27\libs"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\Global.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\IRControl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\RedRatProcess.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="DebugPYD|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="ReleasePYD|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\TCPClient.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\CritSection.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Global.h"
+				>
+			</File>
+			<File
+				RelativePath=".\IRControl.h"
+				>
+			</File>
+			<File
+				RelativePath=".\RedRatProcess.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+			<File
+				RelativePath=".\TCPClient.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\IRControl.rc"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 48 - 0
IRControl_08/IRControl/ReadMe.txt

@@ -0,0 +1,48 @@
+========================================================================
+    动态链接库:IRControl 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 IRControl DLL。
+
+本文件概要介绍组成 IRControl 应用程序的
+的每个文件的内容。
+
+
+IRControl.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+IRControl.cpp
+    这是主 DLL 源文件。
+
+	此 DLL 在创建时不导出任何符号。因此,在生成此 DLL 时
+	将不会产生 .lib 文件。如果希望此项目
+	成为其他某个项目的项目依赖项,则需要
+	添加代码以从 DLL 导出某些符号,
+	以便产生一个导出库,或者,也可以在项目“属性页”对话框中的
+	“链接器”文件夹中,将“常规”属性页上的
+	“忽略输入库”属性设置为“是”。
+
+/////////////////////////////////////////////////////////////////////////////
+应用程序向导创建了下列资源:
+
+IRControl.rc
+这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。
+此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 IRControl.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 559 - 0
IRControl_08/IRControl/RedRatProcess.cpp

@@ -0,0 +1,559 @@
+#include "StdAfx.h"
+#include "RedRatProcess.h"
+#include <tlhelp32.h>
+#include <Shlwapi.h>
+#include "shellapi.h"
+#pragma comment(lib, "shlwapi.lib")
+#include "Global.h"
+
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+#ifndef SEND_SG_FORMAT
+#define SEND_SG_FORMAT _T("name=\"%s\",dataset=\"%s\",signal=\"%s\"\n")
+#endif
+
+#ifndef SEND_SG_REP_FORMAT
+#define SEND_SG_REP_FORMAT _T("name=\"%s\",dataset=\"%s\",signal=\"%s\",repeats=\"%d\"\n")
+#endif
+
+#ifndef SEND_SG_DUR_FORMAT
+#define SEND_SG_DUR_FORMAT _T("name=\"%s\",dataset=\"%s\",signal=\"%s\",duration=\"%d\"\n")
+#endif
+
+#ifndef SEND_SG_BOTH_FORMAT
+#define SEND_SG_BOTH_FORMAT _T("name=\"%s\",dataset=\"%s\",signal=\"%s\",repeats=\"%d\",duration=\"%d\"\n")
+#endif
+
+#ifndef APP_CMD_LINE
+#define APP_CMD_LINE _T("%s --port=%ld")
+#endif
+
+#ifndef GET_IRC_DATA
+#define GET_IRC_DATA \
+	if (m_strCurDevice.size() == 0) \
+	getDeviceNameList(); \
+	if (m_strCurDevice.size() == 0) \
+	return false;\
+	if (m_strCurDataset.size() == 0)\
+	getDatasetNameList();\
+	if (m_strCurDataset.size() == 0)\
+	return false;
+#endif
+
+DWORD CRedRatProcess::m_dwCurAppId = 0;
+
+// 获取设备名;
+void fun_dev(std::vector<std::string>& vtDev, std::string _dev_) {
+	int npos = -1;
+	npos = _dev_.find_last_of(']');
+	if (npos != std::string::npos)
+	{
+		_dev_ = _dev_.substr(npos + 2); // +2 包含空格;
+		// 去除connected;
+		npos = _dev_.find(" (connected)");
+		if (npos != std::string::npos)
+		{
+			_dev_ = _dev_.substr(0, npos);
+		}
+		vtDev.push_back(_dev_);
+	}
+};
+
+
+CRedRatProcess::CRedRatProcess(void)
+{
+}
+
+CRedRatProcess::~CRedRatProcess(void)
+{
+}
+
+bool CRedRatProcess::checkEOM(std::string& data)
+{
+	if (data.size() < 5)
+		return false;
+
+	if (_tcsicmp("{\n", data.substr(0, 2).c_str()) != 0)
+		return false;
+
+	if (_tcsicmp("\n}\n", data.substr(data.size() - 3, 3).c_str()) != 0)
+		return false;
+
+	// 并返回去掉花括号的内容;
+	data = data.substr(2, data.size() - 5);
+
+	return true;
+}
+
+bool CRedRatProcess::StartApp(LPCTSTR lpAppDir, LPCTSTR lpSignalXml, DWORD dwPort)
+{
+	if (!lpAppDir || !PathFileExists(lpAppDir))
+		return false;
+
+	if ( IsAppRunning(lpAppDir) != 0)
+		return true;
+
+	// 启动应用程序;
+	TCHAR szParameters[256] = {0};
+	_stprintf_s(szParameters, APP_CMD_LINE, lpSignalXml, dwPort);
+	//ShellExecute(NULL, "open", pszExePath, NULL, NULL, SW_SHOWNORMAL);
+	SHELLEXECUTEINFO sei;
+	memset(&sei, 0, sizeof(SHELLEXECUTEINFO));
+	sei.cbSize = sizeof(SHELLEXECUTEINFO);
+	sei.hwnd = NULL;
+	// 普通打开方式:open;若想以管理员身份运行:runas
+	sei.lpVerb = _T("runas");
+	//sei.fMask = SEE_MASK_NOCLOSEPROCESS;//不设置,则使用默认值;
+	sei.lpFile = lpAppDir;
+	sei.lpParameters = szParameters;
+	sei.lpDirectory = NULL;
+#ifdef _DEBUG
+	sei.nShow = SW_SHOWNORMAL;
+#else
+	sei.nShow = SW_HIDE;
+#endif
+	sei.hInstApp = NULL;
+
+	if (!ShellExecuteEx(&sei))
+	{
+		DWORD dw = GetLastError();
+		return false;
+	}
+
+	if (sei.hProcess)
+		CloseHandle(sei.hProcess);
+
+	return true;
+}
+
+
+DWORD CRedRatProcess::IsAppRunning(LPCTSTR lpszAppDir)
+{
+	if (!lpszAppDir || !PathFileExists(lpszAppDir))
+		return 0;
+
+	std::string strAppDir = lpszAppDir;
+	int nIndex = strAppDir.find('/');
+	while (nIndex != std::string::npos)
+	{
+		strAppDir.replace(nIndex, 1, _T("\\"));
+		nIndex = strAppDir.find('/');
+	}
+	nIndex = strAppDir.find_last_of(_T('\\'));
+	if (nIndex != std::string::npos)
+		strAppDir = strAppDir.substr(nIndex + 1);
+
+	DWORD dwProcessID = 0;
+	PROCESSENTRY32 pe32 = { 0 };
+
+	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	if (hProcessSnap == NULL)
+	{
+		Global::WriteTextLog(_T("获取进程快照失败:%ld"), GetLastError());
+		return 0;
+	}
+	pe32.dwSize = sizeof(PROCESSENTRY32);
+
+	if (Process32First(hProcessSnap, &pe32))
+	{
+		do
+		{
+			// szExeFile只是文件名,不知道是否只有win10才这样;
+			if (_tcsicmp(strAppDir.c_str(), pe32.szExeFile) == 0)
+			{
+				m_dwCurAppId = dwProcessID = pe32.th32ProcessID;
+				break;
+			}
+		} while (Process32Next(hProcessSnap, &pe32));
+	}
+	CloseHandle(hProcessSnap);
+
+	return dwProcessID;
+}
+
+bool CRedRatProcess::CloseApp(DWORD dwAppId)
+{
+	m_dwCurAppId = GetProcessId();
+	if (dwAppId == 0)
+		dwAppId = m_dwCurAppId;
+
+	if (dwAppId == 0)
+		return true;
+
+	HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwAppId);
+	if (hProcess == NULL)
+	{
+		Global::WriteTextLog(_T("打开进程失败:%ld"), GetLastError());
+		return false;
+	}
+
+	DWORD dwError;
+	if (!TerminateProcess(hProcess, 0))
+	{
+		dwError = GetLastError();
+		CloseHandle(hProcess);
+		hProcess = NULL;
+		return false;
+	}
+
+	// 等待进程结束响应;
+	if (WAIT_OBJECT_0 != WaitForSingleObject(hProcess, INFINITE))
+	{
+		CloseHandle(hProcess);
+		return false;
+	}
+
+	CloseHandle(hProcess);
+	hProcess = NULL;
+
+	return true;
+}
+
+DWORD CRedRatProcess::GetProcessId(std::string strApp)
+{
+	DWORD dwProcessID = 0;
+	PROCESSENTRY32 pe32 = { 0 };
+
+	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	if (hProcessSnap == NULL)
+	{
+		Global::WriteTextLog(_T("获取进程快照失败:%ld"), GetLastError());
+		return 0;
+	}
+	pe32.dwSize = sizeof(PROCESSENTRY32);
+
+	if (Process32First(hProcessSnap, &pe32))
+	{
+		do
+		{
+			// szExeFile只是文件名,不知道是否只有win10才这样;
+			if (_tcsicmp(strApp.c_str(), pe32.szExeFile) == 0)
+			{
+				m_dwCurAppId = dwProcessID = pe32.th32ProcessID;
+				break;
+			}
+		} while (Process32Next(hProcessSnap, &pe32));
+	}
+	CloseHandle(hProcessSnap);
+
+	return dwProcessID;
+}
+
+bool CRedRatProcess::getDeviceNameList()
+{
+	return getDeviceNameList(m_vtDevices);
+}
+
+bool CRedRatProcess::getDeviceNameList(std::vector<std::string>& vtDevice)
+{
+	vtDevice.clear();
+	std::string data;
+	if (!Send("hubquery=\"list redrats\"\n", data))
+		return false;
+
+	if (!checkEOM(data))
+		return false;
+
+	std::string dev;
+	int npos = -1;
+	while (true)
+	{
+		npos = data.find_first_of('\n');
+		if (npos == std::string::npos)
+			break;
+
+		// 去除方括号;
+		fun_dev(vtDevice, data.substr(0, npos));
+		data = data.substr(npos+1);
+	}
+	fun_dev(vtDevice, data);
+
+	// 第一个设备给当前设备;
+	if (vtDevice.size())
+	{
+		m_strCurDevice = *vtDevice.begin();
+	}
+
+	return true;
+}
+
+bool CRedRatProcess::getDatasetNameList()
+{
+	return getDatasetNameList(m_vtDataset);
+}
+
+bool CRedRatProcess::getDatasetNameList(std::vector<std::string>& vtDataset)
+{
+	vtDataset.clear();
+	std::string data;
+	if (!Send("hubquery=\"list datasets\"\n", data))
+		return false;
+
+	if (!checkEOM(data))
+		return false;
+
+	int npos = -1;
+	while (true)
+	{
+		npos = data.find_first_of('\n');
+		if (npos == std::string::npos)
+			break;
+		vtDataset.push_back(data.substr(0, npos));
+		data = data.substr(npos + 1);
+	}
+	vtDataset.push_back(data);
+
+	// 第一个设备给当前设备;
+	if (vtDataset.size())
+	{
+		m_strCurDataset = *vtDataset.begin();
+	}
+
+	return true;
+}
+
+bool CRedRatProcess::loadSignalDataSet(std::string file)
+{
+	std::string data;
+	std::string send_data = "hubquery=\"load ir-file\",file=\"";
+	send_data.append(file);
+	send_data.append("\"\n");
+	// 加载数据集xml文件,以前的会被删除;
+	if (!Send(send_data, data))
+		return false;
+
+	if (_tcsicmp(data.c_str(), _T("OK\n")) == 0)
+	{
+		m_strCurDataset.clear();
+		getDatasetNameList();
+		return true;
+	}
+
+	return false;
+}
+
+bool CRedRatProcess::addSignalDataSet(std::string file)
+{
+	std::string data;
+	std::string send_data = "hubquery=\"add ir-file\",file=\"";
+	send_data.append(file);
+	send_data.append("\"\n");
+	// 添加信息数据集,同名会被覆盖;
+	if (!Send(send_data, data))
+		return false;
+
+	return !_tcsicmp(data.c_str(), _T("OK\n"));
+}
+// 
+// bool CRedRatProcess::getSignalsName(std::string dataset)
+// {
+// 	return getSignalsName(m_vtSignals, dataset);
+// }
+
+bool CRedRatProcess::getSignalsName(std::vector<std::string>& vtSignals, std::string dataset)
+{
+	std::string data;
+	std::string send_data = "hubquery=\"list signals in dataset\",dataset=\"";
+	if (dataset.size() == 0)
+	{// 加载默认;
+		if (m_strCurDataset.size() == 0)
+			getDatasetNameList();
+
+		dataset = m_strCurDataset;
+	}
+
+	if (dataset.size() == 0)
+		return false;
+
+	send_data.append(dataset);
+	send_data.append("\"\n");
+	if (!Send(send_data, data))
+		return false;
+
+	if (!checkEOM(data))
+		return false;
+
+	int npos = -1;
+	while (true)
+	{
+		npos = data.find_first_of('\n');
+		if (npos == std::string::npos)
+			break;
+		vtSignals.push_back(data.substr(0, npos));
+		data = data.substr(npos + 1);
+	}
+	vtSignals.push_back(data);
+
+	return true;
+}
+
+std::string CRedRatProcess::getSignalsName(std::string dataset /* = "" */)
+{
+	std::string data;
+	std::string send_data = "hubquery=\"list signals in dataset\",dataset=\"";
+	if (dataset.size() == 0)
+	{// 加载默认;
+		if (m_strCurDataset.size() == 0)
+			getDatasetNameList();
+
+		dataset = m_strCurDataset;
+	}
+
+	if (dataset.size() == 0)
+	{
+		return data;
+	}
+
+	send_data.append(dataset);
+	send_data.append("\"\n");
+	if (!Send(send_data, data))
+	{
+		return std::string();
+	}
+
+	if (!checkEOM(data))
+	{
+		return std::string();
+	}
+
+	return data;
+}
+
+bool CRedRatProcess::sendSignal(std::string signal, int send_times, int sleep_time)
+{
+	GET_IRC_DATA;
+
+	std::string data;
+	TCHAR szSendSignal[256] = { 0 };
+	_stprintf_s(szSendSignal, SEND_SG_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signal.c_str());
+	for (; send_times > 0; send_times--)
+	{
+		if (!Send(szSendSignal, data))
+			return false;
+
+		if (_tcsicmp(data.c_str(), _T("OK\n")))
+			return false;
+
+		Sleep(sleep_time);
+	}
+
+	return true;
+}
+
+bool CRedRatProcess::sendSignals(const char(*signals)[10], int nCount, int sleep_time)
+{
+	GET_IRC_DATA;
+
+	std::string data;
+	TCHAR szSendSignal[256] = { 0 };
+	for (int i = 0; i < nCount; i++)
+	{
+		//_stprintf_s(szSendSignal, SEND_SG_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signals[i]);
+		_stprintf_s(szSendSignal, SEND_SG_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signals++);
+		if (!Send(szSendSignal, data))
+			return false;
+
+		if (_tcsicmp(data.c_str(), _T("OK\n")))
+			return false;
+
+		Sleep(sleep_time);
+	}
+
+	return true;
+}
+
+bool CRedRatProcess::sendSignals(std::string signals[], int nCount, int sleep_time)
+{
+	GET_IRC_DATA;
+
+	std::string data;
+	TCHAR szSendSignal[256] = { 0 };
+	for (int i = 0; i < nCount; i++)
+	{
+		//_stprintf_s(szSendSignal, SEND_SG_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signals[i].c_str());
+		_stprintf_s(szSendSignal, SEND_SG_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), (*signals++).c_str());
+		if (!Send(szSendSignal, data))
+			return false;
+
+		if (_tcsicmp(data.c_str(), _T("OK\n")))
+			return false;
+
+		Sleep(sleep_time);
+	}
+
+	return true;
+}
+
+bool CRedRatProcess::sendSignals(std::vector<std::string>& vtSignals, int sleep_time)
+{
+	GET_IRC_DATA;
+
+	std::string data;
+	TCHAR szSendSignal[256] = { 0 };
+	for (std::vector<std::string>::iterator signal = vtSignals.begin(); signal != vtSignals.end(); signal++)
+	{
+		_stprintf_s(szSendSignal, SEND_SG_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signal->c_str());
+		if (!Send(szSendSignal, data))
+			return false;
+
+		if (_tcsicmp(data.c_str(), _T("OK\n")))
+			return false;
+
+		Sleep(sleep_time);
+	}
+
+	return true;
+}
+
+bool CRedRatProcess::sendRepeatsSignal(std::string signal, int repeat_time)
+{
+	GET_IRC_DATA;
+
+	std::string data;
+	TCHAR szSendSignal[256] = { 0 };
+	_stprintf_s(szSendSignal, SEND_SG_REP_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signal.c_str(), repeat_time);
+
+	if (!Send(szSendSignal, data))
+	{
+		Global::WriteTextLog(_T("发送重复信号失败:%s"), data.c_str());
+		return false;
+	}
+
+	if (!_tcsicmp(data.c_str(), _T("OK\n")))
+		return true;
+
+	Global::WriteTextLog(_T("发送重复信号失败:%s"), data.c_str());
+	return false;
+}
+
+bool CRedRatProcess::sendDurationSignal(std::string signal, int duration_time)
+{
+	GET_IRC_DATA;
+
+	std::string data;
+	TCHAR szSendSignal[256] = { 0 };
+	_stprintf_s(szSendSignal, SEND_SG_DUR_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signal.c_str(), duration_time);
+
+	if (!Send(szSendSignal, data))
+		return false;
+
+	return !_tcsicmp(data.c_str(), _T("OK\n"));
+}
+
+bool CRedRatProcess::sendBothSignal(std::string signal, int repeat_time, int duration_time)
+{
+	GET_IRC_DATA;
+
+	std::string data;
+	TCHAR szSendSignal[256] = { 0 };
+	_stprintf_s(szSendSignal, SEND_SG_BOTH_FORMAT, m_strCurDevice.c_str(), m_strCurDataset.c_str(), signal.c_str(), repeat_time, duration_time);
+
+	if (!Send(szSendSignal, data))
+		return false;
+
+	return !_tcsicmp(data.c_str(), _T("OK\n"));
+}
+

+ 58 - 0
IRControl_08/IRControl/RedRatProcess.h

@@ -0,0 +1,58 @@
+#pragma once
+
+#include "TCPClient.h"
+
+class CRedRatProcess: public CTCPClient
+{
+public:
+	CRedRatProcess(void);
+	~CRedRatProcess(void);
+
+protected:
+	bool checkEOM(std::string& data);
+
+private:
+	// 只能运行一个红老鼠进程;
+	static DWORD m_dwCurAppId;
+	std::string m_strCurDevice;
+	std::string m_strCurDataset;
+	std::vector<std::string> m_vtDevices;
+	std::vector<std::string> m_vtDataset;
+	std::vector<std::string> m_vtSignals;
+
+	// 外部程序接口;
+public:
+	static bool StartApp(LPCTSTR lpAppDir, LPCTSTR lpSignalXml, DWORD dwPort = 40000);
+	static DWORD IsAppRunning(LPCTSTR lpszAppDir);
+	static bool CloseApp(DWORD dwAppId = 0);
+	static DWORD GetProcessId(std::string strApp = "RedRatHubCmd.exe");
+
+	// 红老鼠接口;
+public:
+	// 获取设备列表;
+	bool getDeviceNameList();
+	bool getDeviceNameList(std::vector<std::string>& vtDevice);
+	// 设置信号数据集;
+	void SelectDataset(std::string dataset) { m_strCurDataset = dataset; }
+	// 获取数据集列表;
+	bool getDatasetNameList();
+	bool getDatasetNameList(std::vector<std::string>& vtDataset);
+	// 加载信号数据集xml文件,将会删除以前所有加载过的xml文件;
+	bool loadSignalDataSet(std::string file);
+	// 添加信号数据集xml文件, 相同数据集名称的将会被覆盖
+	bool addSignalDataSet(std::string file);
+	// 获取指定数据集信号名称;
+	//bool getSignalsName(std::string dataset = "");
+	bool getSignalsName(std::vector<std::string>& vtSignals, std::string dataset = "");
+	std::string getSignalsName(std::string dataset = "");
+	// 发送单个信号;
+	bool sendSignal(std::string signal, int send_times = 1, int sleep_time = 1000);
+	// 发送多个信号;
+	bool sendSignals(const char(*signals)[10], int nCount, int sleep_time = 1000);
+	bool sendSignals(std::string signals[], int nCount, int sleep_time = 1000);
+	bool sendSignals(std::vector<std::string>& vtSignals, int sleep_time = 1000);
+	// 重复发送;
+	bool sendRepeatsSignal(std::string signal, int repeat_time = 2);
+	bool sendDurationSignal(std::string signal, int duration_time = 1000);
+	bool sendBothSignal(std::string signal, int repeat_time = 2, int duration_time = 1000);
+};

+ 17 - 0
IRControl_08/IRControl/Resource.h

@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by IRControl.rc
+//
+
+#define IDS_APP_TITLE			103
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#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
+#endif
+#endif

+ 292 - 0
IRControl_08/IRControl/TCPClient.cpp

@@ -0,0 +1,292 @@
+#include "stdafx.h"
+#include "TCPClient.h"
+#include "CritSection.h"
+
+#define BUF_LEN 8192
+
+CTCPClient::CTCPClient()
+{
+	Global::Init();
+	m_socket = INVALID_SOCKET;
+	//m_sin = {0};
+	m_port = 0;
+}
+
+CTCPClient::~CTCPClient()
+{
+	DisConnect();
+	WSACleanup();
+}
+
+// 初始化WinSock 2.2
+bool CTCPClient::InitSocket()
+{
+	WSADATA wsaData;
+	return (NO_ERROR == WSAStartup(MAKEWORD(2, 2), &wsaData));
+}
+
+bool CTCPClient::Connect(std::string ip, int port)
+{
+	DisConnect();
+	m_ip = ip;
+	m_port = port;
+	// 创建套接字;
+	m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (m_socket == INVALID_SOCKET)
+	{
+		Global::WriteTextLog(_T("创建套接字失败:%d"), WSAGetLastError());
+		return false;
+	}
+
+	// 连接服务器;
+	m_sin.sin_family = AF_INET;
+	m_sin.sin_port = htons(port);
+	if (-1 == inet_pton(AF_INET, ip.c_str(), &m_sin.sin_addr))
+	{
+		Global::WriteTextLog(_T("地址转换失败:%d"), WSAGetLastError());
+		return false;
+	} 
+
+	if (connect(m_socket, (LPSOCKADDR)& m_sin, sizeof(m_sin)) == SOCKET_ERROR)
+	{
+		Global::WriteTextLog(_T("连接服务端失败:%d"), WSAGetLastError());
+		closesocket(m_socket);
+		return false;
+	}
+
+	// 设置收发超时;
+	int nNetTimeout = 3000; //1秒
+	//发送时限
+	setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)& nNetTimeout, sizeof(int));
+	//接收时限
+	setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)& nNetTimeout, sizeof(int));
+	
+	// 设置缓存大小;
+	int bufSize = BUF_LEN;
+	setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char*)& bufSize, sizeof(int));
+	setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char*)& bufSize, sizeof(int));
+
+	return true;
+}
+
+bool CTCPClient::SelectConnect(std::string ip, int port, int time_out)
+{
+	DisConnect();
+	m_ip = ip;
+	m_port = port;
+	// 设置收发超时;
+	int nNetTimeout = 3000; //1秒
+
+	// 创建套接字;
+	m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (m_socket == INVALID_SOCKET)
+	{
+		Global::WriteTextLog(_T("创建套接字失败:%d"), WSAGetLastError());
+		return false;
+	}
+
+	// 连接服务器;
+	m_sin.sin_family = AF_INET;
+	m_sin.sin_port = htons(port);
+	if (-1 == inet_pton(AF_INET, ip.c_str(), &m_sin.sin_addr))
+	{
+		Global::WriteTextLog(_T("地址转换失败:%d"), WSAGetLastError());
+		return false;
+	}
+
+	// 首先设置socket为非阻塞模式;
+	unsigned long um = 1;
+	int nRet = ioctlsocket(m_socket, FIONBIO, &um);
+	if (nRet != NO_ERROR)
+	{
+		// 设置失败;
+		Global::WriteTextLog(_T("设置非阻塞模式失败:%d"), WSAGetLastError());
+		return false;
+	}
+
+	bool bRet = false;
+	nRet = connect(m_socket, (LPSOCKADDR)& m_sin, sizeof(m_sin));
+	if (nRet == NO_ERROR)
+	{
+		bRet = true;
+		goto end;
+	}
+
+	// 因为是非阻塞的,这个时候错误码应该是WSAEWOULDBLOCK,Linux下是EINPROGRESS
+	if (nRet < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
+	{
+		bRet = false;
+		goto end;
+	}
+
+	TIMEVAL Timeout;
+	Timeout.tv_sec = time_out;
+	Timeout.tv_usec = 0;
+
+	// 检测是否连接成功;
+	fd_set write, err;
+	FD_ZERO(&write);
+	FD_ZERO(&err);
+	FD_SET(m_socket, &write);
+	FD_SET(m_socket, &err);
+
+#if 0
+	nRet = select(0, NULL, &write, &err, &Timeout);
+	if (FD_ISSET(m_socket, &write))
+	{
+		bRet = true;
+	}
+#else
+	nRet = select(0, NULL, &write, &err, &Timeout);
+	if (nRet == 0)
+	{
+		Global::WriteTextLog(_T("连接服务端超时"));
+	}
+	else if (nRet < 0)
+	{
+		Global::WriteTextLog(_T("连接服务端出错:%d"), WSAGetLastError());
+	}
+	else
+	{
+		int nError = -1;
+		int nLen = sizeof(int);
+		// 使用getsockopt来检查套接字是否异常;
+		getsockopt(m_socket, SOL_SOCKET, SO_ERROR, (char*)& nError, &nLen);
+		if (nError == 0)
+		{
+			bRet = true;
+		}
+		else
+		{
+			bRet = false;
+			Global::WriteTextLog(_T("连接服务端出错:%d"), nError);
+		}
+	}
+#endif
+
+end:
+	um = 0;
+	ioctlsocket(m_socket, FIONBIO, &um);
+	if (!bRet)
+	{
+		Global::WriteTextLog(_T("连接服务端失败:%d"), WSAGetLastError());
+		closesocket(m_socket);
+	}
+	else {
+		//发送时限
+		setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)& nNetTimeout, sizeof(int));
+		//接收时限
+		setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)& nNetTimeout, sizeof(int));
+		// 设置缓存大小;
+		int bufSize = BUF_LEN;
+		setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char*)& bufSize, sizeof(int));
+		setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char*)& bufSize, sizeof(int));
+	}
+
+	return bRet;
+}
+
+void CTCPClient::DisConnect()
+{
+	if (m_socket != INVALID_SOCKET)
+	{
+		shutdown(m_socket, SD_BOTH);
+		closesocket(m_socket);
+	}
+}
+
+bool CTCPClient::Send(std::string s_data, std::string &r_data)
+{
+	static ThreadSection _critSection;
+	AutoThreadSection aSection(&_critSection);
+
+	r_data.clear();
+	if (m_socket == INVALID_SOCKET)
+	{
+		Global::WriteTextLog(_T("SOCKET未创建, 请创建并连接服务器"));
+		return false;
+	}
+
+	// 向服务器发送数据;
+	int nRet = send(m_socket, s_data.c_str(), s_data.size(), 0);
+	if (nRet < 0 )
+	{
+		DWORD dwError = WSAGetLastError();
+		Global::WriteTextLog(_T("发送数据失败:%d"), dwError);
+		ReConnect(dwError);
+		return false;
+	}
+
+	// 接收服务器返回的数据;
+	char recbuf[64] = { 0 };
+	for (int i = 0; i < 10; i++ )
+	{
+		memset(recbuf, 0, 64);
+		nRet = recv(m_socket, recbuf, 64, 0);
+		if (nRet < 0)
+		{
+			DWORD dwError = WSAGetLastError();
+			Global::WriteTextLog(_T("接收数据失败:%d"), dwError);
+			ReConnect(dwError);
+			return false;
+		}
+
+		// 存储结果;
+		if ( nRet > 0)		
+			r_data.append(recbuf, nRet);
+
+		if ( checkEOM(r_data) || !_tcsicmp(r_data.c_str(), _T("OK\n")) )
+			break;
+	}
+
+	return true;
+}
+
+void CTCPClient::ReConnect(DWORD dwError)
+{
+	bool bReConnect = false;
+	// send/recv error;
+	if (dwError == WSAENETRESET)
+	{
+		bReConnect = true;
+		Global::WriteTextLog(_T("由于保持活动活动在操作正在进行时检测到故障,因此连接已断开。"));
+	}
+	else if (dwError == WSAECONNABORTED)
+	{
+		bReConnect = true;
+		Global::WriteTextLog(_T("由于超时或其他故障,虚电路终止。应用程序应关闭套接字,因为它不再可用。"));
+	}
+	else if (dwError == WSAECONNRESET)
+	{
+		bReConnect = true;		
+		Global::WriteTextLog(_T("虚拟电路由远程端执行硬关闭或中止关闭重置。对于UDP套接字,远程主机无法传送先前发送的UDP数据报,并使用“端口无法访问”ICMP数据包进行响应。应用程序应关闭套接字,因为它不再可用。"));
+	}
+	else if (dwError == WSAETIMEDOUT)
+	{//由于网络故障或另一端的系统在没有通知的情况下发生故障,连接已被丢弃。
+		bReConnect = true;
+		Global::WriteTextLog(_T("由于超时或其他故障,虚电路终止。应用程序应关闭套接字,因为它不再可用。"));
+	}
+
+	if ( bReConnect )
+	{
+		DisConnect();
+		Connect(m_ip, m_port);
+	}
+}
+
+bool CTCPClient::checkEOM(std::string& data)
+{
+	if (data.size() < 5)
+		return false;
+
+	if (_tcsicmp("{\n", data.substr(0, 2).c_str()) != 0)
+		return false;
+
+	if (_tcsicmp("\n}\n", data.substr(data.size() - 3, 3).c_str()) != 0)
+		return false;
+
+	// 并返回去掉花括号的内容;
+	//data = data.substr(2, data.size() - 5);
+
+	return true;
+}

+ 48 - 0
IRControl_08/IRControl/TCPClient.h

@@ -0,0 +1,48 @@
+#ifndef __TCP_CLIENT_HEADER__
+#define __TCP_CLIENT_HEADER__
+
+#include "Global.h"
+// winsocket库;
+#include <Ws2tcpip.h>
+#pragma comment(lib,"Ws2_32.lib")
+
+#pragma once
+
+#ifdef IRCONTROL_EXPORTS
+#define IRCONTROL_API __declspec(dllexport)
+#else
+#define IRCONTROL_API __declspec(dllimport)
+#endif
+
+class IRCONTROL_API CTCPClient
+{
+public:
+	CTCPClient();
+	~CTCPClient();
+
+	// 初始化套接字库;
+	bool InitSocket();
+	// 连接服务器;
+	bool Connect(std::string ip, int port);
+	// 连接服务器;
+	bool SelectConnect(std::string ip, int port, int time_out = 3);
+	// 断开连接;
+	void DisConnect();
+	// 发送数据;
+	bool Send(std::string s_data, std::string &r_data);
+	// 重连;
+	void ReConnect(DWORD dwError = WSAENETRESET);
+protected:
+	bool checkEOM(std::string& data);
+private:
+	// 客户端套接字;
+	SOCKET m_socket;
+	// 客户端地址;
+	sockaddr_in m_sin;
+	// ip;
+	std::string m_ip;
+	// port;
+	int m_port;
+};
+
+#endif //__TCP_CLIENT_HEADER__

+ 8 - 0
IRControl_08/IRControl/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// IRControl.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用

+ 33 - 0
IRControl_08/IRControl/stdafx.h

@@ -0,0 +1,33 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include <afx.h>
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                     // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <iostream>
+// Windows 头文件:
+#include <windows.h>
+
+
+
+// TODO: 在此处引用程序需要的其他头文件

+ 24 - 0
IRControl_08/IRControl/targetver.h

@@ -0,0 +1,24 @@
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif