LogModule.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // LogModule.cpp : 定义 DLL 应用程序的导出函数。
  2. //
  3. #include "stdafx.h"
  4. #include "LogModule.h"
  5. #include <Shlwapi.h>
  6. #include "SynSerial.h"
  7. #include <process.h>
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #endif
  11. // 唯一的应用程序对象
  12. CWinApp theApp;
  13. using namespace std;
  14. CIOCPModel g_IOCP; // 主要对象,完成端口模型
  15. // 线程:用于监听串口消息;
  16. bool g_bStopThread = false;
  17. HANDLE g_hThread = NULL;
  18. unsigned int g_threadID = 0;
  19. unsigned int __stdcall ThreadWathTVPort(PVOID pM)
  20. {
  21. CSynSerial tv;
  22. std::string buffer;
  23. TCHAR szLastPort[10] = {0};
  24. _tcscpy_s(szLastPort, Global::g_szTVPort);
  25. std::vector<std::string> vtNotifyReboot;
  26. std::vector<std::string> vtNotifyShutdown;
  27. DWORD dwTickCount = GetTickCount();
  28. while(!g_bStopThread)
  29. {
  30. // 读取配置文件;
  31. Global::GetResourceCfg();
  32. if ( !Global::g_bWatchTVPort )
  33. {
  34. Sleep(5000);
  35. continue;
  36. }
  37. if ( GetTickCount() - dwTickCount > 5000 )
  38. {// 5秒更新一次;
  39. dwTickCount = GetTickCount();
  40. vtNotifyReboot.clear();
  41. vtNotifyShutdown.clear();
  42. Global::Split(Global::g_szTVReboot, _T(";"), vtNotifyReboot);
  43. Global::Split(Global::g_szTVShutdown, _T(";"), vtNotifyShutdown);
  44. }
  45. // 串口是否变更;
  46. if ( _tcsicmp(szLastPort, Global::g_szTVPort) )
  47. {
  48. _tcscpy_s(szLastPort, Global::g_szTVPort);
  49. // 重启打开串口;
  50. tv.CloseSerialPort();
  51. }
  52. if ( !tv.IsOpen() )
  53. {
  54. tv.OpenSerialPort(szLastPort, 115200, 8, 0, 1, 0, 1000);
  55. }
  56. if ( tv.IsOpen() )
  57. {
  58. BYTE szBuffer[1024] = {0};
  59. DWORD dwBuffer = tv.ReadComm(szBuffer, 1024, 1000);
  60. if ( dwBuffer != 0 )
  61. {
  62. int nType = 0; // 0表示无异常类型,-1表示关机异常,1表示重启异常;
  63. bool bAbnormal = false;
  64. buffer = (char*)szBuffer;
  65. __time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳);
  66. // 遍历是否有符合的子串;
  67. for ( std::vector<std::string>::iterator it = vtNotifyReboot.begin(); it != vtNotifyReboot.end(); it++ )
  68. {
  69. if ( _tcsstr(buffer.c_str(), it->c_str()) )
  70. {
  71. nType = 1;
  72. bAbnormal = true;
  73. break;
  74. }
  75. }
  76. if ( !bAbnormal )
  77. {
  78. for ( std::vector<std::string>::iterator it = vtNotifyShutdown.begin(); it != vtNotifyShutdown.end(); it++ )
  79. {
  80. if ( _tcsstr(buffer.c_str(), it->c_str()) )
  81. {
  82. nType = -1;
  83. bAbnormal = true;
  84. break;
  85. }
  86. }
  87. }
  88. // 1分钟前,是否有收到脚本通知;
  89. if ( Global::g_notify.notify )
  90. {
  91. __int64 nd = gmt - Global::g_notify.datetime;
  92. #ifdef _DEBUG
  93. TRACE3("判断时间%ld-通知时间%ld=相差时间%ld\n\n", gmt, Global::g_notify.datetime, nd);
  94. #endif
  95. if ( nd < 60)
  96. {
  97. // 监测的类型与通知类型是否一致;
  98. if ( (nType == 1 && Global::g_notify.report_type == _T("reboot")) ||
  99. (nType == -1 && Global::g_notify.report_type == _T("shutdown")) )
  100. {
  101. bAbnormal = false;
  102. // 重置;
  103. Global::g_notify.notify = false;
  104. Global::g_notify.datetime = 0;
  105. Global::g_notify.report_type.clear();
  106. }
  107. }
  108. }
  109. if (bAbnormal)
  110. {
  111. if ( nType == -1 )
  112. {
  113. // 遥控:重启电视机;
  114. if ( Global::g_SendPowerKey )
  115. Global::g_SendPowerKey();
  116. }
  117. // 压入容器中;
  118. Global::TLog tlog;
  119. if ( nType == -1 )
  120. tlog.report_type = "Abnormal shutdown";
  121. else if ( nType == 1 )
  122. tlog.report_type = "Abnormal restart";
  123. tlog.datetime = gmt; // 发生时间;
  124. struct tm gmtm = {0};
  125. localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
  126. TCHAR szDataTime[64] = {0};
  127. _stprintf_s(szDataTime,_T("Time of exception:%04d-%02d-%02d %02d:%02d:%02d"), gmtm.tm_year + 1900, gmtm.tm_mon+1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec);
  128. tlog.report_data = szDataTime;
  129. Global::g_vtAbnormal.push_back(tlog);
  130. // 最后,重置;
  131. Global::g_notify.notify = false;
  132. Global::g_notify.datetime = 0;
  133. Global::g_notify.report_type.clear();
  134. }
  135. }
  136. }
  137. Sleep(200);
  138. }
  139. return 0;
  140. }
  141. // 启动tcp服务;
  142. BOOL StartServer(unsigned int port)
  143. {
  144. // 1.加载配置文件;
  145. TCHAR szDrive[_MAX_DRIVE] = { 0 };
  146. TCHAR szDir[_MAX_DIR] = { 0 };
  147. TCHAR szExt[_MAX_DIR] = { 0 };
  148. ::GetModuleFileName(NULL, Global::g_szCurModulePath, sizeof(Global::g_szCurModulePath) / sizeof(TCHAR));
  149. _tsplitpath_s(Global::g_szCurModulePath, szDrive, szDir, Global::g_szFna, szExt);
  150. _tcscpy_s(Global::g_szCurModuleDir, szDrive);
  151. _tcscat_s(Global::g_szCurModuleDir, szDir);
  152. // 初始化网络库;
  153. if ( !g_IOCP.LoadSocketLib() )
  154. {
  155. return FALSE;
  156. }
  157. Global::WriteTextLog(_T("初始化网络库成功"));
  158. // 开启tcp服务;
  159. if ( !g_IOCP.Start(port) )
  160. {
  161. return FALSE;
  162. }
  163. Global::g_time = time(NULL);
  164. Global::g_lastTime = COleDateTime::GetCurrentTime();
  165. Global::WriteTextLog(_T("开启TCP服务成功"));
  166. if ( PathFileExists(Global::g_szConfig) )
  167. {
  168. // runner_tcp_port
  169. TCHAR szTcpPort[10] = {0};
  170. _itoa_s(port, szTcpPort, 10);
  171. Global::WriteTextLog(_T("配置文件路径:%s"), Global::g_szConfig);
  172. for ( int i = 0; i < 10; i++ )
  173. {
  174. if (!WritePrivateProfileString(_T("COMM"), _T("runner_tcp_port"), szTcpPort, Global::g_szConfig))
  175. Global::WriteTextLog(_T("保存端口号:%d 失败; 原因:%d"), port, GetLastError());
  176. else
  177. {
  178. Global::WriteTextLog(_T("保存端口号:%d 成功;"), port);
  179. break;
  180. }
  181. }
  182. }
  183. #ifdef _DEBUG
  184. Sleep(10000);
  185. #endif
  186. Global::GetResourceCfg();
  187. // 启动线程;
  188. g_hThread = (HANDLE)_beginthreadex( NULL, 0, &ThreadWathTVPort, NULL, 0, &g_threadID );
  189. return TRUE;
  190. }
  191. // 停止tcp服务;
  192. void StopServer()
  193. {
  194. g_IOCP.Stop();
  195. // 等待线程结束;
  196. g_bStopThread = true;
  197. WaitForSingleObject( g_hThread, INFINITE );
  198. CloseHandle( g_hThread );
  199. }
  200. // 是否写入日志文件;
  201. void EnableWriteLog(bool bEnable)
  202. {
  203. Global::g_bEnableLog = bEnable;
  204. if ( !bEnable )
  205. Global::ClosePythonLog();
  206. Global::WriteTextLog(_T("当前日志路径:%s; 状态:%s"), Global::g_szLogPath, bEnable ? _T("启用日志") : _T("禁用日志") );
  207. }
  208. void SetCaselogPath(LPCTSTR lpCaselogPath)
  209. {
  210. if ( lpCaselogPath == NULL || lpCaselogPath[0] == '\0')
  211. {
  212. Global::WriteTextLog(_T("日志路径无效"));
  213. return;
  214. }
  215. Global::WriteTextLog(_T("设置日志路径:%s"), lpCaselogPath);
  216. _stprintf_s(Global::g_szLogPath, _T("%s"), lpCaselogPath);
  217. }
  218. void SetConfigPath(LPCTSTR lpConfigPath)
  219. {
  220. if ( lpConfigPath == NULL || lpConfigPath[0] == '\0')
  221. return;
  222. _stprintf_s(Global::g_szConfig, _T("%s"), lpConfigPath);
  223. }
  224. void SetSendPowerKeyCB(void *pCB)
  225. {
  226. Global::g_SendPowerKey = (Global::SENDPOWERKEY)pCB;
  227. }
  228. LPCTSTR GetCaselogPath()
  229. {
  230. return Global::g_szLogPath;
  231. }
  232. __int64 GetReceivePrintTime()
  233. {
  234. return Global::g_time;
  235. }
  236. void SetReceivePrintTime(__int64 dt)
  237. {
  238. Global::g_time = dt;
  239. }
  240. void ClosePythonLog()
  241. {
  242. Global::ClosePythonLog();
  243. }
  244. BOOL AddAbnormaltoXML(LPCTSTR lpXMLPath)
  245. {
  246. // 参数有效性判断;
  247. if ( !lpXMLPath || !PathFileExists(lpXMLPath) )
  248. {
  249. return FALSE;
  250. }
  251. // 解析xml;
  252. tinyxml2::XMLDocument doc;
  253. if (tinyxml2::XML_SUCCESS != doc.LoadFile(lpXMLPath) )
  254. {
  255. return FALSE;
  256. }
  257. tinyxml2::XMLElement *pXmlRoot = NULL;
  258. if ((pXmlRoot = doc.RootElement()) != NULL)
  259. {
  260. int i = 0;
  261. TCHAR szNumber[10] = {0};
  262. for ( std::vector<Global::TLog>::iterator it = Global::g_vtAbnormal.begin(); it != Global::g_vtAbnormal.end(); it++ )
  263. {
  264. tinyxml2::XMLElement *pItem = doc.NewElement("item");
  265. tinyxml2::XMLElement *pName = doc.NewElement("name");
  266. tinyxml2::XMLElement *pResult = doc.NewElement("result");
  267. tinyxml2::XMLElement *pData = doc.NewElement("data");
  268. tinyxml2::XMLElement *pLog = doc.NewElement("log");
  269. tinyxml2::XMLElement *pRemark = doc.NewElement("remark");
  270. memset(szNumber, 0, 10);
  271. _stprintf_s(szNumber, _T("100%04d@%s"), i++, it->report_type.c_str());
  272. pName->SetText(szNumber);
  273. pResult->SetText("PASS");
  274. pData->SetText(it->report_data.c_str());
  275. pItem->InsertEndChild(pName);
  276. pItem->InsertEndChild(pResult);
  277. pItem->InsertEndChild(pData);
  278. pItem->InsertEndChild(pLog);
  279. pItem->InsertEndChild(pRemark);
  280. pXmlRoot->InsertEndChild(pItem);
  281. }
  282. }
  283. // 保存;
  284. doc.SaveFile(lpXMLPath);
  285. Global::g_vtAbnormal.clear();
  286. }