AppService.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. #include "stdafx.h"
  2. #include "AppService.h"
  3. #include <ODBC/DBConnectPool.h>
  4. #include "MonitorObject.h"
  5. #include "httplib.h"
  6. #include <Simplelog.h>
  7. #include <gbk2utf8.h>
  8. #include <jsonxx.h>
  9. #include "Device.h"
  10. #include "ResistAlarm.h"
  11. #ifdef _DEBUG
  12. #pragma comment(lib, "HJ_ACE650d.lib")
  13. #pragma message("Automatically linking with aced.dll")
  14. #else
  15. #pragma comment(lib, "HJ_ACE650.lib")
  16. #pragma message("Automatically linking with ace.dll")
  17. #endif
  18. bool g_bLog;
  19. time_t g_stStart; //程序启动的时间
  20. string g_strExepath; //程序目录
  21. string g_strVersion; //程序版本
  22. void tagFileData::Join()
  23. {
  24. delete this;
  25. }
  26. CAppService::CAppService()
  27. {
  28. AfxSocketInit();
  29. ACE::init();
  30. SPDLOG_INFO("ACE init.");
  31. }
  32. CAppService::~CAppService()
  33. {
  34. SPDLOG_INFO("ACE fini");
  35. ACE::fini();
  36. AfxSocketTerm();
  37. }
  38. bool CAppService::Start()
  39. {
  40. //string str = R"({"id":"100000","name":"国铁集团","type":"group","up":"100000")";
  41. //jsonxx::Object o;
  42. //o.parse(str);
  43. //auto r = o.empty();
  44. SYSTEM_INFO sysinfo;
  45. GetSystemInfo(&sysinfo);
  46. g_strExepath = hjfunc_GetAppDir();
  47. g_strVersion = hjfunc_GetVersion();
  48. auto strPath = CSimpleLog::GetAppDir() + "svg";
  49. if (CSimpleLog::PathFileExistsA(strPath) == FALSE)
  50. CreateDirectory(strPath, nullptr);
  51. strPath = CSimpleLog::GetAppDir() + "refer";
  52. if (CSimpleLog::PathFileExistsA(strPath) == FALSE)
  53. CreateDirectory(strPath, nullptr);
  54. m_strIniPath = CSimpleLog::GetAppDir() + "DataCenter.ini";
  55. char szTemp[100] = { 0 };
  56. CString m_strDriver = "ODBC Driver 11 for SQL Server";
  57. CString m_strDataSource = "127.0.0.1,21009";
  58. CString m_strCataLog = "RMDB0571";
  59. CString m_strUserID = "zljc";
  60. CString m_strPassWD = "Zljc123!@#";
  61. int port = 10086;
  62. ::GetPrivateProfileStringA("ODBC", "DRIVER", CStringA(m_strDriver), szTemp, sizeof(szTemp), m_strIniPath);
  63. m_strDriver = CString(szTemp);
  64. ::GetPrivateProfileStringA("ODBC", "SERVER", CStringA(m_strDataSource), szTemp, sizeof(szTemp), m_strIniPath);
  65. m_strDataSource = CString(szTemp);
  66. ::GetPrivateProfileStringA("ODBC", "UID", CStringA(m_strUserID), szTemp, sizeof(szTemp), m_strIniPath);
  67. m_strUserID = CString(szTemp);
  68. ::GetPrivateProfileStringA("ODBC", "PWD", CStringA(m_strPassWD), szTemp, sizeof(szTemp), m_strIniPath);
  69. m_strPassWD = CString(szTemp);
  70. ::GetPrivateProfileStringA("ODBC", "DATABASE", CStringA(m_strCataLog), szTemp, sizeof(szTemp), m_strIniPath);
  71. m_strCataLog = CString(szTemp);
  72. port = ::GetPrivateProfileInt("SET", "port", port, m_strIniPath);
  73. ::WritePrivateProfileStringA("ODBC", "DRIVER", CStringA(m_strDriver), m_strIniPath);
  74. ::WritePrivateProfileStringA("ODBC", "SERVER", CStringA(m_strDataSource), m_strIniPath);
  75. ::WritePrivateProfileStringA("ODBC", "DATABASE", CStringA(m_strCataLog), m_strIniPath);
  76. ::WritePrivateProfileString("ODBC", "UID", m_strUserID, m_strIniPath);
  77. //::WritePrivateProfileString("ODBC", "PWD", m_strPassWD, m_strIniPath);
  78. ::WritePrivateProfileStringA("SET", "port", (to_string(port) + " #Websocket 端口").c_str(), m_strIniPath);
  79. //ODBC
  80. if (CDBConnectPool::Instance()->Init(m_strDriver, m_strDataSource, m_strUserID, m_strPassWD, m_strCataLog, 5) == FALSE)
  81. {
  82. ASSERT(0);
  83. SPDLOG_CRITICAL("数据库连接池初始化失败{}:{}:{}:{}:{}", m_strDriver, m_strDataSource, m_strCataLog, m_strUserID, m_strPassWD);
  84. return false;
  85. }
  86. //升级
  87. {
  88. CString sql;
  89. BOOL ret;
  90. sql = "if not exists (select 1 from [rm_mo] where [id] = '100000' )\
  91. BEGIN\
  92. INSERT INTO [rm_mo] ([id],[type],[up],[name],[updatetime]) VALUES ('100000' ,'group' ,'100000', '国铁集团',GETDATE());\
  93. END";
  94. ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  95. sql = "if not exists (select 1 from [rm_user] where [username] = 'system' )\
  96. BEGIN\
  97. 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','','');\
  98. END";
  99. ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  100. /*
  101. sql = "select top 1 event_id from rm_alarm";
  102. ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  103. if (true != ret)
  104. {
  105. sql = "alter table rm_alarm add event_id char(36) null default newid();\
  106. alter table rm_alarm add rel_id char(36) null default ''; ";
  107. ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  108. sql = "UPDATE [rm_alarm] SET [event_id]=NEWID() WHERE [event_id] is null;\
  109. UPDATE [rm_alarm] SET [rel_id]='' WHERE [rel_id] is null;";
  110. ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  111. }
  112. */
  113. /*
  114. sql = "SELECT top 1 module FROM rm_record";
  115. ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  116. if (TRUE != ret)
  117. {
  118. sql = "create table rm_record (\
  119. module tinyint not null,\
  120. dura int not null,\
  121. analyze_type tinyint null,\
  122. station nvarchar(50) not null,\
  123. station_name nvarchar(50) not null,\
  124. mo varchar(20) null,\
  125. mo_name varchar(20) null,\
  126. mp varchar(20) null,\
  127. mp_name varchar(20) null,\
  128. start_time bigint not null,\
  129. end_time bigint null,\
  130. time bigint not null,\
  131. name nvarchar(50) not null,\
  132. username varchar(50) not null,\
  133. opt smallint not null,\
  134. mark nvarchar(100) null default ''\
  135. );\
  136. create clustered index IDX_STATION on rm_record(\
  137. station_name ASC,\
  138. time DESC\
  139. );\
  140. create index IDX_TIME on rm_record(\
  141. time DESC\
  142. );";
  143. ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  144. if (ret != TRUE)
  145. SPDLOG_ERROR("语句执行错误:{}", sql);
  146. }
  147. */
  148. }
  149. m_bWork = true;
  150. m_pCreateTableThread = new std::thread(CAppService::ThreadProcCreateTable, (DWORD_PTR)this);
  151. Sleep(50);
  152. //加载设备
  153. CDeviceMng::Instance()->LoadDevice();
  154. //加载机构
  155. if (!CMonitorObjectMng::Instance()->LoadMonitorTree())
  156. {
  157. ASSERT(0);
  158. SPDLOG_CRITICAL("LoadMonitorTree Fail.");
  159. return false;
  160. }
  161. else
  162. {
  163. //CMonitorObjectMng::Instance()->LoadHistoryData();
  164. }
  165. //加载报警
  166. CResistAlarmMng::Instance()->Start();
  167. Sleep(50);
  168. //开启与dataservices 通信端口 10090
  169. m_pProactorTask = new CProactorTask;
  170. m_pProactorTask->start(4);
  171. m_pHandle = new CLNHandle;
  172. m_pAcceptor = new CLNAcceptor(m_pHandle);
  173. //if (m_pAcceptor->listen(10090) == -1)
  174. //{
  175. // SPDLOG_CRITICAL("端口{} tcp 监听失败", 10090);
  176. // return false;
  177. //}
  178. if (m_pAcceptor->Start() == FALSE)
  179. {
  180. SPDLOG_CRITICAL("CLNAcceptor 启动失败");
  181. return false;
  182. }
  183. m_bRun = true;
  184. //磁盘空间检测
  185. m_pThreadSpace = new std::thread(CAppService::ThreadProcForSpace, (DWORD_PTR)this);
  186. //与外部链接放到最后
  187. //开启新的websocket
  188. m_mgServer = new CMGWSServer;
  189. if (!m_mgServer->Start(port))//10086
  190. {
  191. ASSERT(0);
  192. SPDLOG_CRITICAL("websocket {} 端口监听失败", port);
  193. return false;
  194. }
  195. m_pHttpThread = new std::thread(CAppService::ThreadProcForHTTP, (DWORD_PTR)this);//10088
  196. //if (!m_pUdpSocket->Open(10090, NULL, 0, NULL))
  197. //{
  198. // ASSERT(0);
  199. // SPDLOG_CRITICAL("UDP {} 端口监听失败", 10090);
  200. // return false;
  201. //}
  202. if (m_pAcceptor->listen(10090) == -1)
  203. {
  204. SPDLOG_CRITICAL("端口{} tcp 监听失败", 10090);
  205. return false;
  206. }
  207. time(&g_stStart);
  208. SPDLOG_INFO("app start succ.");
  209. return true;
  210. }
  211. void CAppService::Stop()
  212. {
  213. SPDLOG_INFO("停止服务");
  214. m_bRun = false;
  215. m_bWork = false;
  216. //关闭外部链接
  217. if (m_pAcceptor) m_pAcceptor->ClearAllContexts();
  218. if (m_pProactorTask) m_pProactorTask->stop();
  219. if (m_mgServer) m_mgServer->Stop();
  220. //关闭线程
  221. if (m_pThreadSpace)
  222. {
  223. m_pThreadSpace->join();
  224. delete m_pThreadSpace;
  225. m_pThreadSpace = nullptr;
  226. }
  227. if (m_pCreateTableThread)
  228. {
  229. m_pCreateTableThread->join();
  230. delete m_pCreateTableThread;
  231. m_pCreateTableThread = nullptr;
  232. }
  233. if (m_pHttpThread)
  234. {
  235. m_svr.stop();
  236. m_pHttpThread->join();
  237. delete m_pHttpThread;
  238. m_pHttpThread = nullptr;
  239. }
  240. //if (m_pUdpSocket)
  241. //{
  242. // m_pUdpSocket->Close();
  243. // delete m_pUdpSocket;
  244. // m_pUdpSocket = nullptr;
  245. //}
  246. CResistAlarmMng::Instance()->Stop();
  247. //if (m_lwsServer)
  248. //{
  249. // m_lwsServer->Stop();
  250. // delete m_lwsServer;
  251. // m_lwsServer = nullptr;
  252. //}
  253. if (m_mgServer)
  254. {
  255. delete m_mgServer;
  256. m_mgServer = nullptr;
  257. }
  258. if (m_pHandle)
  259. {
  260. m_pHandle->Close();
  261. delete m_pHandle;
  262. m_pHandle = nullptr;
  263. }
  264. if (m_pAcceptor)
  265. {
  266. delete m_pAcceptor;
  267. m_pAcceptor = nullptr;
  268. }
  269. if (m_pProactorTask)
  270. {
  271. delete m_pProactorTask;
  272. m_pProactorTask = nullptr;
  273. }
  274. CDBConnectPool::Instance()->Clear();
  275. }
  276. BOOL CAppService::FileDataConvertCharData(const uint8_t* filedata, const int filelen, char* strData)
  277. {
  278. if (strData == nullptr) return FALSE;
  279. for (auto i = 0; i < filelen; i++)
  280. sprintf_s(strData + i * 2, 3, "%02X", filedata[i]);
  281. return TRUE;
  282. }
  283. #include "HttpPrcess.h"
  284. void CAppService::ThreadProcForHTTP(DWORD_PTR pThis)
  285. {
  286. using namespace httplib;
  287. m_svr.Post("/data/.*", DealHttpPost);
  288. m_svr.Get("/data/.*", DealHttpGet);
  289. auto ret = m_svr.listen("0.0.0.0", 10088);
  290. if (ret == false)
  291. SPDLOG_CRITICAL("HTTP {} 端口监听失败", 10088);
  292. return ;
  293. }
  294. void CAppService::ThreadProcCreateTable(DWORD_PTR pThis)
  295. {
  296. auto pService = (CAppService*)pThis;
  297. SPDLOG_INFO("ThreadProcCreateTable 线程开始!");
  298. do
  299. {
  300. SYSTEMTIME stNow, stTom, stYest;
  301. GetLocalTime(&stNow);
  302. COleDateTime odt_now(stNow);
  303. COleDateTime odt_tom = odt_now + COleDateTimeSpan(1, 0, 0, 0);
  304. COleDateTime odt_yest = odt_now - COleDateTimeSpan(1, 0, 0, 0);
  305. odt_tom.GetAsSystemTime(stTom);
  306. odt_yest.GetAsSystemTime(stYest);
  307. CString tableName;
  308. CString tableNameTom;
  309. CString tableNameYest;
  310. tableName.Format("rm_resistance_%04d%02d%02d", stNow.wYear, stNow.wMonth, stNow.wDay, stNow.wHour, stNow.wMinute, stNow.wSecond);
  311. tableNameTom.Format("rm_resistance_%04d%02d%02d", stTom.wYear, stTom.wMonth, stTom.wDay, stTom.wHour, stTom.wMinute, stTom.wSecond);
  312. tableNameYest.Format("rm_resistance_%04d%02d%02d", stYest.wYear, stYest.wMonth, stYest.wDay, stYest.wHour, stYest.wMinute, stYest.wSecond);
  313. CString existsql = CString("select top 1 id from sysobjects where name = '") + tableName + "' and type = 'U';";
  314. CString existsqlTom = CString("select top 1 id from sysobjects where name = '") + tableNameTom + "' and type = 'U';";
  315. CString existsqlYest = CString("select top 1 id from sysobjects where name = '") + tableNameYest + "' and type = 'U';";
  316. CString tablesqltoday = CString("create table ") + tableName + " (\n" +
  317. " momp varchar(50) not null,\n" +
  318. " acquisitiontime datetime not null,\n" +
  319. " data0 int null,\n" +
  320. " data1 int null,\n" +
  321. " data2 int null\n" +
  322. ");" +
  323. "create unique clustered index IDX_TIME on " + tableName + " (\n" +
  324. "momp ASC,\n" +
  325. "acquisitiontime ASC\n" +
  326. ")";
  327. CString tablesqlTom = "create table " + tableNameTom + " (\n" +
  328. " momp varchar(50) not null,\n" +
  329. " acquisitiontime datetime not null,\n" +
  330. " data0 int null,\n" +
  331. " data1 int null,\n" +
  332. " data2 int null\n" +
  333. ");" +
  334. "create unique clustered index IDX_TIME on " + tableNameTom + " (\n" +
  335. "momp ASC,\n" +
  336. "acquisitiontime ASC\n" +
  337. ")";
  338. CString tableYest = "create table " + tableNameYest + " (\n" +
  339. " momp varchar(50) not null,\n" +
  340. " acquisitiontime datetime not null,\n" +
  341. " data0 int null,\n" +
  342. " data1 int null,\n" +
  343. " data2 int null\n" +
  344. ");" +
  345. "create unique clustered index IDX_TIME on " + tableNameYest + " (\n" +
  346. "momp ASC,\n" +
  347. "acquisitiontime ASC\n" +
  348. ")";
  349. COdbcStatement stmt;
  350. CDBConnectPool::Instance()->DBQuery(stmt, existsql);
  351. int id = 0;
  352. stmt.BindIntCol(1, &id);
  353. if (stmt.FetchNext() != 0)
  354. {
  355. //不存在
  356. if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqltoday))
  357. SPDLOG_ERROR("数据库执行错误:{}", tablesqltoday);
  358. }
  359. stmt.Close();
  360. COdbcStatement stmtTom;
  361. CDBConnectPool::Instance()->DBQuery(stmtTom, existsqlTom);
  362. stmtTom.BindIntCol(1, &id);
  363. if (stmtTom.FetchNext() != 0)
  364. {
  365. //不存在
  366. if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqlTom))
  367. SPDLOG_ERROR("数据库执行错误:{}", tablesqlTom);
  368. }
  369. stmtTom.Close();
  370. COdbcStatement stmtYest;
  371. CDBConnectPool::Instance()->DBQuery(stmtYest, existsqlYest);
  372. stmtYest.BindIntCol(1, &id);
  373. if (stmtYest.FetchNext() != 0)
  374. {
  375. //不存在
  376. if (!CDBConnectPool::Instance()->DBExecuteSQL(tableYest))
  377. SPDLOG_ERROR("数据库执行错误:{}", tableYest);
  378. }
  379. stmtYest.Close();
  380. //temperature
  381. tableName.Format("rm_temphumidity_%04d%02d", stNow.wYear, stNow.wMonth, stNow.wDay, stNow.wHour, stNow.wMinute);
  382. tableNameTom.Format("rm_temphumidity_%04d%02d", stTom.wYear, stTom.wMonth, stTom.wDay, stTom.wHour, stTom.wMinute);
  383. existsql = CString("select top 1 id from sysobjects where name = '") + tableName + "' and type = 'U';";
  384. existsqlTom = CString("select top 1 id from sysobjects where name = '") + tableNameTom + "' and type = 'U';";
  385. tablesqltoday = CString("create table ") + tableName + " (\n" +
  386. " mo varchar(25) not null,\n" +
  387. " mp varchar(5) not null,\n" +
  388. " acquisitiontime datetime not null,\n" +
  389. " temperature int not null,\n" +
  390. " humidity int not null\n" +
  391. ");" +
  392. "create unique clustered index IDX_IMEI on " + tableName + " (\n" +
  393. "mo ASC, mp ASC, acquisitiontime ASC)";
  394. CDBConnectPool::Instance()->DBQuery(stmt, existsql);
  395. stmt.BindIntCol(1, &id);
  396. if (stmt.FetchNext() != 0)
  397. {
  398. //不存在
  399. if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqltoday))
  400. SPDLOG_ERROR("数据库执行错误:{}", tablesqltoday);
  401. }
  402. stmt.Close();
  403. if (stNow.wMonth != stTom.wMonth || stNow.wYear != stTom.wYear)
  404. {
  405. CDBConnectPool::Instance()->DBQuery(stmt, existsqlTom);
  406. stmt.BindIntCol(1, &id);
  407. if (stmt.FetchNext() != 0)
  408. {
  409. //不存在
  410. tablesqlTom = CString("create table ") + tableNameTom + " (\n" +
  411. " mo varchar(50) not null,\n" +
  412. " acquisitiontime datetime not null,\n" +
  413. " temperature int not null,\n" +
  414. " humidity int not null\n" +
  415. ");" +
  416. "create unique clustered index IDX_IMEI on " + tableNameTom + " (\n" +
  417. "mo ASC,\n" +
  418. "acquisitiontime ASC\n" +
  419. ")";
  420. if (!CDBConnectPool::Instance()->DBExecuteSQL(tablesqlTom))
  421. SPDLOG_ERROR("数据库执行错误:{}", tablesqlTom);
  422. }
  423. stmt.Close();
  424. }
  425. //扳动记录表
  426. {
  427. SYSTEMTIME lastSt;
  428. memcpy(&lastSt, &stNow, sizeof(SYSTEMTIME));
  429. move_today:
  430. string table_today = fmt::format("rm_move_{:0>4}{:0>2}", lastSt.wYear, lastSt.wMonth);
  431. COdbcStatement stmt;
  432. CDBConnectPool::Instance()->DBQuery(stmt, CString(fmt::format("select top 1 id from sysobjects where name = '{}' and type = 'U'; ", table_today).c_str()));
  433. int id = 0;
  434. stmt.BindIntCol(1, &id);
  435. if (stmt.FetchNext() != 0)
  436. {
  437. CString strSql = fmt::format("create table {0} (\
  438. mo varchar(20) not null,\
  439. mp varchar(20) not null,\
  440. show_time datetime not null,\
  441. start_time datetime null,\
  442. end_time datetime null,\
  443. curr_val int null,\
  444. show_val int not null,\
  445. idx tinyint null,\
  446. posi tinyint not null,\
  447. mark nvarchar(255) null\
  448. );create unique clustered index IDX_MO_MP on {0}(mo ASC,mp ASC,show_time ASC);", table_today).c_str();
  449. //不存在
  450. if (!CDBConnectPool::Instance()->DBExecuteSQL(strSql))
  451. SPDLOG_ERROR("数据库执行错误:{}", strSql);
  452. }
  453. stmt.Close();
  454. if (lastSt.wYear != stTom.wYear || lastSt.wMonth != stTom.wMonth)
  455. {
  456. memcpy(&lastSt, &stTom, sizeof(SYSTEMTIME));
  457. goto move_today;
  458. }
  459. auto move_reserve = ::GetPrivateProfileInt("SET", "move_reserve", 730, pService->m_strIniPath);
  460. if (move_reserve < 90) move_reserve = 90;
  461. ::WritePrivateProfileStringA("SET", "move_reserve", fmt::format("{} 天 #转换过程记录保留天数, 默认730天, 20230701起", move_reserve).c_str(), pService->m_strIniPath);
  462. static bool bExec_rm_move = true;
  463. COleDateTimeSpan dts_delete(move_reserve, 0, 0, 0);
  464. CString sql = "select name from sys.tables where name like 'rm_move_%' ORDER BY name;";
  465. if (CDBConnectPool::Instance()->DBQuery(stmt, sql)) {
  466. char tablename[50];
  467. stmt.BindCharCol(1, tablename, sizeof(tablename));
  468. while (true)
  469. {
  470. memset(tablename, 0, sizeof(tablename));
  471. if (stmt.FetchNext() != 0) {
  472. break;
  473. }
  474. if (strlen(tablename) < 14)
  475. {
  476. assert(0);
  477. continue;
  478. }
  479. COleDateTime dd;
  480. try
  481. {
  482. int year, month;
  483. sscanf_s(tablename, "rm_move_%04d%02d", &year, &month);
  484. dd = COleDateTime(year, month, 1, 0, 0, 0);
  485. }
  486. catch (const std::exception&)
  487. {
  488. assert(0);
  489. continue;
  490. }
  491. if (odt_now - dd > dts_delete)
  492. {
  493. sql.Format(" DROP TABLE %s ", tablename);
  494. CDBConnectPool::Instance()->DBExecuteSQL(sql);
  495. }
  496. else
  497. {
  498. if (bExec_rm_move == false) break;
  499. CString qq = CString("SELECT end_time FROM ") + tablename;
  500. if (CDBConnectPool::Instance()->DBExecuteSQL(qq) == FALSE)
  501. {
  502. qq.Format("ALTER TABLE %s ADD end_time datetime null;", tablename);
  503. CDBConnectPool::Instance()->DBExecuteSQL(qq);
  504. qq.Format("UPDATE rm_move_202301 SET end_time = 0 where end_time is null;", tablename);
  505. CDBConnectPool::Instance()->DBExecuteSQL(qq);
  506. }
  507. }
  508. }
  509. stmt.Close();
  510. bExec_rm_move = false;
  511. }
  512. }
  513. ULARGE_INTEGER FreeBytesAvailableToCaller, TotalNumberOfBytes, TotalNumberOfFreeBytes;
  514. if (!GetDiskFreeSpaceEx("E:", &FreeBytesAvailableToCaller,
  515. &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
  516. continue;
  517. auto dwCurLeftDisk = DWORD(FreeBytesAvailableToCaller.QuadPart >> 20);
  518. auto idle_reserve = ::GetPrivateProfileInt("SET", "idle_reserve", 20, pService->m_strIniPath);
  519. if (idle_reserve < 5) idle_reserve = 5;
  520. ::WritePrivateProfileStringA("SET", "idle_reserve", fmt::format("{} GB #E盘闲置空间, 默认20GB, 20230701起", idle_reserve).c_str(), pService->m_strIniPath);
  521. BOOL bClear = (dwCurLeftDisk < idle_reserve * 1024); BOOL bForceClear = (dwCurLeftDisk < 3 * 1024);
  522. auto resist_reserve = ::GetPrivateProfileInt("SET", "resist_reserve", 365, pService->m_strIniPath);
  523. if (resist_reserve < 30) resist_reserve = 30;
  524. ::WritePrivateProfileStringA("SET", "resist_reserve", fmt::format("{} 天 #阻力数据保留天数, 默认365天, 20230701起", resist_reserve).c_str(), pService->m_strIniPath);
  525. auto temp_reserve = ::GetPrivateProfileInt("SET", "temp_reserve", 365, pService->m_strIniPath);
  526. if (temp_reserve < 30) temp_reserve = 30;
  527. ::WritePrivateProfileStringA("SET", "temp_reserve", fmt::format("{} 天 #温湿度数据保留天数, 默认365天, 20230701起", temp_reserve).c_str(), pService->m_strIniPath);
  528. //删除365天前的数据
  529. if (bClear)
  530. {
  531. if (bForceClear) resist_reserve = resist_reserve / 2;
  532. COleDateTimeSpan dts_delete(resist_reserve, 0, 0, 0);
  533. COdbcStatement stmt;
  534. CString sql = "select name from sys.tables where name like 'rm_resistance_%' ORDER BY name;";
  535. if (CDBConnectPool::Instance()->DBQuery(stmt, sql)) {
  536. char tablename[50];
  537. stmt.BindCharCol(1, tablename, sizeof(tablename));
  538. while (true)
  539. {
  540. memset(tablename, 0, sizeof(tablename));
  541. if (stmt.FetchNext() != 0) {
  542. break;
  543. }
  544. if (strlen(tablename) < 22)
  545. {
  546. assert(0);
  547. continue;
  548. }
  549. COleDateTime dd;
  550. try
  551. {
  552. dd = COleDateTime(atoi(CString(tablename + 14, 4)), atoi(CString(tablename + 18, 2)), atoi(CString(tablename + 20, 2)), 0, 0, 0);
  553. }
  554. catch (const std::exception&)
  555. {
  556. assert(0);
  557. continue;
  558. }
  559. if (odt_now - dd > dts_delete)
  560. {
  561. sql.Format(" DROP TABLE [%s] ", tablename);
  562. CDBConnectPool::Instance()->DBExecuteSQL(sql);
  563. }
  564. else
  565. {
  566. break;
  567. }
  568. }
  569. }
  570. }
  571. //删除200天的数据
  572. if (bClear)
  573. {
  574. if (bForceClear) temp_reserve = temp_reserve / 2;
  575. COleDateTimeSpan dts_delete(temp_reserve, 0, 0, 0);
  576. COdbcStatement stmt;
  577. CString sql = "select name from sys.tables where name like 'rm_temphumidity_%';";
  578. if (CDBConnectPool::Instance()->DBQuery(stmt, sql)) {
  579. char tablename[50];
  580. stmt.BindCharCol(1, tablename, sizeof(tablename));
  581. while (true)
  582. {
  583. memset(tablename, 0, sizeof(tablename));
  584. if (stmt.FetchNext() != 0) {
  585. break;
  586. }
  587. if (strlen(tablename) < 22)
  588. {
  589. assert(0);
  590. continue;
  591. }
  592. COleDateTime dd;
  593. try
  594. {
  595. auto a = atoi(CString(tablename + 16, 4));
  596. auto b = atoi(CString(tablename + 20, 2));
  597. dd = COleDateTime(atoi(CString(tablename + 16, 4)), atoi(CString(tablename + 20, 2)), 28, 0, 0, 0);
  598. }
  599. catch (const std::exception&)
  600. {
  601. assert(0);
  602. continue;
  603. }
  604. if (odt_now - dd > dts_delete)
  605. {
  606. sql.Format(" DROP TABLE %s ", tablename);
  607. CDBConnectPool::Instance()->DBExecuteSQL(sql);
  608. }
  609. else
  610. {
  611. break;
  612. }
  613. }
  614. }
  615. }
  616. {
  617. CTime ctTime(stNow);
  618. CString sql;
  619. sql.Format("DELETE rm_record WHERE time < %I64d", (ctTime - CTimeSpan(366, 0, 0, 0)).GetTime());
  620. auto ret = CDBConnectPool::Instance()->DBExecuteSQL(sql);
  621. }
  622. //5小时检测一次
  623. #ifdef _DEBUG
  624. for (auto i = 0; i < 60; i++)
  625. #else
  626. for (auto i = 0; i < 18000; i++)
  627. #endif // _DEBUG
  628. if (pService->m_bWork)
  629. Sleep(1);
  630. else
  631. goto l;
  632. } while (pService->m_bWork);
  633. l:
  634. SPDLOG_INFO("ThreadProcCreateTable 线程结束!");
  635. }
  636. //获取E盘剩余容量,返回值以GB为单位
  637. double Get_E_DiskRemainingSpace()
  638. {
  639. DWORD64 qwFreeBytes, qwFreeBytesTocaller, qwTotalBytes;
  640. GetDiskFreeSpaceEx(TEXT("e:"), (PULARGE_INTEGER)&qwFreeBytesTocaller, (PULARGE_INTEGER)&qwTotalBytes, (PULARGE_INTEGER)&qwFreeBytes);
  641. double RemainingSpace = qwFreeBytes / 1024 / 1024 / 1024;
  642. return RemainingSpace;
  643. }
  644. void CAppService::ThreadProcForSpace(DWORD_PTR param)
  645. {
  646. CAppService* pThis = (CAppService*)param;
  647. //刚开始运行,停止一分钟
  648. std::this_thread::sleep_for(std::chrono::seconds(20));
  649. do
  650. {
  651. std::this_thread::sleep_for(std::chrono::milliseconds(950));
  652. auto ttNow = chrono::system_clock::to_time_t(chrono::system_clock::now());
  653. if (ttNow % pThis->m_nInterval) continue;
  654. if (ttNow == pThis->m_tmLastSpaceTime) continue;
  655. pThis->m_tmLastSpaceTime = ttNow;
  656. auto e_disk_space = Get_E_DiskRemainingSpace();
  657. if (e_disk_space < 100 && pThis->m_bWork)
  658. {
  659. auto json = R"({"cmd":"disk_alarm","code":200,"msg":"磁盘余量告警,还剩 )" + fmt::format("{:.1f}", e_disk_space) + " GB.\"}";
  660. auto utf = ANSItoUTF8(json);
  661. if (pThis->GetMgServer()) pThis->GetMgServer()->SendToAllClient(utf.c_str(), utf.length());
  662. }
  663. } while (pThis->m_bWork);
  664. }
  665. CAppService CAppService::obj;
  666. httplib::Server CAppService::m_svr;