SPAServer.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  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. for(auto it = m_vecEqmDevInfo.begin(); it != m_vecEqmDevInfo.end(); it++)
  165. {
  166. for(auto it0 = it + 1; it0 != m_vecEqmDevInfo.end();)
  167. {
  168. if(it->DeviceID == it0->DeviceID)
  169. {
  170. SPDLOG_LOGGER_DEBUG(m_logger, "设备ID: {} 重复", it->DeviceID);
  171. it0 = m_vecEqmDevInfo.erase(it0);
  172. }else {
  173. ++it0;
  174. }
  175. }
  176. }
  177. /* 如果本地缓存没有数据,那么就全部插入 */
  178. if(m_vecEqmDevInfo.size() > 0)
  179. {
  180. for(auto& DevInfo : vecNewDevInfo)
  181. {
  182. bool isExist = false;
  183. for(auto& it0 : m_vecEqmDevInfo)
  184. {
  185. if(DevInfo.DeviceID == it0.DeviceID)
  186. {
  187. isExist = true;
  188. /* 对比其他项是否相等,不相等就更新 */
  189. if(DevInfo == it0)
  190. {
  191. continue;
  192. }else {
  193. vecDevUpdate.push_back(DevInfo);
  194. }
  195. break;
  196. }
  197. }
  198. if(!isExist)
  199. {
  200. vecDevInsert.push_back(DevInfo);
  201. }
  202. }
  203. }else {
  204. vecDevInsert = vecNewDevInfo;
  205. }
  206. /* 获取删除列表 */
  207. if(vecNewDevInfo.size() > 0)
  208. {
  209. bool isExist = false;
  210. for(const auto& it : m_vecEqmDevInfo)
  211. {
  212. isExist = false;
  213. for(const auto& it0 : vecNewDevInfo)
  214. {
  215. if(it.DeviceID == it0.DeviceID)
  216. {
  217. isExist = true;
  218. break;
  219. }
  220. }
  221. if(!isExist)
  222. {
  223. vecDevDelete.push_back(it);
  224. }
  225. }
  226. }else {
  227. vecDevDelete = m_vecEqmDevInfo;
  228. }
  229. bool isUpdate = false;
  230. /* 先删除多余的数据 */
  231. if(vecDevDelete.size() > 0)
  232. {
  233. if(m_fromWebAPIUseSB.deleteDeviceInfo(vecDevDelete))
  234. {
  235. SPDLOG_LOGGER_DEBUG(m_logger,"删除设备信息到 tCamerInfo, 数量:{}",vecDevDelete.size());
  236. isUpdate = true;
  237. }
  238. }
  239. /* 更新数据 */
  240. if(vecDevUpdate.size() > 0)
  241. {
  242. if(m_fromWebAPIUseSB.updateDeviceInfo(vecDevUpdate))
  243. {
  244. SPDLOG_LOGGER_DEBUG(m_logger, "更新设备信息到 tCamerInfo, 数量:{}", vecDevUpdate.size());
  245. isUpdate = true;
  246. }
  247. }
  248. /* 插入数据 */
  249. if(vecDevInsert.size() > 0)
  250. {
  251. if(m_fromWebAPIUseSB.insertDeviceInfo(vecDevInsert))
  252. {
  253. SPDLOG_LOGGER_DEBUG(m_logger, "插入设备信息到 tCamerInfo, 数量:{}", vecDevInsert.size());
  254. isUpdate = true;
  255. }
  256. }
  257. // for(auto& it : vecNewDevInfo)
  258. // {
  259. // for(auto& it0 : it.vecAlgorithmInfo)
  260. // {
  261. // SPDLOG_LOGGER_DEBUG(m_logger, "设备ID: {}, 算法ID: {}", it.DeviceID, it0.ActionID);
  262. // }
  263. // }
  264. /*-------------------------------------------------------------------------
  265. ************* 处理设备和算子关联的表格,单独对比设备的算法信息 *************
  266. *------------------------------------------------------------------------*/
  267. /* 插入新的设备信息 */
  268. // if(vecDevInsert.size() > 0)
  269. // {
  270. // if(m_fromWebAPIUseSB.insertDeviceAlgorithmInfo(vecDevInsert))
  271. // {
  272. // SPDLOG_LOGGER_DEBUG(m_logger, "插入设备和算法关联表(tActionCamer), 数量: {}", vecDevInsert.size());
  273. // isUpdate = true;
  274. // }
  275. // }
  276. vecDevUpdate.clear();
  277. /* 对比现有的设备是否需要更新算法 */
  278. compareDeviceAlgorithmInfo(vecNewDevInfo, vecDevUpdate);
  279. if(vecDevUpdate.size() > 0)
  280. {
  281. if(m_fromWebAPIUseSB.updateDeviceAlgorithmInfo(vecDevUpdate))
  282. {
  283. SPDLOG_LOGGER_DEBUG(m_logger, "更新设备和算法关联表(tActionCamer), 更新设备数目:{}", vecDevUpdate.size());
  284. isUpdate = true;
  285. }
  286. }
  287. /* 删除tActionCamer表中消失的设备信息 */
  288. if(m_listDevIDDelete.size() > 0)
  289. {
  290. if(m_fromWebAPIUseSB.deleteDeviceAlgorithmInfo(m_listDevIDDelete))
  291. {
  292. SPDLOG_LOGGER_DEBUG(m_logger, "删除消失的设备关联的算法(tActionCamer), 数目: {}", m_listDevIDDelete.size());
  293. isUpdate = true;
  294. }
  295. }
  296. return isUpdate;
  297. }
  298. /* 对比现有的数据和新获取到的数据,取出要删除和添加的数据 */
  299. void SPAServer::compareAlgorithmInfo(const std::vector<AlgorithmInfo>& vecNewInfo, std::vector<AlgorithmInfo>& vecAlgUpdate, std::vector<AlgorithmInfo>& vecAlgDelete)
  300. {
  301. /* 取出要添加的,如果本地缓存是0,那么全部都要添加 */
  302. if(m_vecEqmAlgInfo.size() > 0)
  303. {
  304. for(const auto& it : vecNewInfo)
  305. {
  306. bool isExist = false;
  307. for(const auto& it0 : m_vecEqmAlgInfo)
  308. {
  309. /* 如果存在就退出循环 */
  310. if(it.ActionID == it0.ActionID)
  311. {
  312. isExist = true;
  313. break;
  314. }
  315. }
  316. if(!isExist)
  317. {
  318. vecAlgUpdate.push_back(it);
  319. }
  320. }
  321. }else {
  322. vecAlgUpdate = vecNewInfo;
  323. }
  324. /* 取出要删除的,如果新的数据是0,那么全部都要删除 */
  325. if(vecNewInfo.size() > 0)
  326. {
  327. bool isExist = false;
  328. for(const auto& it : m_vecEqmAlgInfo)
  329. {
  330. isExist = false;
  331. for(const auto& it0 : vecNewInfo)
  332. {
  333. if(it.ActionID == it0.ActionID)
  334. {
  335. isExist = true;
  336. break;
  337. }
  338. }
  339. if(!isExist)
  340. {
  341. vecAlgDelete.push_back(it);
  342. }
  343. }
  344. }else {
  345. vecAlgDelete = m_vecEqmAlgInfo;
  346. }
  347. }
  348. /**
  349. * @brief 对比设备和算法关联表是否需要更新
  350. * 对比规则:
  351. * 1、这里只对比已有的设备ID,需要删除的ID在获取到tActionCamer表是就已经取出来了
  352. * 2、如果设备ID相等,那么进一步对比算法信息是否相等
  353. * 3、如果设备ID相等,但是算法信息数目不相等,那么直接加入更新列表
  354. * 4、如果设备ID相等,算法信息数目相等,进一步对比算法信息
  355. *
  356. * @param vecNewInfo
  357. * @param vecDevUpdate
  358. */
  359. void SPAServer::compareDeviceAlgorithmInfo(const std::vector<DeviceInfo>& vecNewInfo, std::vector<DeviceInfo>& vecDevUpdate)
  360. {
  361. vecDevUpdate.clear();
  362. for(const auto& it0 : vecNewInfo)
  363. {
  364. for(const auto& it1 : m_vecEqmDevInfo)
  365. {
  366. if(it0.DeviceID == it1.DeviceID)
  367. {
  368. /* 设备的算法信息数目不相等,直接加入更新列表 */
  369. if(it0.vecAlgorithmInfo.size() != it1.vecAlgorithmInfo.size())
  370. {
  371. vecDevUpdate.push_back(it0);
  372. break;
  373. }
  374. /* 设备的算法信息数目相等,进一步对比算法信息 */
  375. bool isEquality = true;
  376. for(const auto& it2 : it0.vecAlgorithmInfo)
  377. {
  378. bool isEq2 = false;
  379. for(const auto& it3 : it1.vecAlgorithmInfo)
  380. {
  381. /* 这里只对比算法ID */
  382. if(it2.ActionID != it3.ActionID)
  383. {
  384. continue;
  385. }else {
  386. isEq2 = true;
  387. break;
  388. }
  389. }
  390. if(!isEq2)
  391. {
  392. isEquality = false;
  393. break;
  394. }
  395. }
  396. if(!isEquality)
  397. {
  398. vecDevUpdate.push_back(it0);
  399. break;
  400. }
  401. }
  402. }
  403. }
  404. }
  405. /**
  406. * @brief 分派任务的线程
  407. 1、 线程定时刷新房间和摄像机的关联关系,以及和算法Action的关联关系
  408. 2、 将算法信息加入到不同的列表中
  409. 需要多个摄像机配合的加入到 m_runListRoomActionInfo 列表
  410. 不需要多个摄像机配合的加入到 m_runListActionInfo 列表
  411. 3、 每次刷新都会清空ActionInfo或者RoomActionInfo的摄像机列表,但是不会动其他基本信息,如果是列表中没有对应的信息,
  412. 就会创建新的ActionInfo,那么RunState的状态是INIT,需要开启新的线程
  413. 如果刷新完成后,算法对应的摄像机列表为空,那么对应的线程就会停止运行,将RunState设置为STOP,本线程的下一轮
  414. 循环就会删除这个ActionInfo
  415. */
  416. void SPAServer::threadDistribution()
  417. {
  418. SPDLOG_LOGGER_INFO(m_logger, "**************** 开启分派任务线程 ****************");
  419. /* 房间相机关联信息 */
  420. std::list<RoomCameraInfo> listRC;
  421. /* 存储获取到的应用和启用时间的信息 */
  422. std::list<ChannelAppInfo> listAppAndTime;
  423. /* 初始化WebAPI */
  424. std::shared_ptr<FromWebAPI> pFromWebAPI = std::make_shared<FromWebAPI>();
  425. pFromWebAPI->initWebApi(GConfig.webapiUrl(), GConfig.webapiKey(), GConfig.webapiAppType());
  426. while (m_threadRunning)
  427. {
  428. /* ======================================================= */
  429. /* 更新通道名称和摄像机名称信息 */
  430. std::map<int, std::string> mapChannelName;
  431. pFromWebAPI->getChannelInfo(mapChannelName);
  432. GConfig.setChannelInfo(mapChannelName);
  433. std::map<int, std::string> mapCameraName;
  434. pFromWebAPI->getCameraInfo(mapCameraName);
  435. GConfig.setCameraInfo(mapCameraName);
  436. /* ======================================================= */
  437. GThreadInfo.lockRunFAI();
  438. /* 先清理已经退出的线程所用到的Action或者RoomAction */
  439. GThreadInfo.clearNoneFuncThreadInfo();
  440. /* 清空已经停止运行的功能类实例 */
  441. clearNoneFuncThreadInfo();
  442. /* ======================================================= */
  443. /* 创建应用信息,根据从EQM数据库读取到的配置的应用信息创建 */
  444. pFromWebAPI->getAlarmAppInfo(listAppAndTime);
  445. for(const auto& it : listAppAndTime)
  446. {
  447. /* 创建应用信息,如果已有该应用,就更新时间
  448. * 这里只创建应用信息块,没有对应的房间、算法信息 */
  449. GThreadInfo.addFuncThreadInfo(it);
  450. }
  451. /* 设置应用对应的频率信息 */
  452. // for(auto& func : GThreadInfo.getList())
  453. // {
  454. // /* 设置频率名称 */
  455. // func->strChannelName = GConfig.getChannelName(func->ChannelID);
  456. // }
  457. /* 设置对应的摄像机名称列表 */
  458. GThreadInfo.setCameraInfo(GConfig.getCameraInfoMap());
  459. /* 先获取EQM数据库信息,取出房间和摄像机关联信息,包括所在的频率 */
  460. m_mutexActionInfo.lock();
  461. pFromWebAPI->getActionInfo(m_listActionInfo);
  462. /* 将算法信息加入到不同的功能列表中,先清空功能对应的算法设备列表
  463. * 算法信息带有摄像机和房间信息,在从数据库读取的时候就读取出来了
  464. * 如果是新创建的应用,有房间信息就将状态由NONE转换成INIT */
  465. GThreadInfo.clearActionList();
  466. for(const auto& it : m_listActionInfo.getData())
  467. {
  468. GThreadInfo.addActionInfo(*it);
  469. }
  470. /* 检查算法信息的状态,频率里的应用没有配置摄像机就设置为线程运行状态为停止,退出该线程 */
  471. GThreadInfo.setNoneCameraFuncStop();
  472. m_mutexActionInfo.unlock();
  473. /* 开启线程 */
  474. for(const auto& func : GThreadInfo.getList())
  475. {
  476. /* 只有状态是 RUN_STATE_INIT 的才创建线程实例 */
  477. if(func->RunState == RunTimeState::RUN_STATE_INIT)
  478. {
  479. /* 创建实例 */
  480. FuncBase* pFunc = createFuncInstance(*func);
  481. if(pFunc == nullptr)
  482. {
  483. SPDLOG_LOGGER_ERROR(m_logger, "创建功能实例失败:{}", func->strFunctionName);
  484. continue;
  485. }
  486. CPPTP.add_task(&FuncBase::thread_task, pFunc);
  487. m_listFuncBase.push_back(pFunc);
  488. }
  489. }
  490. GThreadInfo.unlockRunFAI();
  491. /* 休眠n秒,默认应该是300秒 */
  492. std::this_thread::sleep_for(std::chrono::seconds(GVariable.CheckSet));
  493. // std::this_thread::sleep_for(std::chrono::seconds(3));
  494. }
  495. SPDLOG_LOGGER_INFO(m_logger, "分派任务线程退出");
  496. }
  497. /**
  498. * @brief 创建任务实例的函数,根据不同的功能创建出不同的实例
  499. *
  500. * @param info
  501. * @return FuncBase*
  502. */
  503. FuncBase* SPAServer::createFuncInstance(FuncThreadInfo& info)
  504. {
  505. if(info.appFunction == AppFunction::APP_NONE)
  506. {
  507. return nullptr;
  508. }
  509. FuncBase* pFunc = nullptr;
  510. /* 普通的功能,只用一个摄像机一个算法的功能 */
  511. if( info.appFunction == AppFunction::APP_AllDown || info.appFunction == AppFunction::APP_NoMask ||
  512. info.appFunction == AppFunction::APP_PlayPhone || info.appFunction == AppFunction::APP_Mouse ||
  513. info.appFunction == AppFunction::APP_Fatigue || info.appFunction == AppFunction::APP_Contraband )
  514. {
  515. /* 普通检测功能 */
  516. auto tmpFunc = new FuncOrdinary();
  517. tmpFunc->setFuncThreadInfo(info);
  518. pFunc = tmpFunc;
  519. }
  520. else if(info.appFunction == AppFunction::APP_OnWork)
  521. {
  522. /* 人员在岗检测 */
  523. // auto tmpFunc = new FuncOnAndOffWork();
  524. // tmpFunc->setFuncThreadInfo(info);
  525. // pFunc = tmpFunc;
  526. }
  527. else if(info.appFunction == AppFunction::APP_Illegal)
  528. {
  529. /* 非法入侵 */
  530. // auto tmpFunc = new FuncIllegalInvasion();
  531. // tmpFunc->setFuncThreadInfo(info);
  532. // pFunc = tmpFunc;
  533. }
  534. else if(info.appFunction == AppFunction::APP_Regional)
  535. {
  536. /* 区域人员检测 */
  537. auto tmpFunc = new FuncRegionalPersonCount();
  538. tmpFunc->setFuncThreadInfo(info);
  539. pFunc = tmpFunc;
  540. }
  541. return pFunc;
  542. }
  543. /* 清理没有在运行的线程实例 */
  544. void SPAServer::clearNoneFuncThreadInfo()
  545. {
  546. for(auto it = m_listFuncBase.begin(); it != m_listFuncBase.end(); )
  547. {
  548. if(!(*it)->getThreadRunning())
  549. {
  550. /* 需要转换成相应的子类实例才能删除 */
  551. if( (*it)->getApp() == AppFunction::APP_AllDown || (*it)->getApp() == AppFunction::APP_NoMask ||
  552. (*it)->getApp() == AppFunction::APP_PlayPhone || (*it)->getApp() == AppFunction::APP_Mouse ||
  553. (*it)->getApp() == AppFunction::APP_Fatigue || (*it)->getApp() == AppFunction::APP_Contraband )
  554. {
  555. FuncOrdinary* p = dynamic_cast<FuncOrdinary*>(*it);
  556. delete p;
  557. }
  558. else if((*it)->getApp() == AppFunction::APP_OnWork)
  559. {
  560. /* 人员在岗检测 */
  561. FuncOnAndOffWork* p = dynamic_cast<FuncOnAndOffWork*>(*it);
  562. delete p;
  563. }
  564. else if((*it)->getApp() == AppFunction::APP_Illegal)
  565. {
  566. /* 非法入侵 */
  567. FuncIllegalInvasion* p = dynamic_cast<FuncIllegalInvasion*>(*it);
  568. delete p;
  569. }
  570. else if((*it)->getApp() == AppFunction::APP_Regional)
  571. {
  572. /* 区域人员检测 */
  573. FuncRegionalPersonCount* p = dynamic_cast<FuncRegionalPersonCount*>(*it);
  574. delete p;
  575. }
  576. it = m_listFuncBase.erase(it);
  577. }else {
  578. ++it;
  579. }
  580. }
  581. }