device.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. #include <cstring>
  2. #include <unistd.h>
  3. #include "utils.h"
  4. #include "device.h"
  5. #include "json/parser.h"
  6. // declare of scoped vars and funcs
  7. namespace hm {
  8. const int gWaitTime = 3000;
  9. std::map<int, std::string> gOpenTypeMap = { // NOLINT
  10. {0, "未知方式"},
  11. {1, "密码开锁"},
  12. {2, "刷卡开锁"},
  13. {3, "先刷卡后密码开锁"},
  14. {4, "先密码后刷卡开锁"},
  15. {5, "远程开锁,如通过室内机或者平台对门口机开锁"},
  16. {6, "开锁按钮进行开锁"},
  17. {7, "开锁"},
  18. {8, "密码+刷卡+组合开锁"},
  19. {10, "密码+组合开锁"},
  20. {11, "刷卡+组合开锁"},
  21. {12, "多人开锁"},
  22. {13, "钥匙开门"},
  23. {14, "胁迫密码开门"},
  24. {15, "二维码开门"},
  25. {16, "目标识别开门"},
  26. {18, "人证对比"},
  27. {19, "证件+人证比对"},
  28. {20, "蓝牙开门"},
  29. {21, "个性化密码开门"},
  30. {22, "UserID+密码"},
  31. {23, "人脸+密码开锁"},
  32. {24, "+密码开锁"},
  33. {25, "+人脸开锁"},
  34. {26, "刷卡+人脸开锁"},
  35. {27, "人脸或密码开锁"},
  36. {28, "或密码开锁"},
  37. {29, "或人脸开锁"},
  38. {30, "刷卡或人脸开锁"},
  39. {31, "刷卡或开锁"},
  40. {32, "+人脸+密码开锁"},
  41. {33, "刷卡+人脸+密码开锁"},
  42. {34, "刷卡++密码开锁"},
  43. {35, "卡++人脸组合开锁"},
  44. {36, "或人脸或密码"},
  45. {37, "卡或人脸或密码开锁"},
  46. {38, "卡或人脸开锁"},
  47. {39, "卡++人脸+密码组合开锁"},
  48. {40, "卡或人脸或密码开锁"},
  49. {41, "(证件+人证比对)或刷卡或人脸"},
  50. {42, "人证比对或刷卡(二维码)或人脸"},
  51. {43, "DTMF开锁(包括SIPINFO,RFC2833,INBAND)"},
  52. {44, "远程二维码开门"},
  53. {45, "远程人脸开门"},
  54. {46, "人证比对开门()"},
  55. {47, "临时密码开门"},
  56. {48, "健康码开门"},
  57. {49, "目标识别开锁"},
  58. {50, "目标+密码组合开锁"},
  59. {51, "人脸+目标组合开锁"},
  60. {52, "卡+目标组合开锁"},
  61. {53, "目标或密码开锁"},
  62. {54, "人脸或目标开锁"},
  63. {55, "卡或目标开锁"},
  64. {56, "人脸+目标+密码组合开锁"},
  65. {57, "卡+人脸+目标组合开锁"},
  66. {58, "卡+目标+密码组合开锁"},
  67. {59, "人脸或目标或密码开锁"},
  68. {60, "卡或人脸或目标开锁"},
  69. {61, "卡或目标或密码开锁"},
  70. {62, "卡+人脸+目标+密码组合开锁"},
  71. {63, "卡或人脸或目标或密码开锁"}
  72. };
  73. int onSubscribeData(
  74. LLONG handler, DWORD type, void *info, BYTE *imgBuf, DWORD bufSize,
  75. LDWORD user, int seq, void *reserved
  76. );
  77. Device *getDeviceBySubId(const LLONG &subId);
  78. }
  79. // implement of scoped funcs
  80. namespace hm {
  81. int onSubscribeData(
  82. LLONG handler, DWORD type, void *info, BYTE *imgBuf, DWORD bufSize,
  83. LDWORD user, int seq, void *reserved
  84. ) {
  85. Device *device = getDeviceBySubId(handler);
  86. if (device == nullptr) {
  87. Log(Warn, "unrecognized subscribe uid: %ld", handler);
  88. return 0;
  89. }
  90. switch (type) {
  91. case EVENT_IVS_ACCESS_CTL: // 人脸
  92. if (device->isFaceDevice)
  93. device->onAccessCtlEvent((DEV_EVENT_ACCESS_CTL_INFO *) info, imgBuf, bufSize);
  94. else Log(Warn, "seq[%s] is car device, but got a face event", device->seq.c_str());
  95. break;
  96. case EVENT_IVS_TRAFFICJUNCTION: // 车辆闸机
  97. if (!device->isFaceDevice)
  98. device->onTrafficJunctionEvent((DEV_EVENT_TRAFFICJUNCTION_INFO *) info, imgBuf, bufSize);
  99. else Log(Warn, "seq[%s] is face device, but got a car event", device->seq.c_str());
  100. break;
  101. default:
  102. Log(Warn, "unrecognized event: %u", type);
  103. break;
  104. }
  105. return 1;
  106. }
  107. Device *getDeviceBySubId(const LLONG &subId) {
  108. for (auto &itr : gDevicesVec) if (itr->subId == subId) return itr.get();
  109. return nullptr;
  110. }
  111. void Device::init() {
  112. NET_IN_INIT_DEVICE_ACCOUNT in;
  113. in.dwSize = sizeof in;
  114. strcpy(in.szMac, this->mac.c_str());
  115. strcpy(in.szUserName, gConfLoginUser.c_str());
  116. strcpy(in.szPwd, gConfLoginPass.c_str());
  117. in.byPwdResetWay = this->reset;
  118. NET_OUT_INIT_DEVICE_ACCOUNT out;
  119. out.dwSize = sizeof out;
  120. if (CLIENT_InitDevAccount(&in, &out, gWaitTime, this->local.data())) {
  121. Log(Info, "device: seq[%s] init success", this->seq.c_str());
  122. this->inited = true;
  123. return;
  124. }
  125. Log(
  126. Error, "device(ip[%s], mac[%s], seq[%s]) init fail",
  127. this->ip.c_str(), this->mac.c_str(), this->seq.c_str()
  128. );
  129. this->running = false;
  130. }
  131. bool Device::login() {
  132. NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY in = {0};
  133. in.dwSize = sizeof in;
  134. strcpy(in.szIP, this->ip.c_str());
  135. in.nPort = this->port;
  136. strcpy(in.szUserName, gConfLoginUser.c_str());
  137. strcpy(in.szPassword, gConfLoginPass.c_str());
  138. in.emSpecCap = EM_LOGIN_SPEC_CAP_TCP;
  139. NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY out;
  140. out.dwSize = sizeof out;
  141. for (int i = 0; i < 3; ++i) {
  142. this->loginId = CLIENT_LoginWithHighLevelSecurity(&in, &out);
  143. if (this->loginId) {
  144. Log(Trace, "device seq[%s] login success", this->seq.c_str());
  145. usleep(1000000);
  146. return true;
  147. }
  148. sleep(1);
  149. }
  150. Log(
  151. Error, "device(ip[%s], mac[%s], seq[%s]) login fail",
  152. this->ip.c_str(), this->mac.c_str(), this->seq.c_str()
  153. );
  154. this->running = false;
  155. return false;
  156. }
  157. void Device::logout() {
  158. if (this->loginId) CLIENT_Logout(this->loginId);
  159. this->loginId = 0, this->running = false;
  160. }
  161. bool Device::subscribe() {
  162. if (isFaceDevice) {
  163. this->subId = CLIENT_RealLoadPictureEx(
  164. this->loginId, 0, EVENT_IVS_ACCESS_CTL, TRUE,
  165. onSubscribeData, 0, nullptr
  166. );
  167. } else {
  168. this->subId = CLIENT_RealLoadPictureEx(
  169. this->loginId, 0, EVENT_IVS_TRAFFICJUNCTION, TRUE,
  170. onSubscribeData, 0, nullptr
  171. );
  172. }
  173. if (this->subId) {
  174. Log(Trace, "device seq[%s] subscribe success", this->seq.c_str());
  175. return true;
  176. }
  177. Log(
  178. Error, "device(ip[%s], mac[%s], seq[%s]) face subscribe fail",
  179. this->ip.c_str(), this->mac.c_str(), this->seq.c_str()
  180. );
  181. this->running = false;
  182. return false;
  183. }
  184. void Device::unsubscribe() {
  185. if (this->subId) CLIENT_StopLoadPic(this->subId);
  186. this->subId = 0, this->running = false;
  187. }
  188. void Device::varUserInsert(const User &user) {
  189. bool have = false;
  190. std::lock_guard<std::mutex> lock(uMtx);
  191. for (const User &itr : faceUserList) {
  192. if (itr.uid == user.uid) {
  193. have = true;
  194. break;
  195. }
  196. }
  197. if (!have) faceUserList.push_back(user);
  198. }
  199. void Device::varUserDelete(const std::string &uid) {
  200. std::lock_guard<std::mutex> lock(uMtx);
  201. for (auto it = faceUserList.begin(); it != faceUserList.end(); ++it) {
  202. if (it->uid == uid) {
  203. faceUserList.erase(it);
  204. break;
  205. }
  206. }
  207. }
  208. bool Device::varUserExists(const std::string &uid) {
  209. std::lock_guard<std::mutex> lock(uMtx);
  210. for (User &user : faceUserList) if (user.uid == uid) return true;
  211. return false;
  212. }
  213. bool Device::addUserFace(const std::string &uid, const std::string &face, std::string &msg) {
  214. NET_IN_ADD_FACE_INFO in;
  215. in.dwSize = sizeof in;
  216. strcpy(in.szUserID, uid.c_str());
  217. in.stuFaceInfo.nFacePhoto = 1;
  218. in.stuFaceInfo.nFacePhotoLen[0] = imgcpy(in.stuFaceInfo.pszFacePhoto[0], face);
  219. // Log(Info, "face-size: %ld, pho-len:%d", face.size(), in.stuFaceInfo.nFacePhotoLen[0]);
  220. // imageSave("./java.jpg", in.stuFaceInfo.pszFacePhoto[0], in.stuFaceInfo.nFacePhotoLen[0]);
  221. NET_OUT_ADD_FACE_INFO out;
  222. out.dwSize = sizeof out;
  223. bool res = CLIENT_FaceInfoOpreate(loginId, EM_FACEINFO_OPREATE_ADD, &in, &out, gWaitTime);
  224. if (!res) msg = "user face add failed";
  225. delete[] in.stuFaceInfo.pszFacePhoto[0];
  226. return res;
  227. }
  228. bool Device::removeUserOnly(const std::string &uid, std::string &msg) {
  229. NET_IN_ACCESS_USER_SERVICE_REMOVE in;
  230. in.dwSize = sizeof in;
  231. in.nUserNum = 1;
  232. std::strcpy(in.szUserID[0], uid.c_str());
  233. in.bUserIDEx = 0;
  234. NET_OUT_ACCESS_USER_SERVICE_REMOVE out;
  235. out.dwSize = sizeof out;
  236. out.nMaxRetNum = 1;
  237. out.pFailCode = new NET_EM_FAILCODE;
  238. bool res = CLIENT_OperateAccessUserService(
  239. loginId, NET_EM_ACCESS_CTL_USER_SERVICE_REMOVE, &in, &out, gWaitTime
  240. );
  241. if (res) varUserDelete(uid);
  242. else msg = "user info delete failed";
  243. delete out.pFailCode;
  244. return res;
  245. }
  246. bool Device::removeUserFace(const std::string &uid, std::string &msg) {
  247. NET_IN_REMOVE_FACE_INFO in;
  248. in.dwSize = sizeof in;
  249. strcpy(in.szUserID, uid.c_str());
  250. NET_OUT_REMOVE_FACE_INFO out;
  251. out.dwSize = sizeof out;
  252. bool res = CLIENT_FaceInfoOpreate(loginId, EM_FACEINFO_OPREATE_REMOVE, &in, &out, gWaitTime);
  253. if (!res) msg = "user face remove failed";
  254. return res;
  255. }
  256. void Device::varCarWoBInsert(const bool &isBlack, const Plate &plate) {
  257. bool have = false;
  258. std::lock_guard<std::mutex> lock(isBlack ? cbMtx : cwMtx);
  259. for (const Plate &itr : isBlack ? carBlackList : carWhiteList) {
  260. if (itr.cid == plate.cid) {
  261. have = true;
  262. break;
  263. }
  264. }
  265. if (!have) isBlack ? carBlackList.push_back(plate) : carWhiteList.push_back(plate);
  266. }
  267. void Device::varCarWoBDelete(const bool &isBlack, const int &cid) {
  268. std::lock_guard<std::mutex> lock(isBlack ? cbMtx : cwMtx);
  269. for (auto it = (isBlack ? carBlackList : carWhiteList).begin();
  270. it != (isBlack ? carBlackList : carWhiteList).end(); ++it) {
  271. if (it->cid == cid) {
  272. (isBlack ? carBlackList : carWhiteList).erase(it);
  273. break;
  274. }
  275. }
  276. }
  277. bool Device::varCarWoBExists(const bool &isBlack, const int &cid) {
  278. std::lock_guard<std::mutex> lock(isBlack ? cbMtx : cwMtx);
  279. for (const Plate &plate : isBlack ? carBlackList : carWhiteList) if (plate.cid == cid) return true;
  280. return false;
  281. }
  282. bool Device::varCarWoBExists(const bool &isBlack, const std::string &plate) {
  283. std::lock_guard<std::mutex> lock(isBlack ? cbMtx : cwMtx);
  284. for (const Plate &itr : isBlack ? carBlackList : carWhiteList) if (itr.plate == plate) return true;
  285. return false;
  286. }
  287. bool Device::insertOneCarWoBList(const bool &isBlack, Plate &plateInfo, std::string &msg) {
  288. if (varCarWoBExists(isBlack, plateInfo.plate)) {
  289. msg = "exist already";
  290. return false;
  291. }
  292. NET_IN_OPERATE_TRAFFIC_LIST_RECORD in;
  293. in.dwSize = sizeof in;
  294. in.emOperateType = NET_TRAFFIC_LIST_INSERT;
  295. in.emRecordType = isBlack ? NET_RECORD_TRAFFICBLACKLIST : NET_RECORD_TRAFFICREDLIST;
  296. auto *info = new NET_INSERT_RECORD_INFO;
  297. info->dwSize = sizeof(NET_INSERT_RECORD_INFO);
  298. auto *record = new NET_TRAFFIC_LIST_RECORD;
  299. strcpy(record->szMasterOfCar, plateInfo.name.c_str());
  300. strcpy(record->szPlateNumber, plateInfo.plate.c_str());
  301. time_t tst = plateInfo.timestamp / 1000;
  302. struct tm *timeInfo = localtime(&tst);
  303. record->stCancelTime.dwYear = timeInfo->tm_year + 1900, record->stCancelTime.dwMonth = timeInfo->tm_mon + 1;
  304. record->stCancelTime.dwDay = timeInfo->tm_mday, record->stCancelTime.dwHour = timeInfo->tm_hour;
  305. record->stCancelTime.dwMinute = timeInfo->tm_min, record->stCancelTime.dwSecond = timeInfo->tm_sec;
  306. record->stBeginTime.dwYear = 2000, record->stBeginTime.dwMonth = 1, record->stBeginTime.dwDay = 1;
  307. record->stBeginTime.dwHour = 0, record->stBeginTime.dwMinute = 0, record->stBeginTime.dwSecond = 0;
  308. record->nAuthrityNum = 0;
  309. info->pRecordInfo = record;
  310. in.pstOpreateInfo = info;
  311. NET_OUT_OPERATE_TRAFFIC_LIST_RECORD out;
  312. out.dwSize = sizeof out;
  313. bool res = CLIENT_OperateTrafficList(loginId, &in, &out);
  314. if (res) {
  315. plateInfo.cid = out.nRecordNo;
  316. plateInfo.cid_s = std::to_string(out.nRecordNo);
  317. varCarWoBInsert(isBlack, plateInfo);
  318. } else {
  319. msg = "insert failed";
  320. plateInfo.cid = 0;
  321. }
  322. delete record;
  323. delete info;
  324. return res;
  325. }
  326. bool Device::removeOneCarWoBList(const bool &isBlack, const int &cid, std::string &msg) {
  327. if (!varCarWoBExists(isBlack, cid)) {
  328. msg = "no such plate";
  329. return false;
  330. }
  331. NET_IN_OPERATE_TRAFFIC_LIST_RECORD in;
  332. in.dwSize = sizeof in;
  333. in.emOperateType = NET_TRAFFIC_LIST_REMOVE;
  334. in.emRecordType = isBlack ? NET_RECORD_TRAFFICBLACKLIST : NET_RECORD_TRAFFICREDLIST;
  335. auto *info = new NET_REMOVE_RECORD_INFO;
  336. info->dwSize = sizeof(NET_REMOVE_RECORD_INFO);
  337. info->nRecordNo = cid;
  338. in.pstOpreateInfo = info;
  339. NET_OUT_OPERATE_TRAFFIC_LIST_RECORD out;
  340. out.dwSize = sizeof out;
  341. bool res = CLIENT_OperateTrafficList(loginId, &in, &out);
  342. if (res) varCarWoBDelete(isBlack, cid);
  343. else msg = "remove failed";
  344. delete info;
  345. return res;
  346. }
  347. Plate *Device::getPlateByCNo(const std::string &cno) {
  348. for (auto &itr : carWhiteList) if (itr.plate == cno) return &itr;
  349. for (auto &itr : carBlackList) if (itr.plate == cno) return &itr;
  350. return nullptr;
  351. }
  352. }
  353. namespace hm {
  354. Device::Device(DEVICE_NET_INFO_EX2 *info) {
  355. this->inited = (info->stuDevInfo.byInitStatus & 3) != 1;
  356. this->port = info->stuDevInfo.nPort;
  357. this->reset = info->stuDevInfo.byPwdResetWay;
  358. this->seq = info->stuDevInfo.szSerialNo;
  359. this->mac = info->stuDevInfo.szMac;
  360. this->ip = info->stuDevInfo.szIP;
  361. this->local = info->szLocalIP;
  362. // 108: {szDeviceType: BSC, szDetailType: DH-ASI31A-MW, szNewDetailType: DH-ASI31A-MW}
  363. // 109: {szDeviceType: ITC, szDetailType: ITC313-PW2A-LF, szNewDetailType: ITC313-PW2A-LF}
  364. this->isFaceDevice = strcmp("DH-ASI31A-MW", info->stuDevInfo.szDetailType) == 0;
  365. this->online = this->running = false;
  366. this->loginId = this->subId = 0;
  367. }
  368. Device::~Device() {
  369. this->unsubscribe();
  370. this->logout();
  371. }
  372. void Device::queryFaceUsers() {
  373. NET_IN_USERINFO_START_FIND start_in;
  374. start_in.dwSize = sizeof start_in;
  375. strcpy(start_in.szUserID, "");
  376. NET_OUT_USERINFO_START_FIND start_out;
  377. start_out.dwSize = sizeof start_out;
  378. LLONG handler = CLIENT_StartFindUserInfo(loginId, &start_in, &start_out, gWaitTime);
  379. if (handler) {
  380. int offset = 0, count = 10;
  381. faceUserList.clear();
  382. while (offset < start_out.nTotalCount) {
  383. NET_IN_USERINFO_DO_FIND find_in;
  384. find_in.dwSize = sizeof find_in;
  385. find_in.nStartNo = offset;
  386. find_in.nCount = count;
  387. NET_OUT_USERINFO_DO_FIND find_out;
  388. find_out.dwSize = sizeof find_out;
  389. find_out.nMaxNum = count;
  390. find_out.pstuInfo = new NET_ACCESS_USER_INFO[count];
  391. bool res = CLIENT_DoFindUserInfo(handler, &find_in, &find_out, gWaitTime);
  392. if (res) {
  393. for (int i = 0; i < find_out.nRetNum; ++i) {
  394. User one = {
  395. .uid=find_out.pstuInfo[i].szUserID, .name=find_out.pstuInfo[i].szName,
  396. .password = find_out.pstuInfo[i].szPsw,
  397. .timestamp=1000 * toTimestamp(
  398. find_out.pstuInfo[i].stuValidEndTime.dwYear,
  399. find_out.pstuInfo[i].stuValidEndTime.dwMonth,
  400. find_out.pstuInfo[i].stuValidEndTime.dwDay,
  401. find_out.pstuInfo[i].stuValidEndTime.dwHour,
  402. find_out.pstuInfo[i].stuValidEndTime.dwMinute,
  403. find_out.pstuInfo[i].stuValidEndTime.dwSecond
  404. )
  405. };
  406. varUserInsert(one);
  407. }
  408. offset += find_out.nRetNum;
  409. delete[] find_out.pstuInfo;
  410. } else break;
  411. }
  412. CLIENT_StopFindUserInfo(handler);
  413. }
  414. }
  415. void Device::queryCarWoBList(const bool &isBlack) {
  416. NET_IN_FIND_RECORD_PARAM find_in;
  417. find_in.dwSize = sizeof find_in;
  418. find_in.emType = isBlack ? NET_RECORD_TRAFFICBLACKLIST : NET_RECORD_TRAFFICREDLIST;
  419. auto *find_cond = new FIND_RECORD_TRAFFICREDLIST_CONDITION;
  420. find_cond->dwSize = sizeof(FIND_RECORD_TRAFFICREDLIST_CONDITION);
  421. strcpy(find_cond->szPlateNumber, "");
  422. strcpy(find_cond->szPlateNumberVague, "");
  423. find_cond->nQueryResultBegin = 0;
  424. find_cond->bRapidQuery = 0;
  425. find_in.pQueryCondition = find_cond;
  426. NET_OUT_FIND_RECORD_PARAM find_out;
  427. find_out.dwSize = sizeof find_out;
  428. bool res = CLIENT_FindRecord(loginId, &find_in, &find_out);
  429. if (res) {
  430. NET_IN_QUEYT_RECORD_COUNT_PARAM query_in;
  431. query_in.dwSize = sizeof query_in;
  432. query_in.lFindeHandle = find_out.lFindeHandle;
  433. NET_OUT_QUEYT_RECORD_COUNT_PARAM query_out;
  434. query_out.dwSize = sizeof query_out;
  435. res = CLIENT_QueryRecordCount(&query_in, &query_out);
  436. if (res) {
  437. int found = 0, batch = 5;
  438. while (found < query_out.nRecordCount) {
  439. NET_IN_FIND_NEXT_RECORD_PARAM do_in;
  440. do_in.dwSize = sizeof do_in;
  441. do_in.lFindeHandle = find_out.lFindeHandle;
  442. do_in.nFileCount = batch;
  443. NET_OUT_FIND_NEXT_RECORD_PARAM do_out;
  444. do_out.dwSize = sizeof do_out;
  445. do_out.nMaxRecordNum = batch;
  446. auto *records = new NET_TRAFFIC_LIST_RECORD[5];
  447. do_out.pRecordList = records;
  448. for (int i = 0; i < batch; ++i) records[i].dwSize = sizeof(NET_TRAFFIC_LIST_RECORD);
  449. res = CLIENT_FindNextRecord(&do_in, &do_out);
  450. if (res) {
  451. found += do_out.nRetRecordNum;
  452. for (int i = 0; i < do_out.nRetRecordNum; ++i) {
  453. Plate one = {
  454. .name = records[i].szMasterOfCar, .plate = records[i].szPlateNumber,
  455. .cid_s = std::to_string(records[i].nRecordNo), .cid = records[i].nRecordNo,
  456. .timestamp = 1000 * toTimestamp(
  457. records[i].stCancelTime.dwYear, records[i].stCancelTime.dwMonth,
  458. records[i].stCancelTime.dwDay, records[i].stCancelTime.dwHour,
  459. records[i].stCancelTime.dwMinute, records[i].stCancelTime.dwSecond
  460. )
  461. };
  462. varCarWoBInsert(isBlack, one);
  463. }
  464. } else break;
  465. delete[] records;
  466. }
  467. }
  468. CLIENT_FindRecordClose(find_out.lFindeHandle);
  469. }
  470. delete find_cond;
  471. }
  472. void Device::Start() {
  473. if (this->running) return;
  474. this->running = true;
  475. if (!this->inited) this->init();
  476. if (!this->login()) return;
  477. this->online = true;
  478. if (!this->subscribe()) return;
  479. }
  480. void Device::onAccessCtlEvent(DEV_EVENT_ACCESS_CTL_INFO *info, BYTE *imgBuf, DWORD bufSize) {
  481. char status[2] = {info->bStatus ? '1' : '0', 0}, method[64] = {0}, time[32] = {0};
  482. strcpy(method, gOpenTypeMap[0].c_str());
  483. if (gOpenTypeMap.find(info->emOpenMethod) != gOpenTypeMap.end())
  484. strcpy(method, gOpenTypeMap[info->emOpenMethod].c_str());
  485. sprintf(
  486. time, "%d-%02d-%02d %02d:%02d:%02d", info->UTC.dwYear, info->UTC.dwMonth,
  487. info->UTC.dwDay, info->UTC.dwHour + 8, info->UTC.dwMinute, info->UTC.dwSecond
  488. );
  489. Log(
  490. Info,
  491. R"({"mac":"%s","seq":"%s","time":"%s","result":%s,"userId":"%s","userName":"%s","method":"%s"})",
  492. this->mac.c_str(), this->seq.c_str(), time, status, info->szUserID, info->szCardName, method
  493. );
  494. // imageSave("./face.jpg", imgBuf, bufSize);
  495. std::map<std::string, std::string> data{
  496. {"mac", this->mac},
  497. {"seq", this->seq},
  498. {"time", time},
  499. {"result", status},
  500. {"userId", info->szUserID},
  501. {"userName", info->szCardName},
  502. {"method", method}
  503. };
  504. dataUpload(gConfFaceRemote, data, imgBuf, bufSize);
  505. }
  506. void Device::onTrafficJunctionEvent(DEV_EVENT_TRAFFICJUNCTION_INFO *info, BYTE *imgBuf, DWORD bufSize) {
  507. char time[32] = {0}, speed[4] = {0}, status[2] = {info->byOpenStrobeState > 1 ? '1' : '0', 0};
  508. sprintf(speed, "%d", info->nSpeed);
  509. sprintf(
  510. time, "%d-%02d-%02d %02d:%02d:%02d", info->UTC.dwYear, info->UTC.dwMonth,
  511. info->UTC.dwDay, info->UTC.dwHour, info->UTC.dwMinute, info->UTC.dwSecond
  512. );
  513. std::string cno(info->stTrafficCar.szPlateNumber), username, cid;
  514. if (!cno.empty()) {
  515. Plate *plate = getPlateByCNo(cno);
  516. if (plate != nullptr) {
  517. username = plate->name;
  518. cid = plate->cid_s;
  519. }
  520. }
  521. Log(
  522. Info,
  523. R"({"mac":"%s","seq":"%s","time":"%s","plateNumber":"%s","username":"%s","cid":"%s","plateType":"%s","plateColor":"%s","carType":"%s","carSubType":"%s","carColor":"%s","speed":"%s","result":"%s"})",
  524. this->mac.c_str(), this->seq.c_str(), time, info->stTrafficCar.szPlateNumber,
  525. username.c_str(), cid.c_str(), info->stTrafficCar.szPlateType, info->stTrafficCar.szPlateColor,
  526. info->stuVehicle.szText, info->stuVehicle.szObjectSubType, info->stTrafficCar.szVehicleColor,
  527. speed, status
  528. );
  529. // imageSave("./car.jpg", imgBuf, bufSize);
  530. std::map<std::string, std::string> data{
  531. {"mac", this->mac},
  532. {"seq", this->seq},
  533. {"time", time},
  534. {"plateNumber", info->stTrafficCar.szPlateNumber},
  535. {"username", username},
  536. {"cid", cid},
  537. {"plateType", info->stTrafficCar.szPlateType},
  538. {"plateColor", info->stTrafficCar.szPlateColor},
  539. {"carType", info->stuVehicle.szText},
  540. {"carSubType", info->stuVehicle.szObjectSubType},
  541. {"carColor", info->stTrafficCar.szVehicleColor},
  542. {"speed", speed},
  543. {"result", status},
  544. };
  545. dataUpload(gConfCarRemote, data, imgBuf, bufSize);
  546. }
  547. std::string Device::getJsonStr() {
  548. /* 1: online: 1 -> true, 0 -> false
  549. * 37: {"mac":"","seq":"","ip":"","online":}
  550. * */
  551. size_t size = mac.size() + seq.size() + ip.size() + 38;
  552. std::string res(size, 0);
  553. sprintf(
  554. res.data(), R"({"mac":"%s","seq":"%s","ip":"%s","online":%d})",
  555. mac.c_str(), seq.c_str(), ip.c_str(), online
  556. );
  557. return res;
  558. }
  559. bool Device::getFaceUsers(std::vector<std::string> &users, std::string &msg) {
  560. for (User &user : faceUserList) users.push_back(user.getJsonStr());
  561. return true;
  562. }
  563. bool Device::insertFaceUser(const User &user, std::string &msg) {
  564. if (varUserExists(user.uid)) {
  565. msg = "user existed already";
  566. return false;
  567. }
  568. NET_IN_ACCESS_USER_SERVICE_INSERT in;
  569. in.dwSize = sizeof in;
  570. in.nInfoNum = 1;
  571. auto *usr = new NET_ACCESS_USER_INFO;
  572. usr->bUserIDEx = 0;
  573. strcpy(usr->szUserID, user.uid.c_str());
  574. usr->bUseNameEx = 0;
  575. strcpy(usr->szName, user.name.c_str());
  576. strcpy(usr->szPsw, user.password.c_str());
  577. usr->emUserType = NET_ENUM_USER_TYPE_NORMAL;
  578. usr->nUserStatus = 0;
  579. usr->nDoorNum = 1, usr->nDoors[0] = 0;
  580. usr->nTimeSectionNum = 1, usr->nTimeSectionNo[0] = 255;
  581. usr->nSpecialDaysScheduleNum = 1, usr->nSpecialDaysSchedule[0] = 255;
  582. time_t tst = user.timestamp / 1000;
  583. struct tm *timeInfo = localtime(&tst);
  584. usr->stuValidEndTime.dwYear = timeInfo->tm_year + 1900;
  585. usr->stuValidEndTime.dwMonth = timeInfo->tm_mon + 1;
  586. usr->stuValidEndTime.dwDay = timeInfo->tm_mday;
  587. usr->stuValidEndTime.dwHour = timeInfo->tm_hour;
  588. usr->stuValidEndTime.dwMinute = timeInfo->tm_min;
  589. usr->stuValidEndTime.dwSecond = timeInfo->tm_sec;
  590. usr->stuValidBeginTime.dwYear = 2000;
  591. usr->stuValidBeginTime.dwMonth = 1;
  592. usr->stuValidBeginTime.dwDay = 1;
  593. usr->stuValidBeginTime.dwHour = 0;
  594. usr->stuValidBeginTime.dwMinute = 0;
  595. usr->stuValidBeginTime.dwSecond = 0;
  596. usr->nFirstEnterDoorsNum = 0;
  597. usr->emAuthority = NET_ATTENDANCE_AUTHORITY_CUSTOMER;
  598. usr->nFloorNum = 0;
  599. usr->nRoom = 0;
  600. usr->bFloorNoExValid = 0;
  601. usr->nFloorNumEx = 0;
  602. usr->bFloorNoEx2Valid = 0;
  603. usr->nUserTimeSectionsNum = 0;
  604. usr->bUserInfoExValid = 0;
  605. usr->bUserInfoEx2Valid = 0;
  606. in.pUserInfo = usr;
  607. NET_OUT_ACCESS_USER_SERVICE_INSERT out;
  608. out.dwSize = sizeof out;
  609. out.nMaxRetNum = 1;
  610. out.pFailCode = new NET_EM_FAILCODE;
  611. bool ok = true, res = CLIENT_OperateAccessUserService(
  612. loginId, NET_EM_ACCESS_CTL_USER_SERVICE_INSERT, &in, &out, gWaitTime
  613. );
  614. if (res) {
  615. res = addUserFace(user.uid, user.face, msg);
  616. if (res) varUserInsert(user);
  617. else {
  618. ok = false;
  619. removeUserOnly(user.uid, msg);
  620. }
  621. } else {
  622. ok = false;
  623. msg = "usr info insert failed";
  624. }
  625. delete usr;
  626. delete out.pFailCode;
  627. return ok;
  628. }
  629. bool Device::removeFaceUser(const std::string &uid, std::string &msg) {
  630. if (!varUserExists(uid)) {
  631. msg = "no such user";
  632. return false;
  633. }
  634. bool ok1 = removeUserFace(uid, msg), ok2 = removeUserOnly(uid, msg);
  635. return ok1 && ok2;
  636. }
  637. bool Device::getCarWoBList(const bool &isBlack, std::vector<std::string> &list, std::string &msg) {
  638. for (Plate &plate : isBlack ? carBlackList : carWhiteList) list.push_back(plate.getJsonStr());
  639. return true;
  640. }
  641. bool Device::insertCarWoBList(const bool &isBlack, std::vector<Plate> &list, std::string &msg) {
  642. json::Parser parser;
  643. json::Value result = parser.parse("[]");
  644. for (Plate &info : list) {
  645. json::Value one = parser.parse("{}");
  646. std::string reason;
  647. bool res = insertOneCarWoBList(isBlack, info, reason);
  648. one["cid"] = json::Value(info.cid);
  649. one["plate"] = json::Value(info.plate);
  650. one["success"] = json::Value(res);
  651. one["msg"] = json::Value(reason);
  652. result.push_back(one);
  653. }
  654. msg = result.str();
  655. return true;
  656. }
  657. bool Device::removeCarWoBList(const bool &isBlack, const std::vector<int> &cids, std::string &msg) {
  658. json::Parser parser;
  659. json::Value result = parser.parse("[]");
  660. for (const int &cid : cids) {
  661. json::Value one = parser.parse("{}");
  662. std::string reason;
  663. bool res = removeOneCarWoBList(isBlack, cid, reason);
  664. one["cid"] = json::Value(cid);
  665. one["success"] = json::Value(res);
  666. one["msg"] = json::Value(reason);
  667. result.push_back(one);
  668. }
  669. msg = result.str();
  670. return true;
  671. }
  672. }