// stdafx.cpp : 只包括标准包含文件的源文件 // Demo.pch 将作为预编译头 // stdafx.obj 将包含预编译类型信息 #include "stdafx.h" // TODO: 在 STDAFX.H 中 // 引用任何所需的附加头文件,而不是在此文件中引用 VOID _dprintf(CHAR* pszStr, ...) { const int LOGLEN = 3072; 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"))); #elif _MSC_VER >= 1500 _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); #if _MSC_VER >= 1200 && _MSC_VER < 1500 _vsnprintf(szData + len, LOGLEN - len, pszStr, args); #elif _MSC_VER >= 1500 _vsntprintf_s(szData + len, LOGLEN - len, _TRUNCATE, pszStr, args); #endif va_end(args); if (szData[strlen(szData) - 1] != '\n') #if _MSC_VER >= 1200 && _MSC_VER < 1500 strcat(szData, "\n"); #elif _MSC_VER >= 1500 strcat_s(szData, "\n"); #endif OutputDebugStringA(szData); } bool parse_key(std::string &RetValue, std::string strLine, TCHAR *lpszText) { TCHAR szText[MAX_PATH] = {0}; TCHAR szValue[MAX_PATH] = {0}; // 去除空格; #if _MSC_VER > 1900 strLine.erase(std::remove_if(strLine.begin(), strLine.end(), [](unsigned char x) {return std::isspace(x); }), strLine.end()); //C++17 #else for (std::string::iterator it = strLine.begin(); it != strLine.end();) { !isspace(*it) ? it++ : it = it = strLine.erase(it); } #endif #if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0 if ( 2 == sscanf(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH) ) #else if ( 2 == _stscanf_s(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH) ) #endif { if ( _tcsstr(szText, lpszText) ) { RetValue = szValue; return true; } } return false; } // 计算时间; // 如: 100ms 100m 100s int pares_time_value(std::string strTime) { int nTimes = 0; #if _MSC_VER >= 1200 && _MSC_VER < 1500 if ( strstr(strTime.c_str(), _T("ms")) || strstr(strTime.c_str(), _T("MS"))) { nTimes = atol(strTime.c_str()); } else if (strstr(strTime.c_str(), _T("s")) || strstr(strTime.c_str(), _T("S"))) { nTimes = atol(strTime.c_str()) * 1000; } else if (strstr(strTime.c_str(), _T("m")) || strstr(strTime.c_str(), _T("M"))) { nTimes = atol(strTime.c_str()) * 6000; } else { // 不带单位或其他的,默认ms; nTimes = atol(strTime.c_str()); } #elif _MSC_VER >= 1500 if ( _tcsstr(strTime.c_str(), _T("ms")) || _tcsstr(strTime.c_str(), _T("MS"))) { nTimes = _tstol(strTime.c_str()); } else if (_tcsstr(strTime.c_str(), _T("s")) || _tcsstr(strTime.c_str(), _T("S"))) { nTimes = _tstol(strTime.c_str()) * 1000; } else if (_tcsstr(strTime.c_str(), _T("m")) || _tcsstr(strTime.c_str(), _T("M"))) { nTimes = _tstol(strTime.c_str()) * 6000; } else { // 不带单位或其他的,默认ms; nTimes = _tstol(strTime.c_str()); } #endif return nTimes; } int parse_cmd_param_from_file(TCHAR *file_name, std::vector &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; } } #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_key(cp.name, name, _T("Name")); parse_key(cp.head, head, _T("HeadCode")); parse_key(cp.code, code, _T("Command")); parse_key(cp.param, param, _T("CMDParam")); std::string value; parse_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_key(value, multicode, _T("MultiParams")); cp.bMulticode = !_tcsicmp(value.c_str(), _T("true")) ? true : false; parse_key(value, read_wait_time, _T("ReadWaitTime")); cp.read_wait_time = pares_time_value(value.c_str()); parse_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; } 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); } const unsigned short CRC16_TABLE[16] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF }; 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; } std::string HexStringToBytes(std::string strHex, const int &len /* = 3 */) { 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); #elif _MSC_VER >=1500 strBytes.push_back((char)TwoHexCharToInteger(strHex[i], strHex[i + 1])); #endif } return strBytes; } 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); #elif _MSC_VER >= 1500 _stprintf_s(szhex, "%02X%c", pbuffer[i], chSpace); #endif hex.append(szhex); } return hex.substr(0, hex.size() - 1); } 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]); #elif _MSC_VER >= 1500 _stprintf_s(szhex, "%02X", pbuffer[i]); #endif hex.append(szhex); } return hex; } std::string ByteToChars(byte b) { char szhex[3] = { 0 }; #if _MSC_VER >= 1200 && _MSC_VER < 1500 sprintf(szhex, "%02X", b); #elif _MSC_VER >= 1500 _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; } // 去除空格; std::string &trim(std::string &str) { #if 0 int nIndex = 0; while ((nIndex = str.find_first_of(' ')) != std::string::npos) str.erase(nIndex, 1); return str; #endif #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); } #elif _MSC_VER >= 1600 str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char x) {return std::isspace(x); }), str.end()); //C++17 #endif return str; } std::string PackingCommand(CommandParam &cmdPara, std::string data, const int &dataLen) { // Tag:[命令头][全命令长度][命令码]<命令码参数><附加数据>[crc1][crc2] std::string command; // 命令头标识位; command.append(HexStringToBytes(cmdPara.head, 2).c_str(), cmdPara.head.size() / 2); // 命令码; command.append(HexStringToBytes(cmdPara.code, 2).c_str(), cmdPara.code.size() / 2); // 命令码参数; command.append(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 = 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); return command; } #define NoneOptLen 5 void TheFirstPart(CommandParam& cmdPara, std::string data, const int& dataLen) { if (data.size() == NoneOptLen) { if (data[0] == cmdPara._rtnCode) { // 长度; int nPackageLen = data[1]; if (nPackageLen != NoneOptLen) { _dprintf("None长度错误:%ld", data[1]); return; } // 执行状态; cmdPara._rtnStatus = data[2]; _dprintf(_T("rtnStatus=%02X"), cmdPara._rtnStatus); // 校验crc; unsigned short usCRCValue = CRC16Calculate((unsigned char*)data.data(), nPackageLen - 2); if (((usCRCValue >> 8) & 0xFF) != (unsigned char)data[nPackageLen - 2] || (usCRCValue & 0xFF) != (unsigned char)data[nPackageLen - 1]) { _dprintf("CRC校验错误:计算[%02% %02X] != 接收[%02X %02X]", (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, data[nPackageLen - 2], data[nPackageLen - 1]); return; } } else { _dprintf("返回码错误:%02X", data[0]); } } else { _dprintf("长度对不上:Option.None"); } } void TheSecondPart(CommandParam& cmdPara, std::string data, const int& dataLen) { } void ParseResultString(CommandParam& cmdPara, std::string data, const int& dataLen) { // Tag:[返回头][全数据长度][返回码]<返回码子项><附加数据>[crc1][crc2] if ( data.size() < 5) { return; } byte rtnCode = 0xAB; std::string head = cmdPara.head.substr(0, 2); 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; } int nTakenLen = 0; // 已取出的长度; unsigned short usCRCValue; // CRC验证值; // 一个完整的包段; int nPackageLen = 0; std::string packaged; // None可以看作是第一段数据包; if ( cmdPara.nOption == CMDOPT::CMDOPT_None ) { if ( data.size() == NoneOptLen) { if (data[0] == rtnCode) { if (data[1] == 0xFE) { // None中不应该出现,配置出错; _dprintf("类型配置错误:%02X %02X", data[0], data[1]); return; } // 长度; nPackageLen = data[1]; if (nPackageLen != NoneOptLen) { _dprintf("None长度错误:%ld", data[1]); return; } // 执行状态; // 校验crc; usCRCValue = CRC16Calculate((unsigned char*)data.data(), nPackageLen - 2); if (((usCRCValue >> 8) & 0xFF) != (unsigned char)data[nPackageLen - 2] || (usCRCValue & 0xFF) != (unsigned char)data[nPackageLen - 1]) { _dprintf("CRC校验错误:计算[%02% %02X] != 接收[%02X %02X]", (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, data[nPackageLen - 2], data[nPackageLen - 1]); return; } } else { _dprintf("返回码错误:%02X", data[0]); } } else { _dprintf("长度对不上:Option.None"); } } else if ( cmdPara.nOption == CMDOPT::CMDOPT_Get ) { } else if ( cmdPara.nOption == CMDOPT::CMDOPT_Set ) { } }