// LogModule.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" #include "LogModule.h" #include #include "SynSerial.h" #include #ifdef _DEBUG #define new DEBUG_NEW #endif // 唯一的应用程序对象 CWinApp theApp; using namespace std; CIOCPModel g_IOCP; // 主要对象,完成端口模型 // 线程:用于监听串口消息; bool g_bStopThread = false; HANDLE g_hThread = NULL; unsigned int g_threadID = 0; unsigned int __stdcall ThreadWathTVPort(PVOID pM) { CSynSerial tv; std::string buffer; TCHAR szLastPort[10] = {0}; _tcscpy_s(szLastPort, Global::g_szTVPort); std::vector vtNotifyReboot; std::vector vtNotifyShutdown; DWORD dwTickCount = GetTickCount(); while(!g_bStopThread) { // 读取配置文件; Global::GetResourceCfg(); if ( !Global::g_bWatchTVPort ) { Sleep(5000); continue; } if ( GetTickCount() - dwTickCount > 5000 ) {// 5秒更新一次; dwTickCount = GetTickCount(); vtNotifyReboot.clear(); vtNotifyShutdown.clear(); Global::Split(Global::g_szTVReboot, _T(";"), vtNotifyReboot); Global::Split(Global::g_szTVShutdown, _T(";"), vtNotifyShutdown); } // 串口是否变更; if ( _tcsicmp(szLastPort, Global::g_szTVPort) ) { _tcscpy_s(szLastPort, Global::g_szTVPort); // 重启打开串口; tv.CloseSerialPort(); } if ( !tv.IsOpen() ) { tv.OpenSerialPort(szLastPort, 115200, 8, 0, 1, 0, 1000); } if ( tv.IsOpen() ) { BYTE szBuffer[1024] = {0}; DWORD dwBuffer = tv.ReadComm(szBuffer, 1024, 1000); if ( dwBuffer != 0 ) { int nType = 0; // 0表示无异常类型,-1表示关机异常,1表示重启异常; bool bAbnormal = false; buffer = (char*)szBuffer; __time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳); // 遍历是否有符合的子串; for ( std::vector::iterator it = vtNotifyReboot.begin(); it != vtNotifyReboot.end(); it++ ) { if ( _tcsstr(buffer.c_str(), it->c_str()) ) { nType = 1; bAbnormal = true; break; } } if ( !bAbnormal ) { for ( std::vector::iterator it = vtNotifyShutdown.begin(); it != vtNotifyShutdown.end(); it++ ) { if ( _tcsstr(buffer.c_str(), it->c_str()) ) { nType = -1; bAbnormal = true; break; } } } // 1分钟前,是否有收到脚本通知; if ( Global::g_notify.notify ) { __int64 nd = gmt - Global::g_notify.datetime; #ifdef _DEBUG TRACE3("判断时间%ld-通知时间%ld=相差时间%ld\n\n", gmt, Global::g_notify.datetime, nd); #endif if ( nd < 60) { // 监测的类型与通知类型是否一致; if ( (nType == 1 && Global::g_notify.report_type == _T("reboot")) || (nType == -1 && Global::g_notify.report_type == _T("shutdown")) ) { bAbnormal = false; // 重置; Global::g_notify.notify = false; Global::g_notify.datetime = 0; Global::g_notify.report_type.clear(); } } } if (bAbnormal) { if ( nType == -1 ) { // 遥控:重启电视机; if ( Global::g_SendPowerKey ) Global::g_SendPowerKey(); } // 压入容器中; Global::TLog tlog; if ( nType == -1 ) tlog.report_type = "Abnormal shutdown"; else if ( nType == 1 ) tlog.report_type = "Abnormal restart"; tlog.datetime = gmt; // 发生时间; struct tm gmtm = {0}; localtime_s(&gmtm, &gmt); // 时间戳转成本地时间; TCHAR szDataTime[64] = {0}; _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); tlog.report_data = szDataTime; Global::g_vtAbnormal.push_back(tlog); // 最后,重置; Global::g_notify.notify = false; Global::g_notify.datetime = 0; Global::g_notify.report_type.clear(); } } } Sleep(200); } return 0; } // 启动tcp服务; BOOL StartServer(unsigned int port) { // 1.加载配置文件; TCHAR szDrive[_MAX_DRIVE] = { 0 }; TCHAR szDir[_MAX_DIR] = { 0 }; TCHAR szExt[_MAX_DIR] = { 0 }; ::GetModuleFileName(NULL, Global::g_szCurModulePath, sizeof(Global::g_szCurModulePath) / sizeof(TCHAR)); _tsplitpath_s(Global::g_szCurModulePath, szDrive, szDir, Global::g_szFna, szExt); _tcscpy_s(Global::g_szCurModuleDir, szDrive); _tcscat_s(Global::g_szCurModuleDir, szDir); // 初始化网络库; if ( !g_IOCP.LoadSocketLib() ) { return FALSE; } Global::WriteTextLog(_T("初始化网络库成功")); // 开启tcp服务; if ( !g_IOCP.Start(port) ) { return FALSE; } Global::g_time = time(NULL); Global::g_lastTime = COleDateTime::GetCurrentTime(); Global::WriteTextLog(_T("开启TCP服务成功")); if ( PathFileExists(Global::g_szConfig) ) { // runner_tcp_port TCHAR szTcpPort[10] = {0}; _itoa_s(port, szTcpPort, 10); Global::WriteTextLog(_T("配置文件路径:%s"), Global::g_szConfig); for ( int i = 0; i < 10; i++ ) { if (!WritePrivateProfileString(_T("COMM"), _T("runner_tcp_port"), szTcpPort, Global::g_szConfig)) Global::WriteTextLog(_T("保存端口号:%d 失败; 原因:%d"), port, GetLastError()); else { Global::WriteTextLog(_T("保存端口号:%d 成功;"), port); break; } } } #ifdef _DEBUG Sleep(10000); #endif Global::GetResourceCfg(); // 启动线程; g_hThread = (HANDLE)_beginthreadex( NULL, 0, &ThreadWathTVPort, NULL, 0, &g_threadID ); return TRUE; } // 停止tcp服务; void StopServer() { g_IOCP.Stop(); // 等待线程结束; g_bStopThread = true; WaitForSingleObject( g_hThread, INFINITE ); CloseHandle( g_hThread ); } // 是否写入日志文件; void EnableWriteLog(bool bEnable) { Global::g_bEnableLog = bEnable; if ( !bEnable ) Global::ClosePythonLog(); Global::WriteTextLog(_T("当前日志路径:%s; 状态:%s"), Global::g_szLogPath, bEnable ? _T("启用日志") : _T("禁用日志") ); } void SetCaselogPath(LPCTSTR lpCaselogPath) { if ( lpCaselogPath == NULL || lpCaselogPath[0] == '\0') { Global::WriteTextLog(_T("日志路径无效")); return; } Global::WriteTextLog(_T("设置日志路径:%s"), lpCaselogPath); _stprintf_s(Global::g_szLogPath, _T("%s"), lpCaselogPath); } void SetConfigPath(LPCTSTR lpConfigPath) { if ( lpConfigPath == NULL || lpConfigPath[0] == '\0') return; _stprintf_s(Global::g_szConfig, _T("%s"), lpConfigPath); } void SetSendPowerKeyCB(void *pCB) { Global::g_SendPowerKey = (Global::SENDPOWERKEY)pCB; } LPCTSTR GetCaselogPath() { return Global::g_szLogPath; } __int64 GetReceivePrintTime() { return Global::g_time; } void SetReceivePrintTime(__int64 dt) { Global::g_time = dt; } void ClosePythonLog() { Global::ClosePythonLog(); } BOOL AddAbnormaltoXML(LPCTSTR lpXMLPath) { // 参数有效性判断; if ( !lpXMLPath || !PathFileExists(lpXMLPath) ) { return FALSE; } // 解析xml; tinyxml2::XMLDocument doc; if (tinyxml2::XML_SUCCESS != doc.LoadFile(lpXMLPath) ) { return FALSE; } tinyxml2::XMLElement *pXmlRoot = NULL; if ((pXmlRoot = doc.RootElement()) != NULL) { int i = 0; TCHAR szNumber[10] = {0}; for ( std::vector::iterator it = Global::g_vtAbnormal.begin(); it != Global::g_vtAbnormal.end(); it++ ) { tinyxml2::XMLElement *pItem = doc.NewElement("item"); tinyxml2::XMLElement *pName = doc.NewElement("name"); tinyxml2::XMLElement *pResult = doc.NewElement("result"); tinyxml2::XMLElement *pData = doc.NewElement("data"); tinyxml2::XMLElement *pLog = doc.NewElement("log"); tinyxml2::XMLElement *pRemark = doc.NewElement("remark"); memset(szNumber, 0, 10); _stprintf_s(szNumber, _T("100%04d@%s"), i++, it->report_type.c_str()); pName->SetText(szNumber); pResult->SetText("PASS"); pData->SetText(it->report_data.c_str()); pItem->InsertEndChild(pName); pItem->InsertEndChild(pResult); pItem->InsertEndChild(pData); pItem->InsertEndChild(pLog); pItem->InsertEndChild(pRemark); pXmlRoot->InsertEndChild(pItem); } } // 保存; doc.SaveFile(lpXMLPath); Global::g_vtAbnormal.clear(); }