SPAServer.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. #include "SPAServer.h"
  2. #include "spdlog/spdlog.h"
  3. #include <filesystem>
  4. #include "ThreadPool/ThreadPool.h"
  5. #include "GlobalInfo/GlobalVariable.h"
  6. #include "GlobalInfo/GlobalConfig.h"
  7. #include "UniversalFunc.h"
  8. #include "FuncOrdinary.h"
  9. #include "FuncIllegalInvasion.h"
  10. #include "FuncOnAndOffWork.h"
  11. #include "FuncRegionalPerson.h"
  12. #include "GlobalFuncThread.h"
  13. #include <QCoreApplication>
  14. SPAServer::SPAServer()
  15. {
  16. m_logger = spdlog::get("SPAServer");
  17. if(m_logger == nullptr)
  18. {
  19. SPDLOG_ERROR("APAServer logger is nullptr");
  20. return;
  21. }
  22. m_threadRunning = true;
  23. /* 初始化WebAPI */
  24. // m_fromWebAPI.initWebApi("http://192.1.3.133:31000/v6/", "", "4c2f9fc91c22dd98331e47af2e2964f4");
  25. /* 模拟违禁品算法ID,后续需要动态调整 */
  26. // GVariable.ActContraband = "OD210_026_005246_001-IZRTKyEx";
  27. }
  28. SPAServer::~SPAServer()
  29. {
  30. }
  31. /* 启动服务 */
  32. void SPAServer::startServer()
  33. {
  34. /* 设置全局运行标志位 */
  35. GThreadInfo.setRunning(true);
  36. /* 添加获取基础信息的线程 */
  37. CPPTP.add_task(&SPAServer::threadFromSuperBrain, this);
  38. // threadFromSuperBrain();
  39. /* 延时启动任务分配线程 */
  40. std::this_thread::sleep_for(std::chrono::seconds(2));
  41. /* 添加分配任务的线程 */
  42. CPPTP.add_task(&SPAServer::threadDistribution, this);
  43. // threadDistribution();
  44. /* 测试Redis读取并解析数据线程 */
  45. }
  46. /**
  47. * @brief 从基础平台获取算法信息和设备信息的线程函数
  48. * 从基础平台获取算法信息和设备信息,然后更新到EQM数据库所对应的表中
  49. *
  50. */
  51. void SPAServer::threadFromSuperBrain()
  52. {
  53. SPDLOG_LOGGER_INFO(m_logger, "开启 fromSuperBrainThread 线程, 获取算法和设备信息");
  54. /* 创建变量 */
  55. std::vector<AlgorithmInfo> vecAlgNewInfo;
  56. std::vector<DeviceInfo> vecDevNewInfo;
  57. /* 初始化WebAPI */
  58. if(!m_fromWebAPIUseSB.initWebApi(GConfig.webapiUrl(), GConfig.webapiKey(), GConfig.webapiAppType()))
  59. {
  60. SPDLOG_LOGGER_ERROR(m_logger, "threadFromSuperBrain线程初始化WebAPI失败");
  61. return;
  62. }
  63. /* 初始化SuperBrain */
  64. m_fromSuperBrain.initSuperBrain(GConfig.superBrainUrl(), GConfig.superBrainAppKey(), GConfig.superBrainAppSecret());
  65. /* 获取一次Token,这玩意好像不是必须的 */
  66. if(!m_fromSuperBrain.getToken())
  67. {
  68. SPDLOG_LOGGER_ERROR(m_logger, "FromSuperBrain线程获取Token失败");
  69. return;
  70. }
  71. while (m_threadRunning)
  72. {
  73. SPDLOG_LOGGER_INFO(m_logger, "----------------- 刷新算法和设备信息 -----------------");
  74. /* 先更新数据库的信息,防止从其他地方更改了数据库,这里没有刷新本地缓存 */
  75. m_fromWebAPIUseSB.getAlgorithmInfo(m_vecEqmAlgInfo);
  76. m_fromWebAPIUseSB.getDeviceInfo(m_vecEqmDevInfo);
  77. m_fromWebAPIUseSB.getDeviceAlgorithmInfo(m_vecEqmDevInfo, m_listDevIDDelete);
  78. /* 从超脑获取基础信息 */
  79. // m_fromSuperBrain.getTaskTypeList(vecAlgNewInfo);
  80. m_fromSuperBrain.getDeviceList(vecDevNewInfo);
  81. // SPDLOG_LOGGER_INFO(m_logger, "获取到的设备信息数量: {}", vecDevNewInfo.size());
  82. /* 将设备返回的算法ID替换成带有后缀的全ID(现在不需要后缀了) */
  83. // checkAlgorithmID(vecDevNewInfo);
  84. /* 处理算法信息,算法信息不需要在服务里处理了,在外部手动处理 */
  85. // bool algIsUpdate = processAlgorithmInfo(vecAlgNewInfo);
  86. /* 处理设备信息 */
  87. bool devIsUpdate = processDeviceInfo(vecDevNewInfo);
  88. if(!devIsUpdate)
  89. {
  90. SPDLOG_LOGGER_INFO(m_logger, "设备信息和算法信息没有更新");
  91. }
  92. vecAlgNewInfo.clear();
  93. vecDevNewInfo.clear();
  94. /* 更新算法详细信息 */
  95. m_mutexActionInfo.lock();
  96. m_fromWebAPIUseSB.getActionInfo(m_listActionInfo);
  97. m_mutexActionInfo.unlock();
  98. /* 20秒更新一次 */
  99. std::this_thread::sleep_for(std::chrono::seconds(GVariable.CheckDeviceTime));
  100. }
  101. SPDLOG_LOGGER_INFO(m_logger, "退出 fromSuperBrainThread 线程");
  102. }
  103. /* 替换算法ID为全ID */
  104. // void SPAServer::checkAlgorithmID(std::vector<DeviceInfo>& vecDevInfo)
  105. // {
  106. // /* 替换算法ID为全ID */
  107. // for(auto& dev : vecDevInfo)
  108. // {
  109. // for(auto act = dev.vecAlgorithmInfo.begin(); act != dev.vecAlgorithmInfo.end(); act++)
  110. // {
  111. // /* 替换算法ID为全ID */
  112. // std::string strFullID = GVariable.getFullActionID(act->ActionID);
  113. // if(strFullID.empty())
  114. // {
  115. // SPDLOG_LOGGER_INFO(m_logger, "未知的算法ID: {}", act->ActionID);
  116. // /* 删除算法ID */
  117. // // act = dev.vecAlgorithmInfo.erase(act);
  118. // }else {
  119. // /* 替换算法ID */
  120. // act->ActionID = strFullID;
  121. // }
  122. // }
  123. // }
  124. // }
  125. /* 处理算法信息,返回值为true,说明有改变,需要重新读取 */
  126. bool SPAServer::processAlgorithmInfo(std::vector<AlgorithmInfo> vecNewAlgInfo)
  127. {
  128. std::vector<AlgorithmInfo> vecAlgUpdate;
  129. std::vector<AlgorithmInfo> vecAlgDelete;
  130. /* 对比数据库表格信息,这里只有插入和删除,没有更新 */
  131. compareAlgorithmInfo(vecNewAlgInfo, vecAlgUpdate, vecAlgDelete);
  132. /* 更新数据库,先删除,再写入刷新 */
  133. bool isUpdate = false;
  134. if(vecAlgDelete.size() > 0)
  135. {
  136. SPDLOG_LOGGER_DEBUG(m_logger, "删除算法信息");
  137. m_fromWebAPIUseSB.deleteAlgorithmInfo(vecAlgDelete);
  138. isUpdate = true;
  139. }
  140. if(vecAlgUpdate.size() > 0)
  141. {
  142. SPDLOG_LOGGER_DEBUG(m_logger, "写入算法信息");
  143. m_fromWebAPIUseSB.writeAlgorithmInfo(vecAlgUpdate);
  144. isUpdate = true;
  145. }
  146. return isUpdate;
  147. }
  148. /**
  149. * @brief 处理设备信息
  150. *
  151. * @param vecNewDevInfo 传入新获取到的值
  152. * @return true 需要重新读取数据库,获取新的数据
  153. * @return false 无需读取数据库
  154. */
  155. bool SPAServer::processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo)
  156. {
  157. std::vector<DeviceInfo> vecDevInsert;
  158. std::vector<DeviceInfo> vecDevUpdate;
  159. std::vector<DeviceInfo> vecDevDelete;
  160. /*-------------------------------------------------------------------------
  161. ****** 这里只对比设备信息,不对比设备的算法信息,算法信息在下面单独对比 *******
  162. *------------------------------------------------------------------------*/
  163. /* 如果本地缓存没有数据,那么就全部插入 */
  164. if(m_vecEqmDevInfo.size() > 0)
  165. {
  166. for(auto& DevInfo : vecNewDevInfo)
  167. {
  168. bool isExist = false;
  169. for(auto& it0 : m_vecEqmDevInfo)
  170. {
  171. if(DevInfo.DeviceID == it0.DeviceID)
  172. {
  173. isExist = true;
  174. /* 对比其他项是否相等,不相等就更新 */
  175. if(DevInfo == it0)
  176. {
  177. continue;
  178. }else {
  179. vecDevUpdate.push_back(DevInfo);
  180. }
  181. break;
  182. }
  183. }
  184. if(!isExist)
  185. {
  186. vecDevInsert.push_back(DevInfo);
  187. }
  188. }
  189. }else {
  190. vecDevInsert = vecNewDevInfo;
  191. }
  192. /* 获取删除列表 */
  193. if(vecNewDevInfo.size() > 0)
  194. {
  195. bool isExist = false;
  196. for(const auto& it : m_vecEqmDevInfo)
  197. {
  198. isExist = false;
  199. for(const auto& it0 : vecNewDevInfo)
  200. {
  201. if(it.DeviceID == it0.DeviceID)
  202. {
  203. isExist = true;
  204. break;
  205. }
  206. }
  207. if(!isExist)
  208. {
  209. vecDevDelete.push_back(it);
  210. }
  211. }
  212. }else {
  213. vecDevDelete = m_vecEqmDevInfo;
  214. }
  215. bool isUpdate = false;
  216. /* 先删除多余的数据 */
  217. if(vecDevDelete.size() > 0)
  218. {
  219. if(m_fromWebAPIUseSB.deleteDeviceInfo(vecDevDelete))
  220. {
  221. SPDLOG_LOGGER_DEBUG(m_logger,"删除设备信息到 tCamerInfo, 数量:{}",vecDevDelete.size());
  222. isUpdate = true;
  223. }
  224. }
  225. /* 更新数据 */
  226. if(vecDevUpdate.size() > 0)
  227. {
  228. if(m_fromWebAPIUseSB.updateDeviceInfo(vecDevUpdate))
  229. {
  230. SPDLOG_LOGGER_DEBUG(m_logger, "更新设备信息到 tCamerInfo, 数量:{}", vecDevUpdate.size());
  231. isUpdate = true;
  232. }
  233. }
  234. /* 插入数据 */
  235. if(vecDevInsert.size() > 0)
  236. {
  237. if(m_fromWebAPIUseSB.insertDeviceInfo(vecDevInsert))
  238. {
  239. SPDLOG_LOGGER_DEBUG(m_logger, "插入设备信息到 tCamerInfo, 数量:{}", vecDevInsert.size());
  240. isUpdate = true;
  241. }
  242. }
  243. // for(auto& it : vecNewDevInfo)
  244. // {
  245. // for(auto& it0 : it.vecAlgorithmInfo)
  246. // {
  247. // SPDLOG_LOGGER_DEBUG(m_logger, "设备ID: {}, 算法ID: {}", it.DeviceID, it0.ActionID);
  248. // }
  249. // }
  250. /*-------------------------------------------------------------------------
  251. ************* 处理设备和算子关联的表格,单独对比设备的算法信息 *************
  252. *------------------------------------------------------------------------*/
  253. /* 插入新的设备信息 */
  254. // if(vecDevInsert.size() > 0)
  255. // {
  256. // if(m_fromWebAPIUseSB.insertDeviceAlgorithmInfo(vecDevInsert))
  257. // {
  258. // SPDLOG_LOGGER_DEBUG(m_logger, "插入设备和算法关联表(tActionCamer), 数量: {}", vecDevInsert.size());
  259. // isUpdate = true;
  260. // }
  261. // }
  262. vecDevUpdate.clear();
  263. /* 对比现有的设备是否需要更新算法 */
  264. compareDeviceAlgorithmInfo(vecNewDevInfo, vecDevUpdate);
  265. if(vecDevUpdate.size() > 0)
  266. {
  267. if(m_fromWebAPIUseSB.updateDeviceAlgorithmInfo(vecDevUpdate))
  268. {
  269. SPDLOG_LOGGER_DEBUG(m_logger, "更新设备和算法关联表(tActionCamer), 更新设备数目:{}", vecDevUpdate.size());
  270. isUpdate = true;
  271. }
  272. }
  273. /* 删除tActionCamer表中消失的设备信息 */
  274. if(m_listDevIDDelete.size() > 0)
  275. {
  276. if(m_fromWebAPIUseSB.deleteDeviceAlgorithmInfo(m_listDevIDDelete))
  277. {
  278. SPDLOG_LOGGER_DEBUG(m_logger, "删除消失的设备关联的算法(tActionCamer), 数目: {}", m_listDevIDDelete.size());
  279. isUpdate = true;
  280. }
  281. }
  282. return isUpdate;
  283. }
  284. /* 对比现有的数据和新获取到的数据,取出要删除和添加的数据 */
  285. void SPAServer::compareAlgorithmInfo(const std::vector<AlgorithmInfo>& vecNewInfo, std::vector<AlgorithmInfo>& vecAlgUpdate, std::vector<AlgorithmInfo>& vecAlgDelete)
  286. {
  287. /* 取出要添加的,如果本地缓存是0,那么全部都要添加 */
  288. if(m_vecEqmAlgInfo.size() > 0)
  289. {
  290. for(const auto& it : vecNewInfo)
  291. {
  292. bool isExist = false;
  293. for(const auto& it0 : m_vecEqmAlgInfo)
  294. {
  295. /* 如果存在就退出循环 */
  296. if(it.ActionID == it0.ActionID)
  297. {
  298. isExist = true;
  299. break;
  300. }
  301. }
  302. if(!isExist)
  303. {
  304. vecAlgUpdate.push_back(it);
  305. }
  306. }
  307. }else {
  308. vecAlgUpdate = vecNewInfo;
  309. }
  310. /* 取出要删除的,如果新的数据是0,那么全部都要删除 */
  311. if(vecNewInfo.size() > 0)
  312. {
  313. bool isExist = false;
  314. for(const auto& it : m_vecEqmAlgInfo)
  315. {
  316. isExist = false;
  317. for(const auto& it0 : vecNewInfo)
  318. {
  319. if(it.ActionID == it0.ActionID)
  320. {
  321. isExist = true;
  322. break;
  323. }
  324. }
  325. if(!isExist)
  326. {
  327. vecAlgDelete.push_back(it);
  328. }
  329. }
  330. }else {
  331. vecAlgDelete = m_vecEqmAlgInfo;
  332. }
  333. }
  334. /**
  335. * @brief 对比设备和算法关联表是否需要更新
  336. * 对比规则:
  337. * 1、这里只对比已有的设备ID,需要删除的ID在获取到tActionCamer表是就已经取出来了
  338. * 2、如果设备ID相等,那么进一步对比算法信息是否相等
  339. * 3、如果设备ID相等,但是算法信息数目不相等,那么直接加入更新列表
  340. * 4、如果设备ID相等,算法信息数目相等,进一步对比算法信息
  341. *
  342. * @param vecNewInfo
  343. * @param vecDevUpdate
  344. */
  345. void SPAServer::compareDeviceAlgorithmInfo(const std::vector<DeviceInfo>& vecNewInfo, std::vector<DeviceInfo>& vecDevUpdate)
  346. {
  347. vecDevUpdate.clear();
  348. for(const auto& it0 : vecNewInfo)
  349. {
  350. for(const auto& it1 : m_vecEqmDevInfo)
  351. {
  352. if(it0.DeviceID == it1.DeviceID)
  353. {
  354. /* 设备的算法信息数目不相等,直接加入更新列表 */
  355. if(it0.vecAlgorithmInfo.size() != it1.vecAlgorithmInfo.size())
  356. {
  357. vecDevUpdate.push_back(it0);
  358. break;
  359. }
  360. /* 设备的算法信息数目相等,进一步对比算法信息 */
  361. bool isEquality = true;
  362. for(const auto& it2 : it0.vecAlgorithmInfo)
  363. {
  364. bool isEq2 = false;
  365. for(const auto& it3 : it1.vecAlgorithmInfo)
  366. {
  367. /* 这里只对比算法ID */
  368. if(it2.ActionID != it3.ActionID)
  369. {
  370. continue;
  371. }else {
  372. isEq2 = true;
  373. break;
  374. }
  375. }
  376. if(!isEq2)
  377. {
  378. isEquality = false;
  379. break;
  380. }
  381. }
  382. if(!isEquality)
  383. {
  384. vecDevUpdate.push_back(it0);
  385. break;
  386. }
  387. }
  388. }
  389. }
  390. }
  391. /**
  392. * @brief 分派任务的线程
  393. 1、 线程定时刷新房间和摄像机的关联关系,以及和算法Action的关联关系
  394. 2、 将算法信息加入到不同的列表中
  395. 需要多个摄像机配合的加入到 m_runListRoomActionInfo 列表
  396. 不需要多个摄像机配合的加入到 m_runListActionInfo 列表
  397. 3、 每次刷新都会清空ActionInfo或者RoomActionInfo的摄像机列表,但是不会动其他基本信息,如果是列表中没有对应的信息,
  398. 就会创建新的ActionInfo,那么RunState的状态是INIT,需要开启新的线程
  399. 如果刷新完成后,算法对应的摄像机列表为空,那么对应的线程就会停止运行,将RunState设置为STOP,本线程的下一轮
  400. 循环就会删除这个ActionInfo
  401. */
  402. void SPAServer::threadDistribution()
  403. {
  404. SPDLOG_LOGGER_INFO(m_logger, "**************** 开启分派任务线程 ****************");
  405. /* 房间相机关联信息 */
  406. std::list<RoomCameraInfo> listRC;
  407. /* 存储获取到的应用和启用时间的信息 */
  408. std::list<ChannelAppInfo> listAppAndTime;
  409. /* 初始化WebAPI */
  410. std::shared_ptr<FromWebAPI> pFromWebAPI = std::make_shared<FromWebAPI>();
  411. pFromWebAPI->initWebApi(GConfig.webapiUrl(), GConfig.webapiKey(), GConfig.webapiAppType());
  412. while (m_threadRunning)
  413. {
  414. /* ======================================================= */
  415. /* 更新通道名称和摄像机名称信息 */
  416. std::map<int, std::string> mapChannelName;
  417. pFromWebAPI->getChannelInfo(mapChannelName);
  418. GConfig.setChannelInfo(mapChannelName);
  419. std::map<int, std::string> mapCameraName;
  420. pFromWebAPI->getCameraInfo(mapCameraName);
  421. GConfig.setCameraInfo(mapCameraName);
  422. /* ======================================================= */
  423. GThreadInfo.lockRunFAI();
  424. /* 先清理已经退出的线程所用到的Action或者RoomAction */
  425. GThreadInfo.clearNoneFuncThreadInfo();
  426. /* 清空已经停止运行的功能类实例 */
  427. clearNoneFuncThreadInfo();
  428. /* ======================================================= */
  429. /* 创建应用信息,根据从EQM数据库读取到的配置的应用信息创建 */
  430. pFromWebAPI->getAlarmAppInfo(listAppAndTime);
  431. for(const auto& it : listAppAndTime)
  432. {
  433. /* 创建应用信息,如果已有该应用,就更新时间
  434. * 这里只创建应用信息块,没有对应的房间、算法信息 */
  435. GThreadInfo.addFuncThreadInfo(it);
  436. }
  437. /* 设置应用对应的频率信息 */
  438. // for(auto& func : GThreadInfo.getList())
  439. // {
  440. // /* 设置频率名称 */
  441. // func->strChannelName = GConfig.getChannelName(func->ChannelID);
  442. // }
  443. /* 设置对应的摄像机名称列表 */
  444. GThreadInfo.setCameraInfo(GConfig.getCameraInfoMap());
  445. /* 先获取EQM数据库信息,取出房间和摄像机关联信息,包括所在的频率 */
  446. m_mutexActionInfo.lock();
  447. pFromWebAPI->getActionInfo(m_listActionInfo);
  448. /* 将算法信息加入到不同的功能列表中,先清空功能对应的算法设备列表
  449. * 算法信息带有摄像机和房间信息,在从数据库读取的时候就读取出来了
  450. * 如果是新创建的应用,有房间信息就将状态由NONE转换成INIT */
  451. GThreadInfo.clearActionList();
  452. for(const auto& it : m_listActionInfo.getData())
  453. {
  454. GThreadInfo.addActionInfo(*it);
  455. }
  456. /* 检查算法信息的状态,频率里的应用没有配置摄像机就设置为线程运行状态为停止,退出该线程 */
  457. GThreadInfo.setNoneCameraFuncStop();
  458. m_mutexActionInfo.unlock();
  459. /* 开启线程 */
  460. for(const auto& func : GThreadInfo.getList())
  461. {
  462. /* 只有状态是 RUN_STATE_INIT 的才创建线程实例 */
  463. if(func->RunState == RunTimeState::RUN_STATE_INIT)
  464. {
  465. /* 创建实例 */
  466. FuncBase* pFunc = createFuncInstance(*func);
  467. if(pFunc == nullptr)
  468. {
  469. SPDLOG_LOGGER_ERROR(m_logger, "创建功能实例失败:{}", func->strFunctionName);
  470. continue;
  471. }
  472. CPPTP.add_task(&FuncBase::thread_task, pFunc);
  473. m_listFuncBase.push_back(pFunc);
  474. }
  475. }
  476. GThreadInfo.unlockRunFAI();
  477. /* 休眠n秒,默认应该是300秒 */
  478. std::this_thread::sleep_for(std::chrono::seconds(GVariable.CheckSet));
  479. // std::this_thread::sleep_for(std::chrono::seconds(3));
  480. }
  481. SPDLOG_LOGGER_INFO(m_logger, "分派任务线程退出");
  482. }
  483. /**
  484. * @brief 创建任务实例的函数,根据不同的功能创建出不同的实例
  485. *
  486. * @param info
  487. * @return FuncBase*
  488. */
  489. FuncBase* SPAServer::createFuncInstance(FuncThreadInfo& info)
  490. {
  491. if(info.appFunction == AppFunction::APP_NONE)
  492. {
  493. return nullptr;
  494. }
  495. FuncBase* pFunc = nullptr;
  496. /* 普通的功能,只用一个摄像机一个算法的功能 */
  497. if( info.appFunction == AppFunction::APP_AllDown || info.appFunction == AppFunction::APP_NoMask ||
  498. info.appFunction == AppFunction::APP_PlayPhone || info.appFunction == AppFunction::APP_Mouse ||
  499. info.appFunction == AppFunction::APP_Fatigue || info.appFunction == AppFunction::APP_Contraband )
  500. {
  501. /* 普通检测功能 */
  502. auto tmpFunc = new FuncOrdinary();
  503. tmpFunc->setFuncThreadInfo(info);
  504. pFunc = tmpFunc;
  505. }
  506. else if(info.appFunction == AppFunction::APP_OnWork)
  507. {
  508. /* 人员在岗检测 */
  509. // auto tmpFunc = new FuncOnAndOffWork();
  510. // tmpFunc->setFuncThreadInfo(info);
  511. // pFunc = tmpFunc;
  512. }
  513. else if(info.appFunction == AppFunction::APP_Illegal)
  514. {
  515. /* 非法入侵 */
  516. // auto tmpFunc = new FuncIllegalInvasion();
  517. // tmpFunc->setFuncThreadInfo(info);
  518. // pFunc = tmpFunc;
  519. }
  520. else if(info.appFunction == AppFunction::APP_Regional)
  521. {
  522. /* 区域人员检测 */
  523. auto tmpFunc = new FuncRegionalPersonCount();
  524. tmpFunc->setFuncThreadInfo(info);
  525. pFunc = tmpFunc;
  526. }
  527. return pFunc;
  528. }
  529. /* 清理没有在运行的线程实例 */
  530. void SPAServer::clearNoneFuncThreadInfo()
  531. {
  532. for(auto it = m_listFuncBase.begin(); it != m_listFuncBase.end(); )
  533. {
  534. if(!(*it)->getThreadRunning())
  535. {
  536. /* 需要转换成相应的子类实例才能删除 */
  537. if( (*it)->getApp() == AppFunction::APP_AllDown || (*it)->getApp() == AppFunction::APP_NoMask ||
  538. (*it)->getApp() == AppFunction::APP_PlayPhone || (*it)->getApp() == AppFunction::APP_Mouse ||
  539. (*it)->getApp() == AppFunction::APP_Fatigue || (*it)->getApp() == AppFunction::APP_Contraband )
  540. {
  541. FuncOrdinary* p = dynamic_cast<FuncOrdinary*>(*it);
  542. delete p;
  543. }
  544. else if((*it)->getApp() == AppFunction::APP_OnWork)
  545. {
  546. /* 人员在岗检测 */
  547. FuncOnAndOffWork* p = dynamic_cast<FuncOnAndOffWork*>(*it);
  548. delete p;
  549. }
  550. else if((*it)->getApp() == AppFunction::APP_Illegal)
  551. {
  552. /* 非法入侵 */
  553. FuncIllegalInvasion* p = dynamic_cast<FuncIllegalInvasion*>(*it);
  554. delete p;
  555. }
  556. else if((*it)->getApp() == AppFunction::APP_Regional)
  557. {
  558. /* 区域人员检测 */
  559. FuncRegionalPersonCount* p = dynamic_cast<FuncRegionalPersonCount*>(*it);
  560. delete p;
  561. }
  562. it = m_listFuncBase.erase(it);
  563. }else {
  564. ++it;
  565. }
  566. }
  567. }