TCLCommand.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. #include "StdAfx.h"
  2. #include "TCLCommand.h"
  3. #define NoneOptLen 5
  4. TCLCommand::TCLCommand(bool bSync):CBaseSerial(bSync ? 0 : FILE_FLAG_OVERLAPPED)
  5. {
  6. }
  7. TCLCommand::~TCLCommand(void)
  8. {
  9. m_vtExternalCMDParams.clear();
  10. m_vtInternalCMDParams.clear();
  11. }
  12. int TCLCommand::pares_time_value(std::string strTime)
  13. {
  14. int nTimes = 0;
  15. #if _MSC_VER >= 1200 && _MSC_VER < 1500
  16. if (strstr(strTime.c_str(), _T("ms")) || strstr(strTime.c_str(), _T("MS")))
  17. {
  18. nTimes = atol(strTime.c_str());
  19. }
  20. else if (strstr(strTime.c_str(), _T("s")) || strstr(strTime.c_str(), _T("S")))
  21. {
  22. nTimes = atol(strTime.c_str()) * 1000;
  23. }
  24. else if (strstr(strTime.c_str(), _T("m")) || strstr(strTime.c_str(), _T("M")))
  25. {
  26. nTimes = atol(strTime.c_str()) * 6000;
  27. }
  28. else
  29. {
  30. // 不带单位或其他的,默认ms;
  31. nTimes = atol(strTime.c_str());
  32. }
  33. #elif _MSC_VER >= 1500
  34. if (_tcsstr(strTime.c_str(), _T("ms")) || _tcsstr(strTime.c_str(), _T("MS")))
  35. {
  36. nTimes = _tstol(strTime.c_str());
  37. }
  38. else if (_tcsstr(strTime.c_str(), _T("s")) || _tcsstr(strTime.c_str(), _T("S")))
  39. {
  40. nTimes = _tstol(strTime.c_str()) * 1000;
  41. }
  42. else if (_tcsstr(strTime.c_str(), _T("m")) || _tcsstr(strTime.c_str(), _T("M")))
  43. {
  44. nTimes = _tstol(strTime.c_str()) * 6000;
  45. }
  46. else
  47. {
  48. // 不带单位或其他的,默认ms;
  49. nTimes = _tstol(strTime.c_str());
  50. }
  51. #endif
  52. return nTimes;
  53. }
  54. bool TCLCommand::parse_pair_key(std::string& RetValue, std::string strLine, TCHAR* lpszText)
  55. {
  56. TCHAR szText[MAX_PATH] = { 0 };
  57. TCHAR szValue[MAX_PATH] = { 0 };
  58. // 去除空格;
  59. #if _MSC_VER > 1900
  60. strLine.erase(std::remove_if(strLine.begin(), strLine.end(), [](unsigned char x) {return std::isspace(x); }), strLine.end()); //C++17
  61. #else
  62. for (std::string::iterator it = strLine.begin(); it != strLine.end();) {
  63. !isspace(*it) ? it++ : it = it = strLine.erase(it);
  64. }
  65. #endif
  66. #if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0
  67. if (2 == sscanf(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH))
  68. #else
  69. if (2 == _stscanf_s(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH))
  70. #endif
  71. {
  72. if (_tcsstr(szText, lpszText)) {
  73. RetValue = szValue;
  74. return true;
  75. }
  76. }
  77. return false;
  78. }
  79. int TCLCommand::parse_cmds_from_file(TCHAR* file_name, std::vector<CommandParam>& vtCommandParams)
  80. {
  81. TCHAR buf[MAX_PATH] = { 0 };
  82. TCHAR name[MAX_PATH] = { 0 };
  83. TCHAR option[MAX_PATH] = { 0 };
  84. TCHAR head[MAX_PATH] = { 0 };
  85. TCHAR code[MAX_PATH] = { 0 };
  86. TCHAR param[MAX_PATH] = { 0 };
  87. TCHAR multicode[MAX_PATH] = { 0 };
  88. TCHAR cmd_wait_time[MAX_PATH] = { 0 };
  89. TCHAR read_wait_time[MAX_PATH] = { 0 };
  90. int ret = -1;
  91. FILE* fp = NULL;
  92. if (!file_name || file_name[0] == '\0')
  93. return ret;
  94. fp = fopen(file_name, "r");
  95. if (!fp)
  96. goto EXIT;
  97. while ((fgets((char*)buf, MAX_PATH, fp) != NULL)) {
  98. int tmp_len = 0;
  99. tmp_len = _tcslen(buf);
  100. if (tmp_len >= 1) {
  101. if (buf[tmp_len - 1] == '\r' || buf[tmp_len - 1] == '\n')
  102. buf[tmp_len - 1] = 0;
  103. if (tmp_len >= 2) {
  104. if (buf[tmp_len - 2] == '\r' || buf[tmp_len - 2] == '\n')
  105. buf[tmp_len - 2] = 0;
  106. }
  107. }
  108. #if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0
  109. if (sscanf(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, option, head, code, param, multicode, read_wait_time, cmd_wait_time) == 8)
  110. #elif _MSC_VER >= 1500
  111. //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) // 等价下面;
  112. 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)
  113. #endif
  114. {
  115. CommandParam cp;
  116. parse_pair_key(cp.name, name, _T("Name"));
  117. parse_pair_key(cp.head, head, _T("HeadCode"));
  118. parse_pair_key(cp.code, code, _T("Command"));
  119. parse_pair_key(cp.param, param, _T("CMDParam"));
  120. std::string value;
  121. parse_pair_key(value, option, _T("Option"));
  122. if (!_tcsicmp(value.c_str(), _T("None")))
  123. cp.nOption = CMDOPT_None;
  124. else if (!_tcsicmp(value.c_str(), _T("Get")))
  125. cp.nOption = CMDOPT_Get;
  126. else if (!_tcsicmp(value.c_str(), _T("Set")))
  127. cp.nOption = CMDOPT_Set;
  128. parse_pair_key(value, multicode, _T("MultiParams"));
  129. cp.bMulticode = !_tcsicmp(value.c_str(), _T("true")) ? true : false;
  130. parse_pair_key(value, read_wait_time, _T("ReadWaitTime"));
  131. cp.read_wait_time = pares_time_value(value.c_str());
  132. parse_pair_key(value, cmd_wait_time, _T("CMDWaitTime"));
  133. cp.cmd_wait_time = pares_time_value(value.c_str());
  134. cp.UpdateRtnCode();
  135. vtCommandParams.push_back(cp);
  136. }
  137. }
  138. ret = 0;
  139. EXIT:
  140. if (fp)
  141. fclose(fp);
  142. return ret;
  143. }
  144. void TCLCommand::parse_cmds_from_string(std::string str, std::vector<CommandParam>& vtCommandParams)
  145. {
  146. int nPos(0);
  147. TCHAR buf[MAX_PATH] = { 0 };
  148. TCHAR name[MAX_PATH] = { 0 };
  149. TCHAR option[MAX_PATH] = { 0 };
  150. TCHAR head[MAX_PATH] = { 0 };
  151. TCHAR code[MAX_PATH] = { 0 };
  152. TCHAR param[MAX_PATH] = { 0 };
  153. TCHAR multicode[MAX_PATH] = { 0 };
  154. TCHAR cmd_wait_time[MAX_PATH] = { 0 };
  155. TCHAR read_wait_time[MAX_PATH] = { 0 };
  156. do
  157. {
  158. memset(buf, 0, MAX_PATH);
  159. int nPos1 = str.find_first_of('\r');
  160. int nPos2 = str.find_first_of('\n');
  161. if ( std::string::npos != nPos1 && std::string::npos != nPos2 ) {
  162. nPos = nPos1 > nPos2 ? nPos1 : nPos2;
  163. _stprintf_s(buf, _T("%s"), str.substr(0, nPos - 1).c_str());
  164. str = str.substr(nPos+1);
  165. }
  166. else if ( std::string::npos != nPos1 ) {
  167. _stprintf_s(buf, _T("%s"), str.substr(0, nPos1 - 1).c_str());
  168. str = str.substr(nPos + 1);
  169. }
  170. else if ( std::string::npos != nPos2 ) {
  171. _stprintf_s(buf, _T("%s"), str.substr(0, nPos2 - 1).c_str());
  172. str = str.substr(nPos + 1);
  173. }
  174. else {
  175. _stprintf_s(buf, _T("%s"), str.c_str());
  176. str.clear();
  177. }
  178. #if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0
  179. if (sscanf(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, option, head, code, param, multicode, read_wait_time, cmd_wait_time) == 8)
  180. #elif _MSC_VER >= 1500
  181. //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) // 等价下面;
  182. 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)
  183. #endif
  184. {
  185. CommandParam cp;
  186. parse_pair_key(cp.name, name, _T("Name"));
  187. parse_pair_key(cp.head, head, _T("HeadCode"));
  188. parse_pair_key(cp.code, code, _T("Command"));
  189. parse_pair_key(cp.param, param, _T("CMDParam"));
  190. std::string value;
  191. parse_pair_key(value, option, _T("Option"));
  192. if (!_tcsicmp(value.c_str(), _T("None")))
  193. cp.nOption = CMDOPT_None;
  194. else if (!_tcsicmp(value.c_str(), _T("Get")))
  195. cp.nOption = CMDOPT_Get;
  196. else if (!_tcsicmp(value.c_str(), _T("Set")))
  197. cp.nOption = CMDOPT_Set;
  198. parse_pair_key(value, multicode, _T("MultiParams"));
  199. cp.bMulticode = !_tcsicmp(value.c_str(), _T("true")) ? true : false;
  200. parse_pair_key(value, read_wait_time, _T("ReadWaitTime"));
  201. cp.read_wait_time = pares_time_value(value.c_str());
  202. parse_pair_key(value, cmd_wait_time, _T("CMDWaitTime"));
  203. cp.cmd_wait_time = pares_time_value(value.c_str());
  204. cp.UpdateRtnCode();
  205. vtCommandParams.push_back(cp);
  206. }
  207. } while (str.size());
  208. }
  209. bool TCLCommand::GetCommandParams(std::string name, CommandParam& cmdPara)
  210. {
  211. bool bget = false;
  212. // 外部优先;
  213. for (std::vector<CommandParam>::iterator it = m_vtExternalCMDParams.begin(); it != m_vtExternalCMDParams.end(); it++ )
  214. {
  215. if ( !_tcsicmp(name.c_str(), it->name.c_str()) ) {
  216. bget = true;
  217. cmdPara = *it;
  218. break;
  219. }
  220. }
  221. if ( !bget )
  222. {
  223. for (std::vector<CommandParam>::iterator it = m_vtInternalCMDParams.begin(); it != m_vtInternalCMDParams.end(); it++ )
  224. {
  225. if ( !_tcsicmp(name.c_str(), it->name.c_str()) ) {
  226. bget = true;
  227. cmdPara = *it;
  228. }
  229. }
  230. }
  231. // 清除状态;
  232. cmdPara.Clean();
  233. return bget;
  234. }
  235. bool TCLCommand::TheFirstPart(CommandParam& cmdPara, std::string data)
  236. {
  237. if (data.size() == NoneOptLen) {
  238. if ((byte)data[0] == cmdPara._rtnCode) {
  239. // 长度;
  240. int nPacketLen = (byte)data[1];
  241. if (nPacketLen != NoneOptLen) {
  242. cmdPara._rtnError = utils::_dprintf("[%s] 返回数据长度错误:%ld", __FUNCTION__, (byte)data[1]);
  243. return false;
  244. }
  245. // 执行状态;
  246. cmdPara._rtnStatus = (byte)data[2];
  247. //utils::_dprintf(_T("[%s] rtnStatus=%02X"), __FUNCTION__, cmdPara._rtnStatus);
  248. // 校验crc;
  249. unsigned short usCRCValue = utils::CRC16Calculate((byte*)data.data(), nPacketLen - 2);
  250. if (((usCRCValue >> 8) & 0xFF) != (byte)data[nPacketLen - 2] || (usCRCValue & 0xFF) != (byte)data[nPacketLen - 1]) {
  251. cmdPara._rtnError = utils::_dprintf("[%s] CRC校验错误:计算[%02% %02X] != 接收[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
  252. return false;
  253. }
  254. }
  255. else {
  256. cmdPara._rtnError = utils::_dprintf("[%s] 返回码错误:%02X", __FUNCTION__, (byte)data[0]);
  257. return false;
  258. }
  259. }
  260. else {
  261. cmdPara._rtnError = utils::_dprintf("[%s] 返回数据长度错误", __FUNCTION__);
  262. return false;
  263. }
  264. return true;
  265. }
  266. bool TCLCommand::TheSecondPart(CommandParam& cmdPara, std::string data)
  267. {
  268. // 数据起始位;
  269. int nDataPos = 0;
  270. // 数据包长度;
  271. int nPacketLen = 0;
  272. if ((byte)data[0] == cmdPara._rtnCode) {
  273. // 获取长度;
  274. if ((byte)data[1] == 0xFE) {
  275. nDataPos = 4;
  276. nPacketLen = (byte)data[2] << 8 | (byte)data[3];
  277. if (data.size() < 255 && data[2] != 0) {
  278. cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回数据长度异常"), __FUNCTION__);
  279. return false;
  280. }
  281. }
  282. else
  283. {
  284. nDataPos = 2;
  285. nPacketLen = (byte)data[1];
  286. #if 0 // 如果数据包含有非协议包内的数据,会判断异常;
  287. if (data.size() > 255) {
  288. //nPackageLen = data[1] << 8 | data[2];
  289. cmdPara._rtnError = _dprintf(_T("长度异常"));
  290. return false;
  291. }
  292. #endif
  293. }
  294. #if 0
  295. // 计算出的长度,必等于包长;// 如果包含有其他非包数据,会判断异常;
  296. if (nPackageLen != data.size())
  297. return false;
  298. #endif
  299. if (_tcsicmp(cmdPara.code.c_str(), utils::ByteToChars((byte)data[nDataPos] - 1).c_str()) != 0) {
  300. cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回的指令错误, %s, %02X"), __FUNCTION__, cmdPara.head.c_str(), (byte)data[nDataPos]);
  301. return false;
  302. }
  303. // 返回的数据;
  304. ++nDataPos;// 返回码占一字节;
  305. if (cmdPara.bMulticode) {
  306. if (_tcsicmp(cmdPara.param.c_str(), utils::ByteToChars((byte)data[nDataPos]).c_str()) != 0) {
  307. cmdPara._rtnError = utils::_dprintf(_T("[%s] 返回的指令参数错误, %s, %02X"), __FUNCTION__, cmdPara.param.c_str(), (byte)data[nDataPos]);
  308. return false;
  309. }
  310. ++nDataPos;// 指令参数码占一字节;
  311. }
  312. cmdPara._rtnData = data.substr(nDataPos, nPacketLen - nDataPos - 2); //2 = crc;
  313. utils::_dprintf(_T("rtnData=%s"), utils::BytesToHexString((byte*)cmdPara._rtnData.c_str(), cmdPara._rtnData.size(), ' ').c_str());
  314. // 校验crc;
  315. unsigned short usCRCValue = utils::CRC16Calculate((byte*)data.data(), nPacketLen - 2);
  316. if (((usCRCValue >> 8) & 0xFF) != (byte)data[nPacketLen - 2] || (usCRCValue & 0xFF) != (byte)data[nPacketLen - 1])
  317. {
  318. cmdPara._rtnError = utils::_dprintf("[%s] CRC校验错误:计算[%02X %02X] != 接收[%02X %02X]", __FUNCTION__, (usCRCValue >> 8) & 0xFF, usCRCValue & 0xFF, (byte)data[nPacketLen - 2], (byte)data[nPacketLen - 1]);
  319. return false;
  320. }
  321. if (data.size() > nPacketLen)
  322. utils::_dprintf("[%s] 带有脏数据:%s", __FUNCTION__, data.substr(nPacketLen));
  323. }
  324. else {
  325. cmdPara._rtnError = utils::_dprintf("[%s] 返回码错误:%02X", __FUNCTION__, (byte)data[0]);
  326. return false;
  327. }
  328. return true;
  329. }
  330. std::string TCLCommand::PackingCommand(CommandParam& cmdPara, std::string data, const int& dataLen)
  331. {
  332. // Tag:[命令头][全命令长度][命令码]<命令码参数><附加数据>[crc1][crc2]
  333. std::string command;
  334. // 命令头标识位;
  335. command.append(utils::HexStringToBytes(cmdPara.head, 2).c_str(), cmdPara.head.size() / 2);
  336. // 命令码;
  337. command.append(utils::HexStringToBytes(cmdPara.code, 2).c_str(), cmdPara.code.size() / 2);
  338. // 命令码参数;
  339. command.append(utils::HexStringToBytes(cmdPara.param, 2).c_str(), cmdPara.param.size() / 2);
  340. // 附加的数据;
  341. if (dataLen > 0)
  342. command.append(data.c_str(), dataLen);
  343. int len(0);
  344. // 长度:可能1字节表示,超过255用2字节表示;
  345. byte szlen[2] = { 0 };
  346. //if ((byte)command[1] == 0xFE)
  347. //if ( cmdPara.head.size() >= 4 && cmdPara.head.find("FE", 2, 2) != std::string::npos )
  348. if (_tcsicmp(_T("AAFE"), cmdPara.head.c_str()) == 0)
  349. {// 长度超过255,需要2字节表示;
  350. len = command.size() + 4; // 2位crc + 2位长度;
  351. szlen[0] = (len >> 8) & 0xFF;
  352. szlen[1] = len & 0xFF;
  353. command.insert(2, (char*)szlen, 2);
  354. }
  355. else {
  356. // 2位crc + 1位长度;
  357. len = command.size() + 3;
  358. //if ( _tcsicmp(cmdPara.code.c_str(), "99 00") == 0 )
  359. // len -= 2;
  360. if (len > 255) {// 长度超过255,多一个占位符;
  361. ++len;
  362. szlen[0] = (len >> 8) & 0xFF;
  363. szlen[1] = len & 0xFF;
  364. command.insert(1, (char*)szlen, 2);
  365. }
  366. else {
  367. szlen[0] = len & 0xFF;
  368. command.insert(1, (char*)szlen, 1);
  369. }
  370. }
  371. // crc校验;
  372. byte szcrc[2] = { 0 };
  373. WORD usCRCValue = utils::CRC16Calculate((byte*)command.c_str(), command.size()); // 如果有0断开有危险;
  374. //WORD usCRCValue = CRC16Calculate((byte *)command.c_str(), len - 2);
  375. szcrc[0] = (usCRCValue >> 8) & 0xFF;
  376. szcrc[1] = usCRCValue & 0xFF;
  377. command.append((char*)szcrc, 2);
  378. cmdPara._cmdContext = utils::BytesToHexString((byte*)command.c_str(), command.size(), ' ');
  379. utils::_dprintf(_T("指令:%s = %s"), cmdPara.name.c_str(), cmdPara._cmdContext.c_str());
  380. return command;
  381. }
  382. void TCLCommand::ParseResultString(CommandParam& cmdPara, std::string data, const int& dataLen)
  383. {
  384. // Tag:[返回头][全数据长度][返回码]<返回码子项><附加数据>[crc16]
  385. if (!TheFirstPart(cmdPara, data.substr(0, 5)))
  386. return;
  387. if (cmdPara._rtnStatus != 0x0A) {
  388. utils::_dprintf("[%s] 执行结果错误:%02X", __FUNCTION__, cmdPara._rtnStatus);
  389. return;
  390. }
  391. switch (cmdPara.nOption)
  392. {
  393. case CMDOPT_None:
  394. break;
  395. case CMDOPT_Get:
  396. case CMDOPT_Set:
  397. TheSecondPart(cmdPara, data.substr(5));
  398. break;
  399. default:
  400. break;
  401. }
  402. }