SPAServer.cpp 22 KB

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