#include "stdafx.h" #include "AppService.h" #include #include "MonitorObject.h" #include "httplib.h" #include #include #include #include "Device.h" #include "ResistAlarm.h" #ifdef _DEBUG #pragma comment(lib, "HJ_ACE650d.lib") #pragma message("Automatically linking with aced.dll") #else #pragma comment(lib, "HJ_ACE650.lib") #pragma message("Automatically linking with ace.dll") #endif bool g_bLog; time_t g_stStart; //程序启动的时间 string g_strExepath; //程序目录 string g_strVersion; //程序版本 void tagFileData::Join() { delete this; } CAppService::CAppService() { AfxSocketInit(); ACE::init(); SPDLOG_INFO("ACE init."); } CAppService::~CAppService() { SPDLOG_INFO("ACE fini"); ACE::fini(); AfxSocketTerm(); } bool CAppService::Start() { //string str = R"({"id":"100000","name":"国铁集团","type":"group","up":"100000")"; //jsonxx::Object o; //o.parse(str); //auto r = o.empty(); SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); g_strExepath = hjfunc_GetAppDir(); g_strVersion = hjfunc_GetVersion(); auto strPath = CSimpleLog::GetAppDir() + "svg"; if (CSimpleLog::PathFileExistsA(strPath) == FALSE) CreateDirectory(strPath, nullptr); strPath = CSimpleLog::GetAppDir() + "refer"; if (CSimpleLog::PathFileExistsA(strPath) == FALSE) CreateDirectory(strPath, nullptr); m_strIniPath = CSimpleLog::GetAppDir() + "DataCenter.ini"; char szTemp[100] = { 0 }; CString m_strDriver = "ODBC Driver 11 for SQL Server"; CString m_strDataSource = "127.0.0.1,21009"; CString m_strCataLog = "RMDB0571"; CString m_strUserID = "zljc"; CString m_strPassWD = "Zljc123!@#"; int port = 10086; ::GetPrivateProfileStringA("ODBC", "DRIVER", CStringA(m_strDriver), szTemp, sizeof(szTemp), m_strIniPath); m_strDriver = CString(szTemp); ::GetPrivateProfileStringA("ODBC", "SERVER", CStringA(m_strDataSource), szTemp, sizeof(szTemp), m_strIniPath); m_strDataSource = CString(szTemp); ::GetPrivateProfileStringA("ODBC", "UID", CStringA(m_strUserID), szTemp, sizeof(szTemp), m_strIniPath); m_strUserID = CString(szTemp); ::GetPrivateProfileStringA("ODBC", "PWD", CStringA(m_strPassWD), szTemp, sizeof(szTemp), m_strIniPath); m_strPassWD = CString(szTemp); ::GetPrivateProfileStringA("ODBC", "DATABASE", CStringA(m_strCataLog), szTemp, sizeof(szTemp), m_strIniPath); m_strCataLog = CString(szTemp); port = ::GetPrivateProfileInt("SET", "port", port, m_strIniPath); ::WritePrivateProfileStringA("ODBC", "DRIVER", CStringA(m_strDriver), m_strIniPath); ::WritePrivateProfileStringA("ODBC", "SERVER", CStringA(m_strDataSource), m_strIniPath); ::WritePrivateProfileStringA("ODBC", "DATABASE", CStringA(m_strCataLog), m_strIniPath); ::WritePrivateProfileString("ODBC", "UID", m_strUserID, m_strIniPath); //::WritePrivateProfileString("ODBC", "PWD", m_strPassWD, m_strIniPath); ::WritePrivateProfileStringA("SET", "port", (to_string(port) + " #Websocket 端口").c_str(), m_strIniPath); //ODBC if (CDBConnectPool::Instance()->Init(m_strDriver, m_strDataSource, m_strUserID, m_strPassWD, m_strCataLog, 5) == FALSE) { ASSERT(0); SPDLOG_CRITICAL("数据库连接池初始化失败{}:{}:{}:{}:{}", m_strDriver, m_strDataSource, m_strCataLog, m_strUserID, m_strPassWD); return false; } //升级 { CString sql; BOOL ret; sql = "if not exists (select 1 from [rm_mo] where [id] = '100000' )\ BEGIN\ INSERT INTO [rm_mo] ([id],[type],[up],[name],[updatetime]) VALUES ('100000' ,'group' ,'100000', '国铁集团',GETDATE());\ END"; ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); sql = "if not exists (select 1 from [rm_user] where [username] = 'system' )\ BEGIN\ INSERT INTO [dbo].[rm_user]([username] ,[password] ,[name] ,[admin] ,[token] ,[node] ,[enable] ,[mobile] ,[email] ,[mark]) VALUES ('system' ,'Zljc123!@#' ,'系统管理员' ,1 ,'AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA','100000',1,'15305712458','','');\ END"; ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); /* sql = "select top 1 event_id from rm_alarm"; ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); if (true != ret) { sql = "alter table rm_alarm add event_id char(36) null default newid();\ alter table rm_alarm add rel_id char(36) null default ''; "; ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); sql = "UPDATE [rm_alarm] SET [event_id]=NEWID() WHERE [event_id] is null;\ UPDATE [rm_alarm] SET [rel_id]='' WHERE [rel_id] is null;"; ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); } */ /* sql = "SELECT top 1 module FROM rm_record"; ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); if (TRUE != ret) { sql = "create table rm_record (\ module tinyint not null,\ dura int not null,\ analyze_type tinyint null,\ station nvarchar(50) not null,\ station_name nvarchar(50) not null,\ mo varchar(20) null,\ mo_name varchar(20) null,\ mp varchar(20) null,\ mp_name varchar(20) null,\ start_time bigint not null,\ end_time bigint null,\ time bigint not null,\ name nvarchar(50) not null,\ username varchar(50) not null,\ opt smallint not null,\ mark nvarchar(100) null default ''\ );\ create clustered index IDX_STATION on rm_record(\ station_name ASC,\ time DESC\ );\ create index IDX_TIME on rm_record(\ time DESC\ );"; ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); if (ret != TRUE) SPDLOG_ERROR("语句执行错误:{}", sql); } */ } m_bWork = true; m_pCreateTableThread = new std::thread(CAppService::ThreadProcCreateTable, (DWORD_PTR)this); Sleep(50); //加载设备 CDeviceMng::Instance()->LoadDevice(); //加载机构 if (!CMonitorObjectMng::Instance()->LoadMonitorTree()) { ASSERT(0); SPDLOG_CRITICAL("LoadMonitorTree Fail."); return false; } else { //CMonitorObjectMng::Instance()->LoadHistoryData(); } //加载报警 CResistAlarmMng::Instance()->Start(); Sleep(50); //开启与dataservices 通信端口 10090 m_pProactorTask = new CProactorTask; m_pProactorTask->start(4); m_pHandle = new CLNHandle; m_pAcceptor = new CLNAcceptor(m_pHandle); //if (m_pAcceptor->listen(10090) == -1) //{ // SPDLOG_CRITICAL("端口{} tcp 监听失败", 10090); // return false; //} if (m_pAcceptor->Start() == FALSE) { SPDLOG_CRITICAL("CLNAcceptor 启动失败"); return false; } m_bRun = true; //磁盘空间检测 m_pThreadSpace = new std::thread(CAppService::ThreadProcForSpace, (DWORD_PTR)this); //与外部链接放到最后 //开启新的websocket m_mgServer = new CMGWSServer; if (!m_mgServer->Start(port))//10086 { ASSERT(0); SPDLOG_CRITICAL("websocket {} 端口监听失败", port); return false; } m_pHttpThread = new std::thread(CAppService::ThreadProcForHTTP, (DWORD_PTR)this);//10088 //if (!m_pUdpSocket->Open(10090, NULL, 0, NULL)) //{ // ASSERT(0); // SPDLOG_CRITICAL("UDP {} 端口监听失败", 10090); // return false; //} if (m_pAcceptor->listen(10090) == -1) { SPDLOG_CRITICAL("端口{} tcp 监听失败", 10090); return false; } time(&g_stStart); SPDLOG_INFO("app start succ."); return true; } void CAppService::Stop() { SPDLOG_INFO("停止服务"); m_bRun = false; m_bWork = false; //关闭外部链接 if (m_pAcceptor) m_pAcceptor->ClearAllContexts(); if (m_pProactorTask) m_pProactorTask->stop(); if (m_mgServer) m_mgServer->Stop(); //关闭线程 if (m_pThreadSpace) { m_pThreadSpace->join(); delete m_pThreadSpace; m_pThreadSpace = nullptr; } if (m_pCreateTableThread) { m_pCreateTableThread->join(); delete m_pCreateTableThread; m_pCreateTableThread = nullptr; } if (m_pHttpThread) { m_svr.stop(); m_pHttpThread->join(); delete m_pHttpThread; m_pHttpThread = nullptr; } //if (m_pUdpSocket) //{ // m_pUdpSocket->Close(); // delete m_pUdpSocket; // m_pUdpSocket = nullptr; //} CResistAlarmMng::Instance()->Stop(); //if (m_lwsServer) //{ // m_lwsServer->Stop(); // delete m_lwsServer; // m_lwsServer = nullptr; //} if (m_mgServer) { delete m_mgServer; m_mgServer = nullptr; } if (m_pHandle) { m_pHandle->Close(); delete m_pHandle; m_pHandle = nullptr; } if (m_pAcceptor) { delete m_pAcceptor; m_pAcceptor = nullptr; } if (m_pProactorTask) { delete m_pProactorTask; m_pProactorTask = nullptr; } CDBConnectPool::Instance()->Clear(); } BOOL CAppService::FileDataConvertCharData(const uint8_t* filedata, const int filelen, char* strData) { if (strData == nullptr) return FALSE; for (auto i = 0; i < filelen; i++) sprintf_s(strData + i * 2, 3, "%02X", filedata[i]); return TRUE; } #include "HttpPrcess.h" void CAppService::ThreadProcForHTTP(DWORD_PTR pThis) { using namespace httplib; m_svr.Post("/data/.*", DealHttpPost); m_svr.Get("/data/.*", DealHttpGet); auto ret = m_svr.listen("0.0.0.0", 10088); if (ret == false) SPDLOG_CRITICAL("HTTP {} 端口监听失败", 10088); return ; } void CAppService::ThreadProcCreateTable(DWORD_PTR pThis) { auto pService = (CAppService*)pThis; SPDLOG_INFO("ThreadProcCreateTable 线程开始!"); do { SYSTEMTIME stNow, stTom, stYest; GetLocalTime(&stNow); COleDateTime odt_now(stNow); COleDateTime odt_tom = odt_now + COleDateTimeSpan(1, 0, 0, 0); COleDateTime odt_yest = odt_now - COleDateTimeSpan(1, 0, 0, 0); odt_tom.GetAsSystemTime(stTom); odt_yest.GetAsSystemTime(stYest); CString tableName; CString tableNameTom; CString tableNameYest; tableName.Format("rm_resistance_%04d%02d%02d", stNow.wYear, stNow.wMonth, stNow.wDay, stNow.wHour, stNow.wMinute, stNow.wSecond); tableNameTom.Format("rm_resistance_%04d%02d%02d", stTom.wYear, stTom.wMonth, stTom.wDay, stTom.wHour, stTom.wMinute, stTom.wSecond); tableNameYest.Format("rm_resistance_%04d%02d%02d", stYest.wYear, stYest.wMonth, stYest.wDay, stYest.wHour, stYest.wMinute, stYest.wSecond); CString existsql = CString("select top 1 id from sysobjects where name = '") + tableName + "' and type = 'U';"; CString existsqlTom = CString("select top 1 id from sysobjects where name = '") + tableNameTom + "' and type = 'U';"; CString existsqlYest = CString("select top 1 id from sysobjects where name = '") + tableNameYest + "' and type = 'U';"; CString tablesqltoday = CString("create table ") + tableName + " (\n" + " momp varchar(50) not null,\n" + " acquisitiontime datetime not null,\n" + " data0 int null,\n" + " data1 int null,\n" + " data2 int null\n" + ");" + "create unique clustered index IDX_TIME on " + tableName + " (\n" + "momp ASC,\n" + "acquisitiontime ASC\n" + ")"; CString tablesqlTom = "create table " + tableNameTom + " (\n" + " momp varchar(50) not null,\n" + " acquisitiontime datetime not null,\n" + " data0 int null,\n" + " data1 int null,\n" + " data2 int null\n" + ");" + "create unique clustered index IDX_TIME on " + tableNameTom + " (\n" + "momp ASC,\n" + "acquisitiontime ASC\n" + ")"; CString tableYest = "create table " + tableNameYest + " (\n" + " momp varchar(50) not null,\n" + " acquisitiontime datetime not null,\n" + " data0 int null,\n" + " data1 int null,\n" + " data2 int null\n" + ");" + "create unique clustered index IDX_TIME on " + tableNameYest + " (\n" + "momp ASC,\n" + "acquisitiontime ASC\n" + ")"; COdbcStatement stmt; CDBConnectPool::Instance()->DBQuery(stmt, existsql); int id = 0; stmt.BindIntCol(1, &id); if (stmt.FetchNext() != 0) { //不存在 if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqltoday)) SPDLOG_ERROR("数据库执行错误:{}", tablesqltoday); } stmt.Close(); COdbcStatement stmtTom; CDBConnectPool::Instance()->DBQuery(stmtTom, existsqlTom); stmtTom.BindIntCol(1, &id); if (stmtTom.FetchNext() != 0) { //不存在 if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqlTom)) SPDLOG_ERROR("数据库执行错误:{}", tablesqlTom); } stmtTom.Close(); COdbcStatement stmtYest; CDBConnectPool::Instance()->DBQuery(stmtYest, existsqlYest); stmtYest.BindIntCol(1, &id); if (stmtYest.FetchNext() != 0) { //不存在 if (!CDBConnectPool::Instance()->DBExecuteSQL(tableYest)) SPDLOG_ERROR("数据库执行错误:{}", tableYest); } stmtYest.Close(); //temperature tableName.Format("rm_temphumidity_%04d%02d", stNow.wYear, stNow.wMonth, stNow.wDay, stNow.wHour, stNow.wMinute); tableNameTom.Format("rm_temphumidity_%04d%02d", stTom.wYear, stTom.wMonth, stTom.wDay, stTom.wHour, stTom.wMinute); existsql = CString("select top 1 id from sysobjects where name = '") + tableName + "' and type = 'U';"; existsqlTom = CString("select top 1 id from sysobjects where name = '") + tableNameTom + "' and type = 'U';"; tablesqltoday = CString("create table ") + tableName + " (\n" + " mo varchar(25) not null,\n" + " mp varchar(5) not null,\n" + " acquisitiontime datetime not null,\n" + " temperature int not null,\n" + " humidity int not null\n" + ");" + "create unique clustered index IDX_IMEI on " + tableName + " (\n" + "mo ASC, mp ASC, acquisitiontime ASC)"; CDBConnectPool::Instance()->DBQuery(stmt, existsql); stmt.BindIntCol(1, &id); if (stmt.FetchNext() != 0) { //不存在 if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqltoday)) SPDLOG_ERROR("数据库执行错误:{}", tablesqltoday); } stmt.Close(); if (stNow.wMonth != stTom.wMonth || stNow.wYear != stTom.wYear) { CDBConnectPool::Instance()->DBQuery(stmt, existsqlTom); stmt.BindIntCol(1, &id); if (stmt.FetchNext() != 0) { //不存在 tablesqlTom = CString("create table ") + tableNameTom + " (\n" + " mo varchar(50) not null,\n" + " acquisitiontime datetime not null,\n" + " temperature int not null,\n" + " humidity int not null\n" + ");" + "create unique clustered index IDX_IMEI on " + tableNameTom + " (\n" + "mo ASC,\n" + "acquisitiontime ASC\n" + ")"; if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqlTom)) SPDLOG_ERROR("数据库执行错误:{}", tablesqlTom); } stmt.Close(); } //扳动记录表 { SYSTEMTIME lastSt; memcpy(&lastSt, &stNow, sizeof(SYSTEMTIME)); move_today: string table_today = fmt::format("rm_move_{:0>4}{:0>2}", lastSt.wYear, lastSt.wMonth); COdbcStatement stmt; CDBConnectPool::Instance()->DBQuery(stmt, CString(fmt::format("select top 1 id from sysobjects where name = '{}' and type = 'U'; ", table_today).c_str())); int id = 0; stmt.BindIntCol(1, &id); if (stmt.FetchNext() != 0) { CString strSql = fmt::format("create table {0} (\ mo varchar(20) not null,\ mp varchar(20) not null,\ show_time datetime not null,\ start_time datetime null,\ end_time datetime null,\ curr_val int null,\ show_val int not null,\ idx tinyint null,\ posi tinyint not null,\ mark nvarchar(255) null\ );create unique clustered index IDX_MO_MP on {0}(mo ASC,mp ASC,show_time ASC);", table_today).c_str(); //不存在 if (!CDBConnectPool::Instance()->DBExecuteSQL(strSql)) SPDLOG_ERROR("数据库执行错误:{}", strSql); } stmt.Close(); if (lastSt.wYear != stTom.wYear || lastSt.wMonth != stTom.wMonth) { memcpy(&lastSt, &stTom, sizeof(SYSTEMTIME)); goto move_today; } auto move_reserve = ::GetPrivateProfileInt("SET", "move_reserve", 730, pService->m_strIniPath); if (move_reserve < 90) move_reserve = 90; ::WritePrivateProfileStringA("SET", "move_reserve", fmt::format("{} 天 #转换过程记录保留天数, 默认730天, 20230701起", move_reserve).c_str(), pService->m_strIniPath); static bool bExec_rm_move = true; COleDateTimeSpan dts_delete(move_reserve, 0, 0, 0); CString sql = "select name from sys.tables where name like 'rm_move_%' ORDER BY name;"; if (CDBConnectPool::Instance()->DBQuery(stmt, sql)) { char tablename[50]; stmt.BindCharCol(1, tablename, sizeof(tablename)); while (true) { memset(tablename, 0, sizeof(tablename)); if (stmt.FetchNext() != 0) { break; } if (strlen(tablename) < 14) { assert(0); continue; } COleDateTime dd; try { int year, month; sscanf_s(tablename, "rm_move_%04d%02d", &year, &month); dd = COleDateTime(year, month, 1, 0, 0, 0); } catch (const std::exception&) { assert(0); continue; } if (odt_now - dd > dts_delete) { sql.Format(" DROP TABLE %s ", tablename); CDBConnectPool::Instance()->DBExecuteSQL(sql); } else { if (bExec_rm_move == false) break; CString qq = CString("SELECT end_time FROM ") + tablename; if (CDBConnectPool::Instance()->DBExecuteSQL(qq) == FALSE) { qq.Format("ALTER TABLE %s ADD end_time datetime null;", tablename); CDBConnectPool::Instance()->DBExecuteSQL(qq); qq.Format("UPDATE rm_move_202301 SET end_time = 0 where end_time is null;", tablename); CDBConnectPool::Instance()->DBExecuteSQL(qq); } } } stmt.Close(); bExec_rm_move = false; } } ULARGE_INTEGER FreeBytesAvailableToCaller, TotalNumberOfBytes, TotalNumberOfFreeBytes; if (!GetDiskFreeSpaceEx("E:", &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes)) continue; auto dwCurLeftDisk = DWORD(FreeBytesAvailableToCaller.QuadPart >> 20); auto idle_reserve = ::GetPrivateProfileInt("SET", "idle_reserve", 20, pService->m_strIniPath); if (idle_reserve < 5) idle_reserve = 5; ::WritePrivateProfileStringA("SET", "idle_reserve", fmt::format("{} GB #E盘闲置空间, 默认20GB, 20230701起", idle_reserve).c_str(), pService->m_strIniPath); BOOL bClear = (dwCurLeftDisk < idle_reserve * 1024); BOOL bForceClear = (dwCurLeftDisk < 3 * 1024); auto resist_reserve = ::GetPrivateProfileInt("SET", "resist_reserve", 365, pService->m_strIniPath); if (resist_reserve < 30) resist_reserve = 30; ::WritePrivateProfileStringA("SET", "resist_reserve", fmt::format("{} 天 #阻力数据保留天数, 默认365天, 20230701起", resist_reserve).c_str(), pService->m_strIniPath); auto temp_reserve = ::GetPrivateProfileInt("SET", "temp_reserve", 365, pService->m_strIniPath); if (temp_reserve < 30) temp_reserve = 30; ::WritePrivateProfileStringA("SET", "temp_reserve", fmt::format("{} 天 #温湿度数据保留天数, 默认365天, 20230701起", temp_reserve).c_str(), pService->m_strIniPath); //删除365天前的数据 if (bClear) { if (bForceClear) resist_reserve = resist_reserve / 2; COleDateTimeSpan dts_delete(resist_reserve, 0, 0, 0); COdbcStatement stmt; CString sql = "select name from sys.tables where name like 'rm_resistance_%' ORDER BY name;"; if (CDBConnectPool::Instance()->DBQuery(stmt, sql)) { char tablename[50]; stmt.BindCharCol(1, tablename, sizeof(tablename)); while (true) { memset(tablename, 0, sizeof(tablename)); if (stmt.FetchNext() != 0) { break; } if (strlen(tablename) < 22) { assert(0); continue; } COleDateTime dd; try { dd = COleDateTime(atoi(CString(tablename + 14, 4)), atoi(CString(tablename + 18, 2)), atoi(CString(tablename + 20, 2)), 0, 0, 0); } catch (const std::exception&) { assert(0); continue; } if (odt_now - dd > dts_delete) { sql.Format(" DROP TABLE [%s] ", tablename); CDBConnectPool::Instance()->DBExecuteSQL(sql); } else { break; } } } } //删除200天的数据 if (bClear) { if (bForceClear) temp_reserve = temp_reserve / 2; COleDateTimeSpan dts_delete(temp_reserve, 0, 0, 0); COdbcStatement stmt; CString sql = "select name from sys.tables where name like 'rm_temphumidity_%';"; if (CDBConnectPool::Instance()->DBQuery(stmt, sql)) { char tablename[50]; stmt.BindCharCol(1, tablename, sizeof(tablename)); while (true) { memset(tablename, 0, sizeof(tablename)); if (stmt.FetchNext() != 0) { break; } if (strlen(tablename) < 22) { assert(0); continue; } COleDateTime dd; try { auto a = atoi(CString(tablename + 16, 4)); auto b = atoi(CString(tablename + 20, 2)); dd = COleDateTime(atoi(CString(tablename + 16, 4)), atoi(CString(tablename + 20, 2)), 28, 0, 0, 0); } catch (const std::exception&) { assert(0); continue; } if (odt_now - dd > dts_delete) { sql.Format(" DROP TABLE %s ", tablename); CDBConnectPool::Instance()->DBExecuteSQL(sql); } else { break; } } } } { CTime ctTime(stNow); CString sql; sql.Format("DELETE rm_record WHERE time < %I64d", (ctTime - CTimeSpan(366, 0, 0, 0)).GetTime()); auto ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); } //5小时检测一次 #ifdef _DEBUG for (auto i = 0; i < 60; i++) #else for (auto i = 0; i < 18000; i++) #endif // _DEBUG if (pService->m_bWork) Sleep(1); else goto l; } while (pService->m_bWork); l: SPDLOG_INFO("ThreadProcCreateTable 线程结束!"); } //获取E盘剩余容量,返回值以GB为单位 double Get_E_DiskRemainingSpace() { DWORD64 qwFreeBytes, qwFreeBytesTocaller, qwTotalBytes; GetDiskFreeSpaceEx(TEXT("e:"), (PULARGE_INTEGER)&qwFreeBytesTocaller, (PULARGE_INTEGER)&qwTotalBytes, (PULARGE_INTEGER)&qwFreeBytes); double RemainingSpace = qwFreeBytes / 1024 / 1024 / 1024; return RemainingSpace; } void CAppService::ThreadProcForSpace(DWORD_PTR param) { CAppService* pThis = (CAppService*)param; //刚开始运行,停止一分钟 std::this_thread::sleep_for(std::chrono::seconds(20)); do { std::this_thread::sleep_for(std::chrono::milliseconds(950)); auto ttNow = chrono::system_clock::to_time_t(chrono::system_clock::now()); if (ttNow % pThis->m_nInterval) continue; if (ttNow == pThis->m_tmLastSpaceTime) continue; pThis->m_tmLastSpaceTime = ttNow; auto e_disk_space = Get_E_DiskRemainingSpace(); if (e_disk_space < 100 && pThis->m_bWork) { auto json = R"({"cmd":"disk_alarm","code":200,"msg":"磁盘余量告警,还剩 )" + fmt::format("{:.1f}", e_disk_space) + " GB.\"}"; auto utf = ANSItoUTF8(json); if (pThis->GetMgServer()) pThis->GetMgServer()->SendToAllClient(utf.c_str(), utf.length()); } } while (pThis->m_bWork); } CAppService CAppService::obj; httplib::Server CAppService::m_svr;